tizen 2.4 release
[external/nghttp2.git] / src / asio_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 HTTP_SERVER2_CONNECTION_HPP
38 #define HTTP_SERVER2_CONNECTION_HPP
39
40 #include "nghttp2_config.h"
41
42 #include <memory>
43
44 #include <boost/asio.hpp>
45 #include <boost/noncopyable.hpp>
46 #include <boost/array.hpp>
47
48 #include <nghttp2/asio_http2.h>
49 #include "asio_http2_handler.h"
50 #include "util.h"
51
52 namespace nghttp2 {
53
54 namespace asio_http2 {
55
56 namespace server {
57
58 /// Represents a single connection from a client.
59 template <typename socket_type>
60 class connection : public std::enable_shared_from_this<connection<socket_type>>,
61                    private boost::noncopyable {
62 public:
63   /// Construct a connection with the given io_service.
64   template <typename... SocketArgs>
65   explicit connection(request_cb cb, boost::asio::io_service &task_io_service,
66                       SocketArgs &&... args)
67       : socket_(std::forward<SocketArgs>(args)...), request_cb_(std::move(cb)),
68         task_io_service_(task_io_service), writing_(false) {}
69
70   /// Start the first asynchronous operation for the connection.
71   void start() {
72     handler_ = std::make_shared<http2_handler>(
73         socket_.get_io_service(), task_io_service_, [this]() { do_write(); },
74         request_cb_);
75     if (handler_->start() != 0) {
76       return;
77     }
78     do_read();
79   }
80
81   socket_type &socket() { return socket_; }
82
83   void do_read() {
84     auto self = this->shared_from_this();
85
86     socket_.async_read_some(boost::asio::buffer(buffer_),
87                             [this, self](const boost::system::error_code &e,
88                                          std::size_t bytes_transferred) {
89       if (!e) {
90         if (handler_->on_read(buffer_, bytes_transferred) != 0) {
91           return;
92         }
93
94         do_write();
95
96         if (!writing_ && handler_->should_stop()) {
97           return;
98         }
99
100         do_read();
101       }
102
103       // If an error occurs then no new asynchronous operations are
104       // started. This means that all shared_ptr references to the
105       // connection object will disappear and the object will be
106       // destroyed automatically after this handler returns. The
107       // connection class's destructor closes the socket.
108     });
109   }
110
111   void do_write() {
112     auto self = this->shared_from_this();
113
114     if (writing_) {
115       return;
116     }
117
118     int rv;
119     std::size_t nwrite;
120
121     rv = handler_->on_write(outbuf_, nwrite);
122
123     if (rv != 0) {
124       return;
125     }
126
127     if (nwrite == 0) {
128       return;
129     }
130
131     writing_ = true;
132
133     boost::asio::async_write(
134         socket_, boost::asio::buffer(outbuf_, nwrite),
135         [this, self](const boost::system::error_code &e, std::size_t) {
136           if (!e) {
137             writing_ = false;
138
139             do_write();
140           }
141         });
142
143     // No new asynchronous operations are started. This means that all
144     // shared_ptr references to the connection object will disappear and
145     // the object will be destroyed automatically after this handler
146     // returns. The connection class's destructor closes the socket.
147   }
148
149 private:
150   socket_type socket_;
151
152   request_cb request_cb_;
153
154   boost::asio::io_service &task_io_service_;
155
156   std::shared_ptr<http2_handler> handler_;
157
158   /// Buffer for incoming data.
159   boost::array<uint8_t, 8192> buffer_;
160
161   boost::array<uint8_t, 16394> outbuf_;
162
163   bool writing_;
164 };
165
166 } // namespace server
167
168 } // namespace asio_http2
169
170 } // namespace nghttp2
171
172 #endif // HTTP_SERVER2_CONNECTION_HPP