18 const int HttpRequestParser::RECEIVE_START_ST;
19 const int HttpRequestParser::HTTP_METHOD_ST;
20 const int HttpRequestParser::HTTP_URI_ST;
21 const int HttpRequestParser::HTTP_VERSION_H_ST;
22 const int HttpRequestParser::HTTP_VERSION_T1_ST;
23 const int HttpRequestParser::HTTP_VERSION_T2_ST;
24 const int HttpRequestParser::HTTP_VERSION_P_ST;
25 const int HttpRequestParser::HTTP_VERSION_SLASH_ST;
26 const int HttpRequestParser::HTTP_VERSION_MAJOR_START_ST;
27 const int HttpRequestParser::HTTP_VERSION_MAJOR_ST;
28 const int HttpRequestParser::HTTP_VERSION_MINOR_START_ST;
29 const int HttpRequestParser::HTTP_VERSION_MINOR_ST;
30 const int HttpRequestParser::EXPECTING_NEW_LINE1_ST;
31 const int HttpRequestParser::HEADER_LINE_START_ST;
32 const int HttpRequestParser::HEADER_LWS_ST;
33 const int HttpRequestParser::HEADER_NAME_ST;
34 const int HttpRequestParser::SPACE_BEFORE_HEADER_VALUE_ST;
35 const int HttpRequestParser::HEADER_VALUE_ST;
36 const int HttpRequestParser::EXPECTING_NEW_LINE2_ST;
37 const int HttpRequestParser::EXPECTING_NEW_LINE3_ST;
38 const int HttpRequestParser::HTTP_BODY_ST;
42 context_(request_.context()) {
58 HttpRequestParser::defineStates() {
64 std::bind(&HttpRequestParser::receiveStartHandler,
this));
67 std::bind(&HttpRequestParser::httpMethodHandler,
this));
70 std::bind(&HttpRequestParser::uriHandler,
this));
73 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'H',
77 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'T',
81 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'T',
85 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'P',
89 std::bind(&HttpRequestParser::versionHTTPHandler,
this,
'/',
93 std::bind(&HttpRequestParser::versionNumberStartHandler,
this,
95 &context_->http_version_major_));
98 std::bind(&HttpRequestParser::versionNumberHandler,
this,
100 &context_->http_version_major_));
103 std::bind(&HttpRequestParser::versionNumberStartHandler,
this,
105 &context_->http_version_minor_));
108 std::bind(&HttpRequestParser::versionNumberHandler,
this,
110 &context_->http_version_minor_));
113 std::bind(&HttpRequestParser::expectingNewLineHandler,
this,
117 std::bind(&HttpRequestParser::headerLineStartHandler,
this));
120 std::bind(&HttpRequestParser::headerLwsHandler,
this));
123 std::bind(&HttpRequestParser::headerNameHandler,
this));
126 std::bind(&HttpRequestParser::spaceBeforeHeaderValueHandler,
this));
129 std::bind(&HttpRequestParser::headerValueHandler,
this));
132 std::bind(&HttpRequestParser::expectingNewLineHandler,
this,
136 std::bind(&HttpRequestParser::expectingNewLineHandler,
this,
140 std::bind(&HttpRequestParser::bodyHandler,
this));
144 HttpRequestParser::receiveStartHandler() {
153 parseFailure(
"invalid first character " + std::string(1, bytes[0]) +
154 " in HTTP method name");
157 context_->method_.push_back(bytes[0]);
169 HttpRequestParser::httpMethodHandler() {
178 " in HTTP method name");
183 context_->method_.push_back(c);
190 HttpRequestParser::uriHandler() {
196 }
else if (
isCtl(c)) {
202 context_->uri_.push_back(c);
209 HttpRequestParser::versionHTTPHandler(
const char expected_letter,
210 const unsigned int next_state) {
212 [
this, expected_letter, next_state](
const char c) {
214 if (c == expected_letter) {
219 context_->http_version_major_ = 0;
220 context_->http_version_minor_ = 0;
227 parseFailure(
"unexpected character " + std::string(1, c) +
228 " in HTTP version string");
234 HttpRequestParser::versionNumberStartHandler(
const unsigned int next_state,
235 unsigned int* storage) {
237 [
this, next_state, storage](
const char c)
mutable {
241 *storage = *storage * 10 + c -
'0';
252 HttpRequestParser::versionNumberHandler(
const char following_character,
253 const unsigned int next_state,
254 unsigned int*
const storage) {
256 [
this, following_character, next_state, storage](
const char c)
260 if (c == following_character) {
263 }
else if (isdigit(c)) {
265 *storage = *storage * 10 + c -
'0';
275 HttpRequestParser::expectingNewLineHandler(
const unsigned int next_state) {
291 uint64_t content_length =
293 if (content_length > 0) {
299 }
catch (
const std::exception& ex) {
324 HttpRequestParser::headerLineStartHandler() {
331 }
else if (!context_->headers_.empty() && ((c ==
' ') || (c ==
'\t'))) {
342 context_->headers_.push_back(HttpHeaderContext());
343 context_->headers_.back().name_.push_back(c);
350 HttpRequestParser::headerLwsHandler() {
357 }
else if ((c ==
' ') || (c ==
'\t')) {
362 }
else if (
isCtl(c)) {
363 parseFailure(
"control character found in the HTTP header " +
364 context_->headers_.back().name_);
368 context_->headers_.back().value_.push_back(c);
375 HttpRequestParser::headerNameHandler() {
383 " found in the HTTP header name");
387 context_->headers_.back().name_.push_back(c);
394 HttpRequestParser::spaceBeforeHeaderValueHandler() {
400 }
else if (c ==
'\r') {
405 }
else if (
isCtl(c)) {
406 parseFailure(
"control character found in the HTTP header "
407 + context_->headers_.back().name_);
411 context_->headers_.back().value_.push_back(c);
418 HttpRequestParser::headerValueHandler() {
425 }
else if (
isCtl(c)) {
426 parseFailure(
"control character found in the HTTP header "
427 + context_->headers_.back().name_);
431 context_->headers_.back().value_.push_back(c);
438 HttpRequestParser::bodyHandler() {
442 context_->body_ += body;
444 if (context_->body_.length() < content_length) {
449 if (context_->body_.length() > content_length) {
450 context_->body_.resize(content_length);
void defineState(unsigned int value, const std::string &label, StateHandler handler, const StatePausing &state_pausing=STATE_PAUSE_NEVER)
Adds an state value and associated label to the set of states.
static const int HTTP_METHOD_ST
Parsing HTTP method, e.g. GET, POST etc.
static const int HTTP_VERSION_SLASH_ST
Parsing slash character in "HTTP/Y.X".
static const int HTTP_VERSION_T2_ST
Parsing second occurrence of "T" in "HTTP".
static const int HTTP_VERSION_H_ST
Parsing letter "H" of "HTTP".
static const int DATA_READ_OK_EVT
Chunk of data successfully read and parsed.
static const int HTTP_VERSION_MAJOR_START_ST
Starting to parse major HTTP version number.
static const int HEADER_VALUE_ST
Parsing header value.
virtual void defineStates()
Defines states of the parser.
static const int HTTP_VERSION_MINOR_ST
Parsing minor HTTP version number.
static const int RECEIVE_START_ST
State indicating a beginning of parsing.
static const int START_EVT
Event issued to start the model execution.
void setState(unsigned int state)
Sets the current state to the given state value.
static const int HTTP_PARSE_OK_ST
Parsing successfully completed.
unsigned int getCurrState() const
Fetches the model's current state.
bool isSpecial(const char c) const
Checks if specified value is a special character.
static const int HTTP_PARSE_OK_EVT
Parsing HTTP request successful.
void stateWithReadHandler(const std::string &handler_name, std::function< void(const char c)> after_read_logic)
Generic parser handler which reads a single byte of data and parses it using specified callback funct...
static const int HEADER_LWS_ST
Parsing LWS (Linear White Space), i.e.
static const int SPACE_BEFORE_HEADER_VALUE_ST
Parsing space before header value.
static const int HTTP_VERSION_MINOR_START_ST
Starting to parse minor HTTP version number.
static const int NEED_MORE_DATA_EVT
Unable to proceed with parsing until new data is provided.
void invalidEventError(const std::string &handler_name, const unsigned int event)
This method is called when invalid event occurred in a particular parser state.
bool isCtl(const char c) const
Checks if specified value is a control value.
void parseFailure(const std::string &error_msg)
Transition parser to failure state.
static const int EXPECTING_NEW_LINE2_ST
Expecting new line after parsing header value.
static const int EXPECTING_NEW_LINE3_ST
Expecting second new line marking end of HTTP headers.
bool isChar(const char c) const
Checks if specified value is a character.
Defines the logger used by the top-level component of kea-dhcp-ddns.
static const int HEADER_NAME_ST
Parsing header name.
void transition(unsigned int state, unsigned int event)
Sets up the model to transition into given state with a given event.
void getNextFromBuffer(std::string &bytes, const size_t limit=1)
Retrieves next bytes of data from the buffer.
virtual void create()
Commits information held in the context into the request.
static const int HEADER_LINE_START_ST
Starting to parse a header line.
static const int HTTP_URI_ST
Parsing URI.
Base class for the HTTP message parsers.
static const int HTTP_VERSION_P_ST
Parsing letter "P" in "HTTP".
Represents HTTP request message.
void initDictionaries()
Initializes the event and state dictionaries.
static const int HTTP_VERSION_T1_ST
Parsing first occurrence of "T" in "HTTP".
unsigned int getNextEvent() const
Fetches the model's next event.
static const int HTTP_VERSION_MAJOR_ST
Parsing major HTTP version number.
static const int EXPECTING_NEW_LINE1_ST
Parsing first new line (after HTTP version number).
uint64_t getHeaderValueAsUint64(const std::string &header_name) const
Returns a value of the specified HTTP header as number.
void initModel()
Initialize the state model for parsing.
static const int HTTP_BODY_ST
Parsing body of a HTTP message.
void postNextEvent(unsigned int event)
Sets the next event to the given event value.
void stateWithMultiReadHandler(const std::string &handler_name, std::function< void(const std::string &)> after_read_logic)
Generic parser handler which reads multiple bytes of data and parses it using specified callback func...
bool requiresBody() const
Checks if the body is required for the HTTP message.