17 const int HttpResponseParser::RECEIVE_START_ST;
18 const int HttpResponseParser::HTTP_VERSION_H_ST;
19 const int HttpResponseParser::HTTP_VERSION_T1_ST;
20 const int HttpResponseParser::HTTP_VERSION_T2_ST;
21 const int HttpResponseParser::HTTP_VERSION_P_ST;
22 const int HttpResponseParser::HTTP_VERSION_SLASH_ST;
23 const int HttpResponseParser::HTTP_VERSION_MAJOR_START_ST;
24 const int HttpResponseParser::HTTP_VERSION_MAJOR_ST;
25 const int HttpResponseParser::HTTP_VERSION_MINOR_START_ST;
26 const int HttpResponseParser::HTTP_VERSION_MINOR_ST;
27 const int HttpResponseParser::HTTP_STATUS_CODE_START_ST;
28 const int HttpResponseParser::HTTP_STATUS_CODE_ST;
29 const int HttpResponseParser::HTTP_PHRASE_START_ST;
30 const int HttpResponseParser::HTTP_PHRASE_ST;
31 const int HttpResponseParser::EXPECTING_NEW_LINE1_ST;
32 const int HttpResponseParser::HEADER_LINE_START_ST;
33 const int HttpResponseParser::HEADER_LWS_ST;
34 const int HttpResponseParser::HEADER_NAME_ST;
35 const int HttpResponseParser::SPACE_BEFORE_HEADER_VALUE_ST;
36 const int HttpResponseParser::HEADER_VALUE_ST;
37 const int HttpResponseParser::EXPECTING_NEW_LINE2_ST;
38 const int HttpResponseParser::EXPECTING_NEW_LINE3_ST;
39 const int HttpResponseParser::HTTP_BODY_ST;
43 context_(response.context()) {
59 HttpResponseParser::defineStates() {
65 std::bind(&HttpResponseParser::receiveStartHandler,
this));
68 std::bind(&HttpResponseParser::versionHTTPHandler,
this,
'T',
72 std::bind(&HttpResponseParser::versionHTTPHandler,
this,
'T',
76 std::bind(&HttpResponseParser::versionHTTPHandler,
this,
'P',
80 std::bind(&HttpResponseParser::versionHTTPHandler,
this,
'/',
84 std::bind(&HttpResponseParser::numberStartHandler,
this,
87 &context_->http_version_major_));
90 std::bind(&HttpResponseParser::numberHandler,
this,
93 &context_->http_version_major_));
96 std::bind(&HttpResponseParser::numberStartHandler,
this,
99 &context_->http_version_minor_));
102 std::bind(&HttpResponseParser::numberHandler,
this,
105 &context_->http_version_minor_));
108 std::bind(&HttpResponseParser::numberStartHandler,
this,
111 &context_->status_code_));
114 std::bind(&HttpResponseParser::numberHandler,
this,
117 &context_->status_code_));
120 std::bind(&HttpResponseParser::phraseStartHandler,
this));
123 std::bind(&HttpResponseParser::phraseHandler,
this));
126 std::bind(&HttpResponseParser::expectingNewLineHandler,
this,
130 std::bind(&HttpResponseParser::headerLineStartHandler,
this));
133 std::bind(&HttpResponseParser::headerLwsHandler,
this));
136 std::bind(&HttpResponseParser::headerNameHandler,
this));
139 std::bind(&HttpResponseParser::spaceBeforeHeaderValueHandler,
this));
142 std::bind(&HttpResponseParser::headerValueHandler,
this));
145 std::bind(&HttpResponseParser::expectingNewLineHandler,
this,
149 std::bind(&HttpResponseParser::expectingNewLineHandler,
this,
153 std::bind(&HttpResponseParser::bodyHandler,
this));
157 HttpResponseParser::receiveStartHandler() {
163 if (bytes[0] ==
'H') {
167 parseFailure(
"unexpected first character " + std::string(1, bytes[0]) +
179 HttpResponseParser::versionHTTPHandler(
const char expected_letter,
180 const unsigned int next_state) {
182 [
this, expected_letter, next_state](
const char c) {
184 if (c == expected_letter) {
189 context_->http_version_major_ = 0;
190 context_->http_version_minor_ = 0;
197 parseFailure(
"unexpected character " + std::string(1, c) +
198 " in HTTP version string");
204 HttpResponseParser::numberStartHandler(
const unsigned int next_state,
205 const std::string& number_name,
206 unsigned int* storage) {
208 [
this, next_state, number_name, storage](
const char c)
mutable {
212 *storage = *storage * 10 + c -
'0';
216 parseFailure(
"expected digit in " + number_name +
", found " +
223 HttpResponseParser::numberHandler(
const char following_character,
224 const unsigned int next_state,
225 const std::string& number_name,
226 unsigned int*
const storage) {
228 [
this, following_character, number_name, next_state, storage](
const char c)
232 if (c == following_character) {
235 }
else if (isdigit(c)) {
237 *storage = *storage * 10 + c -
'0';
240 parseFailure(
"expected digit in " + number_name +
", found " +
247 HttpResponseParser::phraseStartHandler() {
250 parseFailure(
"invalid first character " + std::string(1, c) +
253 context_->phrase_.push_back(c);
260 HttpResponseParser::phraseHandler() {
270 context_->phrase_.push_back(c);
277 HttpResponseParser::expectingNewLineHandler(
const unsigned int next_state) {
293 uint64_t content_length =
295 if (content_length > 0) {
301 }
catch (
const std::exception& ex) {
326 HttpResponseParser::headerLineStartHandler() {
333 }
else if (!context_->headers_.empty() && ((c ==
' ') || (c ==
'\t'))) {
344 context_->headers_.push_back(HttpHeaderContext());
345 context_->headers_.back().name_.push_back(c);
352 HttpResponseParser::headerLwsHandler() {
359 }
else if ((c ==
' ') || (c ==
'\t')) {
364 }
else if (
isCtl(c)) {
365 parseFailure(
"control character found in the HTTP header " +
366 context_->headers_.back().name_);
370 context_->headers_.back().value_.push_back(c);
377 HttpResponseParser::headerNameHandler() {
385 " found in the HTTP header name");
389 context_->headers_.back().name_.push_back(c);
396 HttpResponseParser::spaceBeforeHeaderValueHandler() {
402 }
else if (c ==
'\r') {
407 }
else if (
isCtl(c)) {
408 parseFailure(
"control character found in the HTTP header "
409 + context_->headers_.back().name_);
413 context_->headers_.back().value_.push_back(c);
420 HttpResponseParser::headerValueHandler() {
427 }
else if (
isCtl(c)) {
428 parseFailure(
"control character found in the HTTP header "
429 + context_->headers_.back().name_);
433 context_->headers_.back().value_.push_back(c);
440 HttpResponseParser::bodyHandler() {
444 context_->body_ += body;
446 if (context_->body_.length() < content_length) {
451 if (context_->body_.length() > content_length) {
452 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 DATA_READ_OK_EVT
Chunk of data successfully read and parsed.
virtual void defineStates()
Defines states of the parser.
static const int HTTP_PHRASE_ST
Parsing HTTP status phrase.
static const int START_EVT
Event issued to start the model execution.
static const int SPACE_BEFORE_HEADER_VALUE_ST
Parsing space before header value.
void setState(unsigned int state)
Sets the current state to the given state value.
static const int HEADER_NAME_ST
Parsing header name.
static const int HTTP_PARSE_OK_ST
Parsing successfully completed.
static const int HTTP_VERSION_SLASH_ST
Parsing slash character in "HTTP/Y.X".
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.
virtual void create()
Commits information held in the context into the response.
static const int HTTP_VERSION_MAJOR_START_ST
Starting to parse major HTTP version number.
static const int HTTP_VERSION_MAJOR_ST
Parsing major HTTP version number.
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...
Represents HTTP response message.
static const int NEED_MORE_DATA_EVT
Unable to proceed with parsing until new data is provided.
static const int HTTP_VERSION_T2_ST
Parsing second occurrence of "T" in "HTTP".
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 HEADER_LWS_ST
Parsing LWS (Linear White Space), i.e.
static const int HTTP_VERSION_MINOR_ST
Parsing minor HTTP version number.
static const int HTTP_STATUS_CODE_ST
Parsing HTTP status code.
bool isChar(const char c) const
Checks if specified value is a character.
static const int EXPECTING_NEW_LINE1_ST
Parsing first new line (after HTTP status phrase).
static const int HTTP_PHRASE_START_ST
Starting to parse HTTP status phrase.
Defines the logger used by the top-level component of kea-dhcp-ddns.
static const int HEADER_VALUE_ST
Parsing header value.
static const int RECEIVE_START_ST
State indicating a beginning of parsing.
void transition(unsigned int state, unsigned int event)
Sets up the model to transition into given state with a given event.
static const int EXPECTING_NEW_LINE3_ST
Expecting second new line marking end of HTTP headers.
void getNextFromBuffer(std::string &bytes, const size_t limit=1)
Retrieves next bytes of data from the buffer.
static const int HTTP_VERSION_P_ST
Parsing letter "P" in "HTTP".
Base class for the HTTP message parsers.
static const int HTTP_STATUS_CODE_START_ST
Starting to parse HTTP status code.
void initDictionaries()
Initializes the event and state dictionaries.
void initModel()
Initialize the state model for parsing.
static const int HEADER_LINE_START_ST
unsigned int getNextEvent() const
Fetches the model's next event.
uint64_t getHeaderValueAsUint64(const std::string &header_name) const
Returns a value of the specified HTTP header as number.
static const int HTTP_BODY_ST
Parsing body of a HTTP message.
static const int EXPECTING_NEW_LINE2_ST
Expecting new line after parsing header value.
static const int HTTP_VERSION_T1_ST
Parsing first occurrence of "T" in "HTTP".
void postNextEvent(unsigned int event)
Sets the next event to the given event value.
static const int HTTP_VERSION_MINOR_START_ST
Starting to parse minor HTTP version number.
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.