diff --git a/client_http.hpp b/client_http.hpp index 3e5a128..fcc47dd 100644 --- a/client_http.hpp +++ b/client_http.hpp @@ -501,7 +501,7 @@ namespace SimpleWeb { auto content_length = stoull(header_it->second); if(content_length > num_additional_bytes) { session->connection->set_timeout(); - asio::async_read(*session->connection->socket, session->response->streambuf, asio::transfer_exactly(content_length - num_additional_bytes), [this, session](const error_code &ec, std::size_t /*bytes_transferred*/) { + asio::async_read(*session->connection->socket, session->response->streambuf, asio::transfer_exactly(content_length - num_additional_bytes), [session](const error_code &ec, std::size_t /*bytes_transferred*/) { session->connection->cancel_timeout(); auto lock = session->connection->handler_runner->continue_lock(); if(!lock) @@ -526,7 +526,7 @@ namespace SimpleWeb { } else if(session->response->http_version < "1.1" || ((header_it = session->response->header.find("Session")) != session->response->header.end() && header_it->second == "close")) { session->connection->set_timeout(); - asio::async_read(*session->connection->socket, session->response->streambuf, [this, session](const error_code &ec, std::size_t /*bytes_transferred*/) { + asio::async_read(*session->connection->socket, session->response->streambuf, [session](const error_code &ec, std::size_t /*bytes_transferred*/) { session->connection->cancel_timeout(); auto lock = session->connection->handler_runner->continue_lock(); if(!lock) diff --git a/server_http.hpp b/server_http.hpp index c5389e9..e282bcb 100644 --- a/server_http.hpp +++ b/server_http.hpp @@ -286,7 +286,7 @@ namespace SimpleWeb { Config(unsigned short port) noexcept : port(port) {} public: - /// Port number to use. Defaults to 80 for HTTP and 443 for HTTPS. + /// Port number to use. Defaults to 80 for HTTP and 443 for HTTPS. Set to 0 get an assigned port. unsigned short port; /// If io_service is not set, number of threads that the server will use when start() is called. /// Defaults to 1 thread. @@ -332,35 +332,43 @@ namespace SimpleWeb { /// If you have your own asio::io_service, store its pointer here before running start(). std::shared_ptr io_service; - virtual unsigned short bindAndPrepare() { - if(!io_service) { - io_service = std::make_shared(); - internal_io_service = true; - } - - if(io_service->stopped()) - io_service->reset(); - + /// If you know the server port in advance, use start() instead. + /// Returns assigned port. If io_service is not set, an internal io_service is created instead. + /// Call before accept_and_run(). + unsigned short bind() { asio::ip::tcp::endpoint endpoint; if(config.address.size() > 0) endpoint = asio::ip::tcp::endpoint(asio::ip::address::from_string(config.address), config.port); else endpoint = asio::ip::tcp::endpoint(asio::ip::tcp::v4(), config.port); + if(!io_service) { + io_service = std::make_shared(); + internal_io_service = true; + } + if(!acceptor) acceptor = std::unique_ptr(new asio::ip::tcp::acceptor(*io_service)); acceptor->open(endpoint.protocol()); acceptor->set_option(asio::socket_base::reuse_address(config.reuse_address)); acceptor->bind(endpoint); - acceptor->listen(); - accept(); + after_bind(); return acceptor->local_endpoint().port(); } - virtual void runServer() { + /// If you know the server port in advance, use start() instead. + /// Accept requests, and if io_service was not set before calling bind(), run the internal io_service instead. + /// Call after bind(). + void accept_and_run() { + acceptor->listen(); + accept(); + if(internal_io_service) { + if(io_service->stopped()) + io_service->reset(); + // If thread_pool_size>1, start m_io_service.run() in (thread_pool_size-1) threads for thread-pooling threads.clear(); for(std::size_t c = 1; c < config.thread_pool_size; c++) { @@ -379,9 +387,10 @@ namespace SimpleWeb { } } - virtual void start() { - bindAndPrepare(); - runServer(); + /// Start the server by calling bind() and accept_and_run() + void start() { + bind(); + accept_and_run(); } /// Stop accepting new requests, and close current connections. @@ -420,6 +429,7 @@ namespace SimpleWeb { ServerBase(unsigned short port) noexcept : config(port), connections(new std::unordered_set()), connections_mutex(new std::mutex()), handler_runner(new ScopeRunner()) {} + virtual void after_bind() {} virtual void accept() = 0; template diff --git a/server_https.hpp b/server_https.hpp index 4840b82..0746f4f 100644 --- a/server_https.hpp +++ b/server_https.hpp @@ -17,7 +17,6 @@ namespace SimpleWeb { template <> class Server : public ServerBase { - std::string session_id_context; bool set_session_id_context = false; public: @@ -33,20 +32,19 @@ namespace SimpleWeb { } } - void start() override { + protected: + asio::ssl::context context; + + void after_bind() override { if(set_session_id_context) { // Creating session_id_context from address:port but reversed due to small SSL_MAX_SSL_SESSION_ID_LENGTH - session_id_context = std::to_string(config.port) + ':'; + auto session_id_context = std::to_string(acceptor->local_endpoint().port()) + ':'; session_id_context.append(config.address.rbegin(), config.address.rend()); SSL_CTX_set_session_id_context(context.native_handle(), reinterpret_cast(session_id_context.data()), std::min(session_id_context.size(), SSL_MAX_SSL_SESSION_ID_LENGTH)); } - ServerBase::start(); } - protected: - asio::ssl::context context; - void accept() override { auto connection = create_connection(*io_service, context);