Imported Upstream version 1.0.0
[platform/upstream/nghttp2.git] / src / asio_server_connection.h
1 /*
2  * nghttp2 - HTTP/2 C Library
3  *
4  * Copyright (c) 2014 Tatsuhiro Tsujikawa
5  *
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:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
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.
24  */
25 // We wrote this code based on the original code which has the
26 // following license:
27 //
28 // connection.hpp
29 // ~~~~~~~~~~~~~~
30 //
31 // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com)
32 //
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)
35 //
36
37 #ifndef ASIO_SERVER_CONNECTION_H
38 #define ASIO_SERVER_CONNECTION_H
39
40 #include "nghttp2_config.h"
41
42 #include <memory>
43
44 #include <boost/noncopyable.hpp>
45 #include <boost/array.hpp>
46
47 #include <nghttp2/asio_http2_server.h>
48
49 #include "asio_server_http2_handler.h"
50 #include "asio_server_serve_mux.h"
51 #include "util.h"
52
53 namespace nghttp2 {
54
55 namespace asio_http2 {
56
57 namespace server {
58
59 /// Represents a single connection from a client.
60 template <typename socket_type>
61 class connection : public std::enable_shared_from_this<connection<socket_type>>,
62                    private boost::noncopyable {
63 public:
64   /// Construct a connection with the given io_service.
65   template <typename... SocketArgs>
66   explicit connection(serve_mux &mux, SocketArgs &&... args)
67       : socket_(std::forward<SocketArgs>(args)...), mux_(mux), writing_(false) {
68   }
69
70   /// Start the first asynchronous operation for the connection.
71   void start() {
72     handler_ = std::make_shared<http2_handler>(socket_.get_io_service(),
73                                                [this]() { do_write(); }, mux_);
74     if (handler_->start() != 0) {
75       return;
76     }
77     do_read();
78   }
79
80   socket_type &socket() { return socket_; }
81
82   void do_read() {
83     auto self = this->shared_from_this();
84
85     socket_.async_read_some(boost::asio::buffer(buffer_),
86                             [this, self](const boost::system::error_code &e,
87                                          std::size_t bytes_transferred) {
88       if (!e) {
89         if (handler_->on_read(buffer_, bytes_transferred) != 0) {
90           return;
91         }
92
93         do_write();
94
95         if (!writing_ && handler_->should_stop()) {
96           return;
97         }
98
99         do_read();
100       }
101
102       // If an error occurs then no new asynchronous operations are
103       // started. This means that all shared_ptr references to the
104       // connection object will disappear and the object will be
105       // destroyed automatically after this handler returns. The
106       // connection class's destructor closes the socket.
107     });
108   }
109
110   void do_write() {
111     auto self = this->shared_from_this();
112
113     if (writing_) {
114       return;
115     }
116
117     int rv;
118     std::size_t nwrite;
119
120     rv = handler_->on_write(outbuf_, nwrite);
121
122     if (rv != 0) {
123       return;
124     }
125
126     if (nwrite == 0) {
127       return;
128     }
129
130     writing_ = true;
131
132     boost::asio::async_write(
133         socket_, boost::asio::buffer(outbuf_, nwrite),
134         [this, self](const boost::system::error_code &e, std::size_t) {
135           if (!e) {
136             writing_ = false;
137
138             do_write();
139           }
140         });
141
142     // No new asynchronous operations are started. This means that all
143     // shared_ptr references to the connection object will disappear and
144     // the object will be destroyed automatically after this handler
145     // returns. The connection class's destructor closes the socket.
146   }
147
148 private:
149   socket_type socket_;
150
151   serve_mux &mux_;
152
153   std::shared_ptr<http2_handler> handler_;
154
155   /// Buffer for incoming data.
156   boost::array<uint8_t, 8192> buffer_;
157
158   boost::array<uint8_t, 65536> outbuf_;
159
160   bool writing_;
161 };
162
163 } // namespace server
164
165 } // namespace asio_http2
166
167 } // namespace nghttp2
168
169 #endif // ASIO_SERVER_CONNECTION_H