move tribool obj into request_parser

This commit is contained in:
karenzshea 2016-01-28 18:43:19 -05:00 committed by Patrick Niklaus
parent efee07e20b
commit 262cdd7bc0
4 changed files with 80 additions and 93 deletions

View File

@ -3,7 +3,6 @@
#include "server/http/compression_type.hpp" #include "server/http/compression_type.hpp"
#include "server/http/header.hpp" #include "server/http/header.hpp"
#include "util/tribool.hpp"
#include <tuple> #include <tuple>
@ -22,11 +21,18 @@ class RequestParser
public: public:
RequestParser(); RequestParser();
std::tuple<util::tribool, http::compression_type> std::tuple<RequestStatus, http::compression_type>
parse(http::request &current_request, char *begin, char *end); parse(http::request &current_request, char *begin, char *end);
enum class RequestStatus : char
{
valid,
invalid,
indeterminate
};
private: private:
util::tribool consume(http::request &current_request, const char input); RequestStatus consume(http::request &current_request, const char input);
bool is_char(const int character) const; bool is_char(const int character) const;

View File

@ -1,17 +0,0 @@
#ifndef TRIBOOL_HPP
#define TRIBOOL_HPP
namespace osrm
{
namespace util
{
enum class tribool : char
{
yes,
no,
indeterminate
};
}
}
#endif // TRIBOOL_HPP

View File

