Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit3f106d1

Browse files
committed
More fleshing out of HTTP Async Connection
This commit actually builds in Clang, but doesn't do much (yet). Whatstill needs to be done is to: - Implement the writing of the status, status message, version, and header information especially when a write is first scheduled. - Implement a means for the handler to read asynchronously from the connection provided. - Write up a fairly complex example of how to use the asynchronous HTTP server-side handlerMore work has to be done in regard to testing with GCC 4.4 and 4.5 asfar as builds are concerned.
1 parent36eb5a7 commit3f106d1

File tree

7 files changed

+195
-25
lines changed

7 files changed

+195
-25
lines changed

‎boost/network/protocol/http/header.hpp‎

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,17 @@
1414
#defineHTTP_SERVER3_HEADER_HPP
1515

1616
#include<boost/network/traits/string.hpp>
17+
#include<boost/fusion/adapted/struct/adapt_struct.hpp>
18+
#include<boost/fusion/include/adapt_struct.hpp>
19+
#include<boost/assign/list_of.hpp>
1720

1821
namespaceboost {namespacenetwork {namespacehttp {
1922

2023
template<classTag>
2124
structrequest_header
2225
{
2326
typedeftypename string<Tag>::type string_type;
24-
string_type name;
25-
std::string value;
27+
string_type name, value;
2628
};
2729

2830
template<classTag>
@@ -37,4 +39,11 @@ namespace boost { namespace network { namespace http {
3739

3840
}// namespace boost
3941

42+
BOOST_FUSION_ADAPT_TPL_STRUCT(
43+
(Tag),
44+
(boost::network::http::request_header)(Tag),
45+
(typename boost::network::string<Tag>::type, name)
46+
(typename boost::network::string<Tag>::type, value)
47+
)
48+
4049
#endif// HTTP_SERVER3_HEADER_HPP

‎boost/network/protocol/http/request_parser.hpp‎

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,6 @@ class basic_request_parser
9797
} state_;
9898
};
9999

100-
typedef basic_request_parser<tags::http_server> request_parser;
101-
102100
}// namespace http
103101

104102
}// namespace network

‎boost/network/protocol/http/server/async_connection.hpp‎

Lines changed: 164 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include<boost/asio/strand.hpp>
1919
#include<boost/asio/buffer.hpp>
2020
#include<boost/make_shared.hpp>
21+
#include<boost/network/protocol/http/server/request_parser.hpp>
22+
#include<boost/range/iterator_range.hpp>
23+
#include<boost/spirit/include/qi.hpp>
2124
#include<list>
2225
#include<vector>
2326
#include<iterator>
@@ -37,7 +40,6 @@ namespace boost { namespace network { namespace http {
3740

3841
template<classTag,classHandler>
3942
structasync_connection : boost::enable_shared_from_this<async_connection<Tag,Handler> > {
40-
static std::size_tconst connection_buffer_size = BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE;
4143

4244
enumstatus_t {
4345
ok =200
@@ -61,6 +63,7 @@ namespace boost { namespace network { namespace http {
6163
};
6264

6365
typedeftypename string<Tag>::type string_type;
66+
typedef basic_request<Tag> request;
6467

6568
async_connection(
6669
asio::io_service & io_service
@@ -73,7 +76,9 @@ namespace boost { namespace network { namespace http {
7376
, thread_pool_(thread_pool)
7477
, headers_already_sent(false)
7578
, headers_buffer(BOOST_NETWORK_HTTP_SERVER_CONNECTION_HEADER_BUFFER_MAX_SIZE)
76-
{}
79+
{
80+
new_start = read_buffer_.begin();
81+
}
7782

7883
/** Function: template <class Range> set_headers(Range headers)
7984
* Precondition: headers have not been sent yet
@@ -146,22 +151,26 @@ namespace boost { namespace network { namespace http {
146151
// TODO implement a sane default here, for now ignore the error
147152
}
148153

154+
typedef boost::array<char, BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE> buffer_type;
155+
typedef boost::array<char, BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE> array;
156+
typedef std::list<shared_ptr<array> > array_list;
157+
typedef boost::shared_ptr<array_list> shared_array_list;
158+
typedef boost::shared_ptr<std::vector<asio::const_buffer> > shared_buffers;
159+
typedef request_parser<Tag> request_parser_type;
160+
149161
asio::ip::tcp::socket socket_;
150162
asio::io_service::strand strand;
151163
Handler & handler;
152164
utils::thread_pool & thread_pool_;
153165
bool headers_already_sent;
154166
asio::streambuf headers_buffer;
155167

156-
typedef boost::array<char, connection_buffer_size>
157-
buffer_type;
158-
typedef boost::array<char, connection_buffer_size>
159-
array;
160-
typedef std::list<shared_ptr<array> > array_list;
161-
typedef boost::shared_ptr<array_list> shared_array_list;
162-
typedef boost::shared_ptr<std::vector<asio::const_buffer> > shared_buffers;
163168
buffer_type read_buffer_;
164169
boost::uint16_t status;
170+
request_parser_type parser;
171+
request request_;
172+
buffer_type::iterator new_start;
173+
string_type partial_parsed;
165174

166175
template<class,class>friendstructasync_server_base;
167176

@@ -170,24 +179,166 @@ namespace boost { namespace network { namespace http {
170179
};
171180

172181
voidstart() {
182+
read_more(method);
183+
}
184+
185+
voidread_more(state_t state) {
173186
socket_.async_read_some(
174187
asio::buffer(read_buffer_)
175188
, strand.wrap(
176189
boost::bind(
177190
&async_connection<Tag,Handler>::handle_read_data,
178191
async_connection<Tag,Handler>::shared_from_this(),
179-
method,
192+
state,
180193
boost::asio::placeholders::error,
181194
boost::asio::placeholders::bytes_transferred
182195
)
183196
)
184197
);
185198
}
186199

187-
voidhandle_read_data(state_t, boost::system::error_codeconst & ec, std::size_t bytes_transferred) {
188-
// FIXME -- damn all that work got wiped out because Jeni tripped on the power. :(
200+
voidhandle_read_data(state_t state, boost::system::error_codeconst & ec, std::size_t bytes_transferred) {
201+
if (!ec) {
202+
logic::tribool parsed_ok;
203+
iterator_range<buffer_type::iterator> result_range, input_range;
204+
switch (state) {
205+
case method:
206+
input_range =boost::make_iterator_range(
207+
new_start, read_buffer_.end());
208+
fusion::tie(parsed_ok, result_range) = parser.parse_until(
209+
request_parser_type::method_done, input_range);
210+
if (!parsed_ok) {
211+
client_error();
212+
break;
213+
}elseif (parsed_ok ==true) {
214+
swap(partial_parsed, request_.method);
215+
request_.method.append(
216+
boost::begin(result_range),
217+
boost::end(result_range));
218+
trim(request_.method);
219+
new_start =boost::end(result_range);
220+
}else {
221+
partial_parsed.append(
222+
boost::begin(result_range),
223+
boost::end(result_range));
224+
new_start = read_buffer_.begin();
225+
read_more(method);
226+
break;
227+
}
228+
case uri:
229+
input_range =boost::make_iterator_range(
230+
new_start, read_buffer_.end());
231+
fusion::tie(parsed_ok, result_range) = parser.parse_until(
232+
request_parser_type::uri_done,
233+
input_range);
234+
if (!parsed_ok) {
235+
client_error();
236+
break;
237+
}elseif (parsed_ok ==true) {
238+
swap(partial_parsed, request_.destination);
239+
request_.destination.append(
240+
boost::begin(result_range),
241+
boost::end(result_range));
242+
trim(request_.destination);
243+
new_start =boost::end(result_range);
244+
}else {
245+
partial_parsed.append(
246+
boost::begin(result_range),
247+
boost::end(result_range));
248+
new_start = read_buffer_.begin();
249+
read_more(uri);
250+
break;
251+
}
252+
case version:
253+
input_range =boost::make_iterator_range(
254+
new_start, read_buffer_.end());
255+
fusion::tie(parsed_ok, result_range) = parser.parse_until(
256+
request_parser_type::version_done,
257+
input_range);
258+
if (!parsed_ok) {
259+
client_error();
260+
break;
261+
}elseif (parsed_ok ==true) {
262+
fusion::tuple<uint8_t,uint8_t> version_pair;
263+
usingnamespaceboost::spirit::qi;
264+
partial_parsed.append(boost::begin(result_range),boost::end(result_range));
265+
parse(
266+
partial_parsed.begin(), partial_parsed.end(),
267+
(
268+
lit("HTTP/")
269+
>> ushort_
270+
>>'.'
271+
>> ushort_
272+
)
273+
, version_pair);
274+
request_.http_version_major = fusion::get<0>(version_pair);
275+
request_.http_version_minor = fusion::get<1>(version_pair);
276+
new_start =boost::end(result_range);
277+
}else {
278+
partial_parsed.append(
279+
boost::begin(result_range),
280+
boost::end(result_range));
281+
new_start = read_buffer_.begin();
282+
read_more(version);
283+
break;
284+
}
285+
case headers:
286+
input_range =boost::make_iterator_range(
287+
new_start, read_buffer_.end());
288+
fusion::tie(parsed_ok, result_range) = parser.parse_until(
289+
request_parser_type::headers_done,
290+
input_range);
291+
if (!parsed_ok) {
292+
client_error();
293+
break;
294+
}elseif (parsed_ok ==true) {
295+
partial_parsed.append(
296+
boost::begin(result_range),
297+
boost::end(result_range));
298+
trim(partial_parsed);
299+
parse_headers(partial_parsed, request_.headers);
300+
new_start =boost::end(result_range);
301+
thread_pool().post(
302+
boost::bind(
303+
&Handler::operator(),
304+
handler,
305+
cref(request_),
306+
async_connection<Tag,Handler>::shared_from_this()));
307+
return;
308+
}else {
309+
partial_parsed.append(
310+
boost::begin(result_range),
311+
boost::end(result_range));
312+
new_start = read_buffer_.begin();
313+
read_more(headers);
314+
break;
315+
}
316+
default:
317+
BOOST_ASSERT(false &&"This is a bug, report to the cpp-netlib devel mailing list!");
318+
std::abort();
319+
}
320+
}
321+
// TODO log the error
189322
}
190323

324+
voidclient_error() {
325+
//FIXME write out a client request error
326+
}
327+
328+
voidparse_headers(string_type & input,typename request::headers_container_type & container) {
329+
usingnamespaceboost::spirit::qi;
330+
std::vector<fusion::tuple<std::string,std::string> > headers;
331+
parse(
332+
input.begin(), input.end(),
333+
*(
334+
+(alnum|(punct-':'))
335+
>>lit(":")
336+
>> +(alnum|space|punct)
337+
>>lit("\r\n")
338+
)
339+
, headers
340+
);
341+
}
191342
template<classRange,classCallback>
192343
voidwrite_headers(Range range, Callback callback) {
193344
// TODO send out the headers, then once that's done
@@ -236,6 +387,7 @@ namespace boost { namespace network { namespace http {
236387
// on doing I/O.
237388
//
238389

390+
static std::size_tconst connection_buffer_size = BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE;
239391
shared_array_list temporaries =
240392
boost::make_shared<array_list>();
241393
shared_buffers buffers =

‎boost/network/protocol/http/server/async_server.hpp‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ namespace boost { namespace network { namespace http {
1616
structasync_server_base {
1717
typedef basic_request<Tag> request;
1818
typedef basic_response<Tag> response;
19-
typedef async_connection<Tag, Handler> connection;
2019
typedef response_header<Tag> response_header;
2120
typedeftypename string<Tag>::type string_type;
21+
typedef async_connection<Tag,Handler> connection;
22+
typedef shared_ptr<connection> connection_ptr;
2223

2324
async_server_base(string_typeconst & address
2425
, string_typeconst & port
@@ -62,7 +63,7 @@ namespace boost { namespace network { namespace http {
6263
asio::io_service io_service;
6364
asio::ip::tcp::acceptor acceptor;
6465
bool stopping;
65-
boost::shared_ptr<async_connection<Tag,Handler> > new_connection;
66+
connection_ptr new_connection;
6667

6768
voidhandle_accept(boost::system::error_codeconst & ec) {
6869
if (!ec) {

‎boost/network/protocol/http/server/header.hpp‎

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
// http://www.boost.org/LICENSE_1_0.txt)
88

99
#include<boost/network/traits/string.hpp>
10+
#include<boost/fusion/adapted/struct/adapt_struct.hpp>
11+
#include<boost/fusion/include/adapt_struct.hpp>
12+
#include<boost/assign/list_of.hpp>
1013
#include<algorithm>
1114

1215
namespaceboost {namespacenetwork {namespacehttp {
@@ -17,7 +20,6 @@ namespace boost { namespace network { namespace http {
1720
string_type name, value;
1821
};
1922

20-
2123
template<classTag>
2224
voidswap(response_header<Tag> & l, response_header<Tag> & r) {
2325
std::swap(l.name, r.name);
@@ -30,4 +32,11 @@ namespace boost { namespace network { namespace http {
3032

3133
}/* boost*/
3234

35+
BOOST_FUSION_ADAPT_TPL_STRUCT(
36+
(Tag),
37+
(boost::network::http::response_header) (Tag),
38+
(typename boost::network::string<Tag>::type, name)
39+
(typename boost::network::string<Tag>::type, value)
40+
)
41+
3342
#endif/* BOOST_NETWORK_PROTOCOL_HTTP_SERVER_HEADER_HPP_20101027*/

‎boost/network/protocol/http/server/sync_connection.hpp‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,7 @@ namespace boost { namespace network { namespace http {
260260

261261
typedef boost::array<char,BOOST_NETWORK_HTTP_SERVER_CONNECTION_BUFFER_SIZE> buffer_type;
262262
buffer_type buffer_;
263+
typedef basic_request_parser<Tag> request_parser;
263264
request_parser parser_;
264265
basic_request<Tag> request_;
265266
basic_response<Tag> response_;

‎libs/network/test/http_async_server.cpp‎

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,18 @@ struct async_hello_world;
1717
typedef http::async_server<async_hello_world> server;
1818

1919
structasync_hello_world {
20-
voidoperator()(server::requestconst & request, server::connection & connection) {
20+
voidoperator()(server::requestconst & request, server::connection_ptr connection) {
2121
server::response_header headers[] = {
2222
{"Connection","close"}
2323
, {"Content-Type","text/plain"}
2424
};
25-
connection.set_headers(boost::make_iterator_range(headers, headers+2));
25+
connection->set_headers(boost::make_iterator_range(headers, headers+2));
2626
if (request.method !="GET") {
27-
connection.set_status(server::connection::not_supported);
28-
connection.write("Unsupported method.");
27+
connection->set_status(server::connection::not_supported);
28+
connection->write("Unsupported method.");
2929
}else {
30-
connection.set_status(server::connection::ok);
31-
connection.write("Hello, World!");
30+
connection->set_status(server::connection::ok);
31+
connection->write("Hello, World!");
3232
}
3333
}
3434
};

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp