11#include " server/connection.hpp"
22#include " server/request_handler.hpp"
3+ #include " server/request_parser.hpp"
34
45#include < boost/algorithm/string/predicate.hpp>
56#include < boost/bind.hpp>
67#include < boost/iostreams/filter/gzip.hpp>
78#include < boost/iostreams/filtering_stream.hpp>
9+
810#include < vector>
911
1012namespace osrm
1113{
1214namespace server
1315{
1416
15- namespace
16- {
17- const size_t CHUNK_SIZE = 8192 ;
18-
19- } // namespace
2017Connection::Connection (boost::asio::io_context &io_context, RequestHandler &handler)
2118 : 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)
2320{
24- http_request_parser->header_limit (std::numeric_limits<std::uint32_t >::max ());
2521}
2622
2723boost::asio::ip::tcp::socket &Connection::socket () { return TCP_socket; }
2824
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-
4925// / Start the first asynchronous operation for the connection.
5026void Connection::start ()
5127{
@@ -65,8 +41,7 @@ void Connection::start()
6541 }
6642}
6743
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)
7045{
7146 if (error)
7247 {
@@ -85,48 +60,20 @@ void Connection::handle_read(const boost::system::error_code &error,
8560 timer.expires_from_now (boost::posix_time::seconds (0 ));
8661 }
8762
88- boost::beast::error_code ec;
89- http_request_parser->put (boost::asio::buffer (incoming_data_buffer), ec);
9063 // no error detected, let's parse the request
9164 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)
12073 {
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);
12674
12775 boost::system::error_code ec;
12876 current_request.endpoint = TCP_socket.remote_endpoint (ec).address ();
129-
13077 if (ec)
13178 {
13279 util::Log (logDEBUG) << " Socket remote endpoint error: " << ec.message ();
@@ -180,6 +127,25 @@ void Connection::handle_read(const boost::system::error_code &error,
180127 this ->shared_from_this (),
181128 boost::asio::placeholders::error));
182129 }
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+ }
183149}
184150
185151// / Handle completion of a write operation.
@@ -192,9 +158,8 @@ void Connection::handle_write(const boost::system::error_code &error)
192158 --processed_requests;
193159 current_request = http::request ();
194160 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 >();
198163 output_buffer.clear ();
199164 this ->start ();
200165 }
@@ -255,15 +220,5 @@ std::vector<char> Connection::compress_buffers(const std::vector<char> &uncompre
255220
256221 return compressed_data;
257222}
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-
268223} // namespace server
269224} // namespace osrm
0 commit comments