2 * nghttp2 - HTTP/2 C Library
4 * Copyright (c) 2014 Tatsuhiro Tsujikawa
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sublicense, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
14 * The above copyright notice and this permission notice shall be
15 * included in all copies or substantial portions of the Software.
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 // We wrote this code based on the original code which has the
31 // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
33 // Distributed under the Boost Software License, Version 1.0. (See accompanying
34 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
37 #include "asio_server.h"
39 #include "asio_server_connection.h"
43 namespace asio_http2 {
46 server::server(std::size_t io_service_pool_size)
47 : io_service_pool_(io_service_pool_size) {}
49 boost::system::error_code
50 server::listen_and_serve(boost::system::error_code &ec,
51 boost::asio::ssl::context *tls_context,
52 const std::string &address, const std::string &port,
53 int backlog, serve_mux &mux, bool asynchronous) {
56 if (bind_and_listen(ec, address, port, backlog)) {
60 for (auto &acceptor : acceptors_) {
62 start_accept(*tls_context, acceptor, mux);
64 start_accept(acceptor, mux);
68 io_service_pool_.run(asynchronous);
73 boost::system::error_code server::bind_and_listen(boost::system::error_code &ec,
74 const std::string &address,
75 const std::string &port,
77 // Open the acceptor with the option to reuse the address (i.e.
79 tcp::resolver resolver(io_service_pool_.get_io_service());
80 tcp::resolver::query query(address, port);
81 auto it = resolver.resolve(query, ec);
86 for (; it != tcp::resolver::iterator(); ++it) {
87 tcp::endpoint endpoint = *it;
88 auto acceptor = tcp::acceptor(io_service_pool_.get_io_service());
90 if (acceptor.open(endpoint.protocol(), ec)) {
94 acceptor.set_option(tcp::acceptor::reuse_address(true));
96 if (acceptor.bind(endpoint, ec)) {
101 backlog == -1 ? boost::asio::socket_base::max_connections : backlog,
106 acceptors_.push_back(std::move(acceptor));
109 if (acceptors_.empty()) {
113 // ec could have some errors since we may have failed to bind some
120 void server::start_accept(boost::asio::ssl::context &tls_context,
121 tcp::acceptor &acceptor, serve_mux &mux) {
122 auto new_connection = std::make_shared<connection<ssl_socket>>(
123 mux, io_service_pool_.get_io_service(), tls_context);
125 acceptor.async_accept(new_connection->socket().lowest_layer(),
126 [this, &tls_context, &acceptor, &mux, new_connection](
127 const boost::system::error_code &e) {
129 new_connection->socket().lowest_layer().set_option(tcp::no_delay(true));
130 new_connection->socket().async_handshake(
131 boost::asio::ssl::stream_base::server,
132 [new_connection](const boost::system::error_code &e) {
134 new_connection->start();
139 start_accept(tls_context, acceptor, mux);
143 void server::start_accept(tcp::acceptor &acceptor, serve_mux &mux) {
144 auto new_connection = std::make_shared<connection<tcp::socket>>(
145 mux, io_service_pool_.get_io_service());
147 acceptor.async_accept(new_connection->socket(),
148 [this, &acceptor, &mux, new_connection](
149 const boost::system::error_code &e) {
151 new_connection->socket().set_option(tcp::no_delay(true));
152 new_connection->start();
155 start_accept(acceptor, mux);
159 void server::stop() { io_service_pool_.stop(); }
161 void server::join() { io_service_pool_.join(); }
163 } // namespace server
164 } // namespace asio_http2
165 } // namespace nghttp2