diff --git a/CMakeLists.txt b/CMakeLists.txt index 4899a06..51735b8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,8 @@ set(LT_AGE 0) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) include(Version) +set(CMAKE_CXX_STANDARD 11) + math(EXPR LT_SOVERSION "${LT_CURRENT} - ${LT_AGE}") set(LT_VERSION "${LT_SOVERSION}.${LT_AGE}.${LT_REVISION}") set(PACKAGE_VERSION "${PROJECT_VERSION}") diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index ee8f87d..34e9d77 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -36,35 +36,57 @@ set(NGHTTP2_ASIO_SOURCES asio_client_tls_context.cc ) -add_library(nghttp2_asio SHARED - ${NGHTTP2_ASIO_SOURCES} - $ -) -target_include_directories(nghttp2_asio PRIVATE - "${CMAKE_CURRENT_SOURCE_DIR}/includes" - "${CMAKE_CURRENT_SOURCE_DIR}/../third-party" +if (NOT ENABLE_SHARED_LIB AND NOT ENABLE_STATIC_LIB) + if (BUILD_SHARED_LIBS) + set(ENABLE_SHARED_LIB ON) + else() + set(ENABLE_STATIC_LIB ON) + endif() +endif() - ${LIBNGHTTP2_INCLUDE_DIRS} - ${OPENSSL_INCLUDE_DIRS} - ${Boost_INCLUDE_DIRS} +# Object lib used for both static and shared lib +add_library(nghttp2_asio_object OBJECT ${NGHTTP2_ASIO_SOURCES}) +target_include_directories(nghttp2_asio_object + PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/includes" + "${CMAKE_CURRENT_SOURCE_DIR}/../third-party" + ${LIBNGHTTP2_INCLUDE_DIRS} + ${OPENSSL_INCLUDE_DIRS} + ${Boost_INCLUDE_DIRS} + INTERFACE + "${CMAKE_CURRENT_BINARY_DIR}/../lib/includes" + "${CMAKE_CURRENT_SOURCE_DIR}/../lib/includes" + "${CMAKE_CURRENT_SOURCE_DIR}/includes" ) -target_include_directories(nghttp2_asio INTERFACE - "${CMAKE_CURRENT_BINARY_DIR}/../lib/includes" - "${CMAKE_CURRENT_SOURCE_DIR}/../lib/includes" - "${CMAKE_CURRENT_SOURCE_DIR}/includes" +target_link_libraries(nghttp2_asio_object + PRIVATE + ${LIBNGHTTP2_LIBRARIES} + ${OPENSSL_LIBRARIES} + PUBLIC + ${Boost_LIBRARIES} ) -target_link_libraries(nghttp2_asio - ${LIBNGHTTP2_LIBRARIES} - ${OPENSSL_LIBRARIES} - ${Boost_LIBRARIES} +set_target_properties(nghttp2_asio_object + PROPERTIES + VERSION ${LT_VERSION} + SOVERSION ${LT_SOVERSION} ) -set_target_properties(nghttp2_asio PROPERTIES - VERSION ${LT_VERSION} SOVERSION ${LT_SOVERSION}) -install(TARGETS nghttp2_asio - ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}" - LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}" - RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}") +# Public shared library +if(ENABLE_SHARED_LIB) + set_property(TARGET nghttp2_asio_object PROPERTY POSITION_INDEPENDENT_CODE 1) + target_compile_definitions(nghttp2_asio_object PUBLIC BUILDING_NGHTTP2_ASIO) + add_library(nghttp2_asio SHARED) + target_link_libraries(nghttp2_asio PUBLIC nghttp2_asio_object $) + install(TARGETS nghttp2_asio) +endif() + +# Static library +if(ENABLE_STATIC_LIB) + add_library(nghttp2_asio_static STATIC) + target_link_libraries(nghttp2_asio_static PUBLIC nghttp2_asio_object $) + set_target_properties(nghttp2_asio_static PROPERTIES ARCHIVE_OUTPUT_NAME nghttp2_asio${STATIC_LIB_SUFFIX}) + install(TARGETS nghttp2_asio_static) +endif() install(FILES "${CMAKE_CURRENT_BINARY_DIR}/libnghttp2_asio.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") diff --git a/lib/allocator.h b/lib/allocator.h index 97b9a41..b5eee6f 100644 --- a/lib/allocator.h +++ b/lib/allocator.h @@ -31,6 +31,7 @@ # include #endif // !_WIN32 +#include #include #include @@ -59,7 +60,8 @@ struct BlockAllocator { : retain(nullptr), head(nullptr), block_size(block_size), - isolation_threshold(std::min(block_size, isolation_threshold)) { + isolation_threshold(std::min(block_size, isolation_threshold)) + { assert(isolation_threshold <= block_size); } @@ -109,7 +111,7 @@ struct BlockAllocator { void *alloc(size_t size) { if (size + sizeof(size_t) >= isolation_threshold) { - auto len = std::max(static_cast(16), size); + auto len = std::max(static_cast(16), size); // We will store the allocated size in size_t field. auto mb = alloc_mem_block(len + sizeof(size_t)); auto sp = reinterpret_cast(mb->begin); @@ -158,7 +160,7 @@ struct BlockAllocator { return ptr; } - auto nalloclen = std::max(size + 1, alloclen * 2); + auto nalloclen = std::max(size + 1, alloclen * 2); auto res = alloc(nalloclen); std::copy_n(p, alloclen, static_cast(res)); diff --git a/lib/asio_common.cc b/lib/asio_common.cc index 428dbd6..91cc69f 100644 --- a/lib/asio_common.cc +++ b/lib/asio_common.cc @@ -27,6 +27,10 @@ #include #include +#ifdef _WIN32 +# include +#endif + #include "util.h" #include "template.h" #include "http2.h" @@ -80,7 +84,7 @@ generator_cb string_generator(std::string data) { return [strio](uint8_t *buf, size_t len, uint32_t *data_flags) { auto &data = strio->first; auto &left = strio->second; - auto n = std::min(len, left); + auto n = std::min(len, left); std::copy_n(data.c_str() + data.size() - left, n, buf); left -= n; if (left == 0) { @@ -102,8 +106,14 @@ std::shared_ptr> defer_shared(F &&f, T &&...t) { std::forward(t)...); } +#ifdef _WIN32 +# define FD_MAGIC(f) _##f +#else +# define FD_MAGIC(f) f +#endif + generator_cb file_generator(const std::string &path) { - auto fd = open(path.c_str(), O_RDONLY); + auto fd = FD_MAGIC(open)(path.c_str(), FD_MAGIC(O_RDONLY)); if (fd == -1) { return generator_cb(); } @@ -112,12 +122,12 @@ generator_cb file_generator(const std::string &path) { } generator_cb file_generator_from_fd(int fd) { - auto d = defer_shared(close, fd); + auto d = defer_shared(FD_MAGIC(close), fd); return [fd, d](uint8_t *buf, size_t len, uint32_t *data_flags) -> generator_cb::result_type { ssize_t n; - while ((n = read(fd, buf, len)) == -1 && errno == EINTR) + while ((n = FD_MAGIC(read)(fd, buf, len)) == -1 && errno == EINTR) ; if (n == -1) { diff --git a/lib/http2.cc b/lib/http2.cc index 28dbc49..305a62f 100644 --- a/lib/http2.cc +++ b/lib/http2.cc @@ -25,6 +25,8 @@ #include "http2.h" #include "util.h" +#include + namespace nghttp2 { namespace http2 { @@ -599,9 +601,9 @@ StringRef path_join(BlockAllocator &balloc, const StringRef &base_path, const StringRef &base_query, const StringRef &rel_path, const StringRef &rel_query) { auto res = make_byte_ref( - balloc, std::max(static_cast(1), base_path.size()) + + balloc, std::max(static_cast(1), base_path.size()) + rel_path.size() + 1 + - std::max(base_query.size(), rel_query.size()) + 1); + std::max(base_query.size(), rel_query.size()) + 1); auto p = res.base; if (rel_path.empty()) { diff --git a/lib/includes/nghttp2/asio_http2.h b/lib/includes/nghttp2/asio_http2.h index 57e55e1..72e6e55 100644 --- a/lib/includes/nghttp2/asio_http2.h +++ b/lib/includes/nghttp2/asio_http2.h @@ -38,11 +38,25 @@ #include +#ifndef __has_declspec_attribute +# define __has_declspec_attribute(x) false +#endif +#if defined(_WIN32) || \ + (__has_declspec_attribute(dllexport) && __has_declspec_attribute(dllimport)) +# ifdef BUILDING_NGHTTP2_ASIO +# define NGHTTP2_ASIO_EXPORT __declspec(dllexport) +# else +# define NGHTTP2_ASIO_EXPORT __declspec(dllimport) +# endif +#else +# define NGHTTP2_ASIO_EXPORT +#endif + namespace nghttp2 { namespace asio_http2 { -struct header_value { +struct NGHTTP2_ASIO_EXPORT header_value { // header field value std::string value; // true if the header field value is sensitive information, such as @@ -55,9 +69,9 @@ struct header_value { // header fields. The header field name must be lower-cased. using header_map = std::multimap; -const boost::system::error_category &nghttp2_category() noexcept; +NGHTTP2_ASIO_EXPORT const boost::system::error_category &nghttp2_category() noexcept; -struct uri_ref { +struct NGHTTP2_ASIO_EXPORT uri_ref { std::string scheme; std::string host; // form after percent-encoding decoded @@ -95,35 +109,36 @@ typedef std::function struct is_error_code_enum { +template <> struct NGHTTP2_ASIO_EXPORT is_error_code_enum { BOOST_STATIC_CONSTANT(bool, value = true); }; -template <> struct is_error_code_enum { +template <> struct NGHTTP2_ASIO_EXPORT is_error_code_enum { BOOST_STATIC_CONSTANT(bool, value = true); }; diff --git a/lib/includes/nghttp2/asio_http2_client.h b/lib/includes/nghttp2/asio_http2_client.h index 7257914..069c262 100644 --- a/lib/includes/nghttp2/asio_http2_client.h +++ b/lib/includes/nghttp2/asio_http2_client.h @@ -35,7 +35,7 @@ namespace client { class response_impl; -class response { +class NGHTTP2_ASIO_EXPORT response { public: // Application must not call this directly. response(); @@ -71,7 +71,7 @@ using connect_cb = class request_impl; -class request { +class NGHTTP2_ASIO_EXPORT request { public: // Application must not call this directly. request(); @@ -119,7 +119,7 @@ class request { }; // Wrapper around an nghttp2_priority_spec. -class priority_spec { +class NGHTTP2_ASIO_EXPORT priority_spec { public: // The default ctor is used only by sentinel values. priority_spec() = default; @@ -142,7 +142,7 @@ class priority_spec { class session_impl; -class session { +class NGHTTP2_ASIO_EXPORT session { public: // Starts HTTP/2 session by connecting to |host| and |service| // (e.g., "80") using clear text TCP connection with connect timeout @@ -239,6 +239,7 @@ class session { // configure |tls_ctx| for client use. Currently, we just set NPN // callback for HTTP/2. +NGHTTP2_ASIO_EXPORT boost::system::error_code configure_tls_context(boost::system::error_code &ec, boost::asio::ssl::context &tls_ctx); diff --git a/lib/includes/nghttp2/asio_http2_server.h b/lib/includes/nghttp2/asio_http2_server.h index 651af69..eb41dfe 100644 --- a/lib/includes/nghttp2/asio_http2_server.h +++ b/lib/includes/nghttp2/asio_http2_server.h @@ -36,7 +36,7 @@ namespace server { class request_impl; class response_impl; -class request { +class NGHTTP2_ASIO_EXPORT request { public: // Application must not call this directly. request(); @@ -66,7 +66,7 @@ class request { std::unique_ptr impl_; }; -class response { +class NGHTTP2_ASIO_EXPORT response { public: // Application must not call this directly. response(); @@ -130,7 +130,7 @@ typedef std::function request_cb; class http2_impl; -class http2 { +class NGHTTP2_ASIO_EXPORT http2 { public: http2(); ~http2(); @@ -224,17 +224,19 @@ class http2 { // Configures |tls_context| for server use. This function sets couple // of OpenSSL options (disables SSLv2 and SSLv3 and compression) and // enables ECDHE ciphers. NPN callback is also configured. +NGHTTP2_ASIO_EXPORT boost::system::error_code configure_tls_context_easy(boost::system::error_code &ec, boost::asio::ssl::context &tls_context); // Returns request handler to do redirect to |uri| using // |status_code|. The |uri| appears in "location" header field as is. +NGHTTP2_ASIO_EXPORT request_cb redirect_handler(int status_code, std::string uri); // Returns request handler to reply with given |status_code| and HTML // including message about status code. -request_cb status_handler(int status_code); +NGHTTP2_ASIO_EXPORT request_cb status_handler(int status_code); } // namespace server diff --git a/lib/util.cc b/lib/util.cc index ce634fd..3ec2e44 100644 --- a/lib/util.cc +++ b/lib/util.cc @@ -22,6 +22,12 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ + +// Avoid min / max macros on windows +#ifdef _WIN32 +# define NOMINMAX +#endif + #include "util.h" #ifdef HAVE_TIME_H @@ -173,7 +179,14 @@ std::string http_date(time_t t) { char *http_date(char *res, time_t t) { struct tm tms; - if (gmtime_r(&t, &tms) == nullptr) { + if ( +#ifndef _WIN32 + gmtime_r(&t, &tms) == nullptr +#else + // microsoft decided to reverse the arguments + gmtime_s(&tms, &t) +#endif + ) { return res; } diff --git a/lib/util.h b/lib/util.h index d980e7a..3032299 100644 --- a/lib/util.h +++ b/lib/util.h @@ -30,7 +30,6 @@ #ifdef HAVE_UNISTD_H # include #endif // HAVE_UNISTD_H -#include #ifdef HAVE_NETDB_H # include #endif // HAVE_NETDB_H