1
1
#include " server/connection.hpp"
2
2
#include " server/request_handler.hpp"
3
+ #include " server/request_parser.hpp"
3
4
4
5
#include < boost/algorithm/string/predicate.hpp>
5
6
#include < boost/bind.hpp>
6
7
#include < boost/iostreams/filter/gzip.hpp>
7
8
#include < boost/iostreams/filtering_stream.hpp>
9
+
8
10
#include < vector>
9
11
10
12
namespace osrm
11
13
{
12
14
namespace server
13
15
{
14
16
15
- namespace
16
- {
17
- const size_t CHUNK_SIZE = 8192 ;
18
-
19
- } // namespace
20
17
Connection::Connection (boost::asio::io_context &io_context, RequestHandler &handler)
21
18
: strand(boost::asio::make_strand(io_context)), TCP_socket(strand), timer(strand),
22
- request_handler (handler), http_request_parser(std::make_optional<RequestParser>())
19
+ request_handler (handler)
23
20
{
24
- http_request_parser->header_limit (std::numeric_limits<std::uint32_t >::max ());
25
21
}
26
22
27
23
boost::asio::ip::tcp::socket &Connection::socket () { return TCP_socket; }
28
24
29
- namespace
30
- {
31
-
32
- http::compression_type select_compression (const boost::beast::http::fields &fields)
33
- {
34
- const auto header_value = fields[boost::beast::http::field::accept_encoding];
35
- /* giving gzip precedence over deflate */
36
- if (boost::icontains (header_value, " gzip" ))
37
- {
38
- return http::gzip_rfc1952;
39
- }
40
- if (boost::icontains (header_value, " deflate" ))
41
- {
42
- return http::deflate_rfc1951;
43
- }
44
- return http::no_compression;
45
- }
46
-
47
- } // namespace
48
-
49
25
// / Start the first asynchronous operation for the connection.
50
26
void Connection::start ()
51
27
{
@@ -65,8 +41,7 @@ void Connection::start()
65
41
}
66
42
}
67
43
68
- void Connection::handle_read (const boost::system::error_code &error,
69
- std::size_t /* bytes_transferred*/ )
44
+ void Connection::handle_read (const boost::system::error_code &error, std::size_t bytes_transferred)
70
45
{
71
46
if (error)
72
47
{
@@ -85,48 +60,20 @@ void Connection::handle_read(const boost::system::error_code &error,
85
60
timer.expires_from_now (boost::posix_time::seconds (0 ));
86
61
}
87
62
88
- boost::beast::error_code ec;
89
- http_request_parser->put (boost::asio::buffer (incoming_data_buffer), ec);
90
63
// no error detected, let's parse the request
91
64
http::compression_type compression_type (http::no_compression);
92
-
93
- if (ec)
94
- {
95
- if (ec == boost::beast::http::error::need_more)
96
- {
97
- const auto current_size = incoming_data_buffer.size ();
98
- incoming_data_buffer.resize (incoming_data_buffer.size () + CHUNK_SIZE, 0 );
99
- // we don't have a result yet, so continue reading
100
- TCP_socket.async_read_some (
101
- boost::asio::buffer (incoming_data_buffer.data () + current_size, CHUNK_SIZE),
102
- boost::bind (&Connection::handle_read,
103
- this ->shared_from_this (),
104
- boost::asio::placeholders::error,
105
- boost::asio::placeholders::bytes_transferred));
106
- }
107
- else
108
- {
109
- // request is not parseable
110
- current_reply = http::reply::stock_reply (http::reply::bad_request);
111
-
112
- boost::asio::async_write (TCP_socket,
113
- current_reply.to_buffers (),
114
- boost::bind (&Connection::handle_write,
115
- this ->shared_from_this (),
116
- boost::asio::placeholders::error));
117
- }
118
- }
119
- else
65
+ RequestParser::RequestStatus result;
66
+ std::tie (result, compression_type) =
67
+ request_parser.parse (current_request,
68
+ incoming_data_buffer.data (),
69
+ incoming_data_buffer.data () + bytes_transferred);
70
+
71
+ // the request has been parsed
72
+ if (result == RequestParser::RequestStatus::valid)
120
73
{
121
- // the request has been parsed
122
- const auto &message = http_request_parser->get ();
123
- compression_type = select_compression (message);
124
-
125
- fill_request (message, current_request);
126
74
127
75
boost::system::error_code ec;
128
76
current_request.endpoint = TCP_socket.remote_endpoint (ec).address ();
129
-
130
77
if (ec)
131
78
{
132
79
util::Log (logDEBUG) << " Socket remote endpoint error: " << ec.message ();
@@ -180,6 +127,25 @@ void Connection::handle_read(const boost::system::error_code &error,
180
127
this ->shared_from_this (),
181
128
boost::asio::placeholders::error));
182
129
}
130
+ else if (result == RequestParser::RequestStatus::invalid)
131
+ { // request is not parseable
132
+ current_reply = http::reply::stock_reply (http::reply::bad_request);
133
+
134
+ boost::asio::async_write (TCP_socket,
135
+ current_reply.to_buffers (),
136
+ boost::bind (&Connection::handle_write,
137
+ this ->shared_from_this (),
138
+ boost::asio::placeholders::error));
139
+ }
140
+ else
141
+ {
142
+ // we don't have a result yet, so continue reading
143
+ TCP_socket.async_read_some (boost::asio::buffer (incoming_data_buffer),
144
+ boost::bind (&Connection::handle_read,
145
+ this ->shared_from_this (),
146
+ boost::asio::placeholders::error,
147
+ boost::asio::placeholders::bytes_transferred));
148
+ }
183
149
}
184
150
185
151
// / Handle completion of a write operation.
@@ -192,9 +158,8 @@ void Connection::handle_write(const boost::system::error_code &error)
192
158
--processed_requests;
193
159
current_request = http::request ();
194
160
current_reply = http::reply ();
195
- http_request_parser.emplace ();
196
- http_request_parser->header_limit (std::numeric_limits<std::uint32_t >::max ());
197
- incoming_data_buffer.resize (CHUNK_SIZE, 0 );
161
+ request_parser = RequestParser ();
162
+ incoming_data_buffer = boost::array<char , 8192 >();
198
163
output_buffer.clear ();
199
164
this ->start ();
200
165
}
@@ -255,15 +220,5 @@ std::vector<char> Connection::compress_buffers(const std::vector<char> &uncompre
255
220
256
221
return compressed_data;
257
222
}
258
-
259
- void Connection::fill_request (const RequestParser::value_type &http_message,
260
- http::request ¤t_request)
261
- {
262
- current_request.uri = http_message.target ().to_string ();
263
- current_request.agent = http_message[boost::beast::http::field::user_agent].to_string ();
264
- current_request.referrer = http_message[boost::beast::http::field::referer].to_string ();
265
- current_request.connection = http_message[boost::beast::http::field::connection].to_string ();
266
- }
267
-
268
223
} // namespace server
269
224
} // namespace osrm
0 commit comments