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 #ifndef ASIO_SERVER_CONNECTION_H
38 #define ASIO_SERVER_CONNECTION_H
40 #include "nghttp2_config.h"
44 #include <boost/noncopyable.hpp>
45 #include <boost/array.hpp>
47 #include <nghttp2/asio_http2_server.h>
49 #include "asio_server_http2_handler.h"
50 #include "asio_server_serve_mux.h"
54 #if BOOST_VERSION >= 107000
55 # define GET_IO_SERVICE(s) \
56 ((boost::asio::io_context &)(s).get_executor().context())
58 # define GET_IO_SERVICE(s) ((s).get_io_service())
63 namespace asio_http2 {
67 /// Represents a single connection from a client.
68 template <typename socket_type>
69 class connection : public std::enable_shared_from_this<connection<socket_type>>,
70 private boost::noncopyable {
72 /// Construct a connection with the given io_service.
73 template <typename... SocketArgs>
76 const boost::posix_time::time_duration &tls_handshake_timeout,
77 const boost::posix_time::time_duration &read_timeout,
78 SocketArgs &&... args)
79 : socket_(std::forward<SocketArgs>(args)...),
81 deadline_(GET_IO_SERVICE(socket_)),
82 tls_handshake_timeout_(tls_handshake_timeout),
83 read_timeout_(read_timeout),
87 /// Start the first asynchronous operation for the connection.
89 boost::system::error_code ec;
91 handler_ = std::make_shared<http2_handler>(
92 GET_IO_SERVICE(socket_), socket_.lowest_layer().remote_endpoint(ec),
93 [this]() { do_write(); }, mux_);
94 if (handler_->start() != 0) {
101 socket_type &socket() { return socket_; }
103 void start_tls_handshake_deadline() {
104 deadline_.expires_from_now(tls_handshake_timeout_);
105 deadline_.async_wait(
106 std::bind(&connection::handle_deadline, this->shared_from_this()));
109 void start_read_deadline() {
110 deadline_.expires_from_now(read_timeout_);
111 deadline_.async_wait(
112 std::bind(&connection::handle_deadline, this->shared_from_this()));
115 void handle_deadline() {
120 if (deadline_.expires_at() <=
121 boost::asio::deadline_timer::traits_type::now()) {
123 deadline_.expires_at(boost::posix_time::pos_infin);
127 deadline_.async_wait(
128 std::bind(&connection::handle_deadline, this->shared_from_this()));
132 auto self = this->shared_from_this();
134 deadline_.expires_from_now(read_timeout_);
136 socket_.async_read_some(
137 boost::asio::buffer(buffer_),
138 [this, self](const boost::system::error_code &e,
139 std::size_t bytes_transferred) {
145 if (handler_->on_read(buffer_, bytes_transferred) != 0) {
152 if (!writing_ && handler_->should_stop()) {
159 // If an error occurs then no new asynchronous operations are
160 // started. This means that all shared_ptr references to the
161 // connection object will disappear and the object will be
162 // destroyed automatically after this handler returns. The
163 // connection class's destructor closes the socket.
168 auto self = this->shared_from_this();
177 rv = handler_->on_write(outbuf_, nwrite);
185 if (handler_->should_stop()) {
193 // Reset read deadline here, because normally client is sending
194 // something, it does not expect timeout while doing it.
195 deadline_.expires_from_now(read_timeout_);
197 boost::asio::async_write(
198 socket_, boost::asio::buffer(outbuf_, nwrite),
199 [this, self](const boost::system::error_code &e, std::size_t) {
210 // No new asynchronous operations are started. This means that all
211 // shared_ptr references to the connection object will disappear and
212 // the object will be destroyed automatically after this handler
213 // returns. The connection class's destructor closes the socket.
222 boost::system::error_code ignored_ec;
223 socket_.lowest_layer().close(ignored_ec);
232 std::shared_ptr<http2_handler> handler_;
234 /// Buffer for incoming data.
235 boost::array<uint8_t, 8_k> buffer_;
237 boost::array<uint8_t, 64_k> outbuf_;
239 boost::asio::deadline_timer deadline_;
240 boost::posix_time::time_duration tls_handshake_timeout_;
241 boost::posix_time::time_duration read_timeout_;
247 } // namespace server
249 } // namespace asio_http2
251 } // namespace nghttp2
253 #endif // ASIO_SERVER_CONNECTION_H