@ -41,13 +41,13 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t
// no error detected, let's parse the request // no error detected, let's parse the request
http::compression_type compression_type(http::no_compression); http::compression_type compression_type(http::no_compression);
util::tribool result; RequestStatus result;
std::tie(result, compression_type) = std::tie(result, compression_type) =
request_parser.parse(current_request, incoming_data_buffer.data(), request_parser.parse(current_request, incoming_data_buffer.data(),
incoming_data_buffer.data() + bytes_transferred); incoming_data_buffer.data() + bytes_transferred);
// the request has been parsed // the request has been parsed
if (result == util::tribool::yes) if (result == RequestStatus::yes)
{ {
current_request.endpoint = TCP_socket.remote_endpoint().address(); current_request.endpoint = TCP_socket.remote_endpoint().address();
request_handler.handle_request(current_request, current_reply); request_handler.handle_request(current_request, current_reply);
@ -85,7 +85,7 @@ void Connection::handle_read(const boost::system::error_code &error, std::size_t
strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(), strand.wrap(boost::bind(&Connection::handle_write, this->shared_from_this(),
boost::asio::placeholders::error))); boost::asio::placeholders::error)));
} }
else if (result == util::tribool::no) else if (result == RequestStatus::no)
{ // request is not parseable { // request is not parseable
current_reply = http::reply::stock_reply(http::reply::bad_request); current_reply = http::reply::stock_reply(http::reply::bad_request);

View File

@ -4,8 +4,6 @@
#include "server/http/header.hpp" #include "server/http/header.hpp"
#include "server/http/request.hpp" #include "server/http/request.hpp"
#include "util/tribool.hpp"
#include <boost/algorithm/string/predicate.hpp> #include <boost/algorithm/string/predicate.hpp>
#include <string> #include <string>
@ -21,177 +19,177 @@ RequestParser::RequestParser()
{ {
} }
std::tuple<util::tribool, http::compression_type> std::tuple<RequestStatus, http::compression_type>
RequestParser::parse(http::request &current_request, char *begin, char *end) RequestParser::parse(http::request &current_request, char *begin, char *end)
{ {
while (begin != end) while (begin != end)
{ {
util::tribool result = consume(current_request, *begin++); RequestStatus result = consume(current_request, *begin++);
if (result != util::tribool::indeterminate) if (result != RequestStatus::indeterminate)
{ {
return std::make_tuple(result, selected_compression); return std::make_tuple(result, selected_compression);
} }
} }
util::tribool result = util::tribool::indeterminate; RequestStatus result = RequestStatus::indeterminate;
if (state == internal_state::post_request && content_length <= 0) if (state == internal_state::post_request && content_length <= 0)
{ {
result = util::tribool::yes; result = RequestStatus::valid;
} }
return std::make_tuple(result, selected_compression); return std::make_tuple(result, selected_compression);
} }
util::tribool RequestParser::consume(http::request &current_request, const char input) RequestStatus RequestParser::consume(http::request &current_request, const char input)
{ {
switch (state) switch (state)
{ {
case internal_state::method_start: case internal_state::method_start:
if (!is_char(input) || is_CTL(input) || is_special(input)) if (!is_char(input) || is_CTL(input) || is_special(input))
{ {
return util::tribool::no; return RequestStatus::invalid;
} }
if (input == 'P') if (input == 'P')
{ {
state = internal_state::post_O; state = internal_state::post_O;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
state = internal_state::method; state = internal_state::method;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
case internal_state::post_O: case internal_state::post_O:
if (input == 'O') if (input == 'O')
{ {
state = internal_state::post_S; state = internal_state::post_S;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::post_S: case internal_state::post_S:
if (input == 'S') if (input == 'S')
{ {
state = internal_state::post_T; state = internal_state::post_T;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::post_T: case internal_state::post_T:
if (input == 'T') if (input == 'T')
{ {
is_post_header = true; is_post_header = true;
state = internal_state::method; state = internal_state::method;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::post_request: case internal_state::post_request:
current_request.uri.push_back(input); current_request.uri.push_back(input);
--content_length; --content_length;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
case internal_state::method: case internal_state::method:
if (input == ' ') if (input == ' ')
{ {
state = internal_state::uri; state = internal_state::uri;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
if (!is_char(input) || is_CTL(input) || is_special(input)) if (!is_char(input) || is_CTL(input) || is_special(input))
{ {
return util::tribool::no; return RequestStatus::invalid;
} }
return util::tribool::indeterminate; return RequestStatus::indeterminate;
case internal_state::uri_start: case internal_state::uri_start:
if (is_CTL(input)) if (is_CTL(input))
{ {
return util::tribool::no; return RequestStatus::invalid;
} }
state = internal_state::uri; state = internal_state::uri;
current_request.uri.push_back(input); current_request.uri.push_back(input);
return util::tribool::indeterminate; return RequestStatus::indeterminate;
case internal_state::uri: case internal_state::uri:
if (input == ' ') if (input == ' ')
{ {
state = internal_state::http_version_h; state = internal_state::http_version_h;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
if (is_CTL(input)) if (is_CTL(input))
{ {
return util::tribool::no; return RequestStatus::invalid;
} }
current_request.uri.push_back(input); current_request.uri.push_back(input);
return util::tribool::indeterminate; return RequestStatus::indeterminate;
case internal_state::http_version_h: case internal_state::http_version_h:
if (input == 'H') if (input == 'H')
{ {
state = internal_state::http_version_t_1; state = internal_state::http_version_t_1;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::http_version_t_1: case internal_state::http_version_t_1:
if (input == 'T') if (input == 'T')
{ {
state = internal_state::http_version_t_2; state = internal_state::http_version_t_2;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::http_version_t_2: case internal_state::http_version_t_2:
if (input == 'T') if (input == 'T')
{ {
state = internal_state::http_version_p; state = internal_state::http_version_p;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::http_version_p: case internal_state::http_version_p:
if (input == 'P') if (input == 'P')
{ {
state = internal_state::http_version_slash; state = internal_state::http_version_slash;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::http_version_slash: case internal_state::http_version_slash:
if (input == '/') if (input == '/')
{ {
state = internal_state::http_version_major_start; state = internal_state::http_version_major_start;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::http_version_major_start: case internal_state::http_version_major_start:
if (is_digit(input)) if (is_digit(input))
{ {
state = internal_state::http_version_major; state = internal_state::http_version_major;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::http_version_major: case internal_state::http_version_major:
if (input == '.') if (input == '.')
{ {
state = internal_state::http_version_minor_start; state = internal_state::http_version_minor_start;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
if (is_digit(input)) if (is_digit(input))
{ {
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::http_version_minor_start: case internal_state::http_version_minor_start:
if (is_digit(input)) if (is_digit(input))
{ {
state = internal_state::http_version_minor; state = internal_state::http_version_minor;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::http_version_minor: case internal_state::http_version_minor:
if (input == '\r') if (input == '\r')
{ {
state = internal_state::expecting_newline_1; state = internal_state::expecting_newline_1;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
if (is_digit(input)) if (is_digit(input))
{ {
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::expecting_newline_1: case internal_state::expecting_newline_1:
if (input == '\n') if (input == '\n')
{ {
state = internal_state::header_line_start; state = internal_state::header_line_start;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::header_line_start: case internal_state::header_line_start:
if (boost::iequals(current_header.name, "Accept-Encoding")) if (boost::iequals(current_header.name, "Accept-Encoding"))
{ {
@ -230,77 +228,77 @@ util::tribool RequestParser::consume(http::request &current_request, const char
{ {
if (!boost::icontains(current_header.value, "application/x-www-form-urlencoded")) if (!boost::icontains(current_header.value, "application/x-www-form-urlencoded"))
{ {
return util::tribool::no; return RequestStatus::invalid;
} }
} }
if (input == '\r') if (input == '\r')
{ {
state = internal_state::expecting_newline_3; state = internal_state::expecting_newline_3;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
if (!is_char(input) || is_CTL(input) || is_special(input)) if (!is_char(input) || is_CTL(input) || is_special(input))
{ {
return util::tribool::no; return RequestStatus::invalid;
} }
state = internal_state::header_name; state = internal_state::header_name;
current_header.clear(); current_header.clear();
current_header.name.push_back(input); current_header.name.push_back(input);
return util::tribool::indeterminate; return RequestStatus::indeterminate;
case internal_state::header_lws: case internal_state::header_lws:
if (input == '\r') if (input == '\r')
{ {
state = internal_state::expecting_newline_2; state = internal_state::expecting_newline_2;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
if (input == ' ' || input == '\t') if (input == ' ' || input == '\t')
{ {
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
if (is_CTL(input)) if (is_CTL(input))
{ {
return util::tribool::no; return RequestStatus::invalid;
} }
state = internal_state::header_value; state = internal_state::header_value;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
case internal_state::header_name: case internal_state::header_name:
if (input == ':') if (input == ':')
{ {
state = internal_state::space_before_header_value; state = internal_state::space_before_header_value;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
if (!is_char(input) || is_CTL(input) || is_special(input)) if (!is_char(input) || is_CTL(input) || is_special(input))
{ {
return util::tribool::no; return RequestStatus::invalid;
} }
current_header.name.push_back(input); current_header.name.push_back(input);
return util::tribool::indeterminate; return RequestStatus::indeterminate;
case internal_state::space_before_header_value: case internal_state::space_before_header_value:
if (input == ' ') if (input == ' ')
{ {
state = internal_state::header_value; state = internal_state::header_value;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::header_value: case internal_state::header_value:
if (input == '\r') if (input == '\r')
{ {
state = internal_state::expecting_newline_2; state = internal_state::expecting_newline_2;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
if (is_CTL(input)) if (is_CTL(input))
{ {
return util::tribool::no; return RequestStatus::invalid;
} }
current_header.value.push_back(input); current_header.value.push_back(input);
return util::tribool::indeterminate; return RequestStatus::indeterminate;
case internal_state::expecting_newline_2: case internal_state::expecting_newline_2:
if (input == '\n') if (input == '\n')
{ {
state = internal_state::header_line_start; state = internal_state::header_line_start;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::no; return RequestStatus::invalid;
case internal_state::expecting_newline_3: case internal_state::expecting_newline_3:
if (input == '\n') if (input == '\n')
{ {
@ -311,13 +309,13 @@ util::tribool RequestParser::consume(http::request &current_request, const char
current_request.uri.push_back('?'); current_request.uri.push_back('?');
} }
state = internal_state::post_request; state = internal_state::post_request;
return util::tribool::indeterminate; return RequestStatus::indeterminate;
} }
return util::tribool::yes; return RequestStatus::valid;
} }
return util::tribool::no; return RequestStatus::invalid;
default: // should never be reached default: // should never be reached
return input == '\n' ? util::tribool::yes : util::tribool::no; return input == '\n' ? RequestStatus::valid : RequestStatus::invalid;
} }
} }