/usr/include/pion/http/parser.hpp is in libpion-dev 5.0.4+dfsg-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 | // ---------------------------------------------------------------------
// pion: a Boost C++ framework for building lightweight HTTP interfaces
// ---------------------------------------------------------------------
// Copyright (C) 2007-2012 Cloudmeter, Inc. (http://www.cloudmeter.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//
#ifndef __PION_HTTP_PARSER_HEADER__
#define __PION_HTTP_PARSER_HEADER__
#include <string>
#include <boost/noncopyable.hpp>
#include <boost/function/function2.hpp>
#include <boost/logic/tribool.hpp>
#include <boost/system/error_code.hpp>
#include <boost/thread/once.hpp>
#include <pion/config.hpp>
#include <pion/logger.hpp>
#include <pion/http/message.hpp>
#ifndef BOOST_SYSTEM_NOEXCEPT
#define BOOST_SYSTEM_NOEXCEPT BOOST_NOEXCEPT
#endif
namespace pion { // begin namespace pion
namespace http { // begin namespace http
// forward declarations used for finishing HTTP messages
class request;
class response;
///
/// parser: parses HTTP messages
///
class PION_API parser :
private boost::noncopyable
{
public:
/// maximum length for HTTP payload content
static const std::size_t DEFAULT_CONTENT_MAX;
/// callback type used to consume payload content
typedef boost::function2<void, const char *, std::size_t> payload_handler_t;
/// class-specific error code values
enum error_value_t {
ERROR_METHOD_CHAR = 1,
ERROR_METHOD_SIZE,
ERROR_URI_CHAR,
ERROR_URI_SIZE,
ERROR_QUERY_CHAR,
ERROR_QUERY_SIZE,
ERROR_VERSION_EMPTY,
ERROR_VERSION_CHAR,
ERROR_STATUS_EMPTY,
ERROR_STATUS_CHAR,
ERROR_HEADER_CHAR,
ERROR_HEADER_NAME_SIZE,
ERROR_HEADER_VALUE_SIZE,
ERROR_INVALID_CONTENT_LENGTH,
ERROR_CHUNK_CHAR,
ERROR_MISSING_CHUNK_DATA,
ERROR_MISSING_HEADER_DATA,
ERROR_MISSING_TOO_MUCH_CONTENT,
};
/// class-specific error category
class error_category_t
: public boost::system::error_category
{
public:
const char *name() const BOOST_SYSTEM_NOEXCEPT { return "parser"; }
std::string message(int ev) const {
switch (ev) {
case ERROR_METHOD_CHAR:
return "invalid method character";
case ERROR_METHOD_SIZE:
return "method exceeds maximum size";
case ERROR_URI_CHAR:
return "invalid URI character";
case ERROR_URI_SIZE:
return "method exceeds maximum size";
case ERROR_QUERY_CHAR:
return "invalid query string character";
case ERROR_QUERY_SIZE:
return "query string exceeds maximum size";
case ERROR_VERSION_EMPTY:
return "HTTP version undefined";
case ERROR_VERSION_CHAR:
return "invalid version character";
case ERROR_STATUS_EMPTY:
return "HTTP status undefined";
case ERROR_STATUS_CHAR:
return "invalid status character";
case ERROR_HEADER_CHAR:
return "invalid header character";
case ERROR_HEADER_NAME_SIZE:
return "header name exceeds maximum size";
case ERROR_HEADER_VALUE_SIZE:
return "header value exceeds maximum size";
case ERROR_INVALID_CONTENT_LENGTH:
return "invalid Content-Length header";
case ERROR_CHUNK_CHAR:
return "invalid chunk character";
case ERROR_MISSING_HEADER_DATA:
return "missing header data";
case ERROR_MISSING_CHUNK_DATA:
return "missing chunk data";
case ERROR_MISSING_TOO_MUCH_CONTENT:
return "missing too much content";
}
return "parser error";
}
};
/**
* creates new parser objects
*
* @param is_request if true, the message is parsed as an HTTP request;
* if false, the message is parsed as an HTTP response
* @param max_content_length maximum length for HTTP payload content
*/
parser(const bool is_request, std::size_t max_content_length = DEFAULT_CONTENT_MAX)
: m_logger(PION_GET_LOGGER("pion.http.parser")), m_is_request(is_request),
m_read_ptr(NULL), m_read_end_ptr(NULL), m_message_parse_state(PARSE_START),
m_headers_parse_state(is_request ? PARSE_METHOD_START : PARSE_HTTP_VERSION_H),
m_chunked_content_parse_state(PARSE_CHUNK_SIZE_START), m_status_code(0),
m_bytes_content_remaining(0), m_bytes_content_read(0),
m_bytes_last_read(0), m_bytes_total_read(0),
m_max_content_length(max_content_length),
m_parse_headers_only(false), m_save_raw_headers(false)
{}
/// default destructor
virtual ~parser() {}
/**
* parses an HTTP message including all payload content it might contain
*
* @param http_msg the HTTP message object to populate from parsing
* @param ec error_code contains additional information for parsing errors
*
* @return boost::tribool result of parsing:
* false = message has an error,
* true = finished parsing HTTP message,
* indeterminate = not yet finished parsing HTTP message
*/
boost::tribool parse(http::message& http_msg, boost::system::error_code& ec);
/**
* attempts to continue parsing despite having missed data (length is known but content is not)
*
* @param http_msg the HTTP message object to populate from parsing
* @param len the length in bytes of the missing data
* @param ec error_code contains additional information for parsing errors
*
* @return boost::tribool result of parsing:
* false = message has an error,
* true = finished parsing HTTP message,
* indeterminate = not yet finished parsing HTTP message
*/
boost::tribool parse_missing_data(http::message& http_msg, std::size_t len,
boost::system::error_code& ec);
/**
* finishes parsing an HTTP response message
*
* @param http_msg the HTTP message object to finish
*/
void finish(http::message& http_msg) const;
/**
* resets the location and size of the read buffer
*
* @param ptr pointer to the first bytes available to be read
* @param len number of bytes available to be read
*/
inline void set_read_buffer(const char *ptr, size_t len) {
m_read_ptr = ptr;
m_read_end_ptr = ptr + len;
}
/**
* loads a read position bookmark
*
* @param read_ptr points to the next character to be consumed in the read_buffer
* @param read_end_ptr points to the end of the read_buffer (last byte + 1)
*/
inline void load_read_pos(const char *&read_ptr, const char *&read_end_ptr) const {
read_ptr = m_read_ptr;
read_end_ptr = m_read_end_ptr;
}
/**
* checks to see if a premature EOF was encountered while parsing. This
* should be called if there is no more data to parse, and if the last
* call to the parse() function returned boost::indeterminate
*
* @param http_msg the HTTP message object being parsed
* @return true if premature EOF, false if message is OK & finished parsing
*/
inline bool check_premature_eof(http::message& http_msg) {
if (m_message_parse_state != PARSE_CONTENT_NO_LENGTH)
return true;
m_message_parse_state = PARSE_END;
http_msg.concatenate_chunks();
finish(http_msg);
return false;
}
/**
* controls headers-only parsing (default is disabled; content parsed also)
*
* @param b if true, then the parse() function returns true after headers
*/
inline void parse_headers_only(bool b = true) { m_parse_headers_only = b; }
/**
* skip parsing all headers and parse payload content only
*
* @param http_msg the HTTP message object being parsed
*/
inline void skip_header_parsing(http::message& http_msg) {
boost::system::error_code ec;
finish_header_parsing(http_msg, ec);
}
/// resets the parser to its initial state
inline void reset(void) {
m_message_parse_state = PARSE_START;
m_headers_parse_state = (m_is_request ? PARSE_METHOD_START : PARSE_HTTP_VERSION_H);
m_chunked_content_parse_state = PARSE_CHUNK_SIZE_START;
m_status_code = 0;
m_status_message.erase();
m_method.erase();
m_resource.erase();
m_query_string.erase();
m_raw_headers.erase();
m_bytes_content_read = m_bytes_last_read = m_bytes_total_read = 0;
}
/// returns true if there are no more bytes available in the read buffer
inline bool eof(void) const { return m_read_ptr == NULL || m_read_ptr >= m_read_end_ptr; }
/// returns the number of bytes available in the read buffer
inline std::size_t bytes_available(void) const { return (eof() ? 0 : (std::size_t)(m_read_end_ptr - m_read_ptr)); }
/// returns the number of bytes read during the last parse operation
inline std::size_t gcount(void) const { return m_bytes_last_read; }
/// returns the total number of bytes read while parsing the HTTP message
inline std::size_t get_total_bytes_read(void) const { return m_bytes_total_read; }
/// returns the total number of bytes read while parsing the payload content
inline std::size_t get_content_bytes_read(void) const { return m_bytes_content_read; }
/// returns the maximum length for HTTP payload content
inline std::size_t get_max_content_length(void) const { return m_max_content_length; }
/// returns the raw HTTP headers saved by the parser
inline const std::string& get_raw_headers(void) const { return m_raw_headers; }
/// returns true if the parser is saving raw HTTP header contents
inline bool get_save_raw_headers(void) const { return m_save_raw_headers; }
/// returns true if parsing headers only
inline bool get_parse_headers_only(void) { return m_parse_headers_only; }
/// returns true if the parser is being used to parse an HTTP request
inline bool is_parsing_request(void) const { return m_is_request; }
/// returns true if the parser is being used to parse an HTTP response
inline bool is_parsing_response(void) const { return ! m_is_request; }
/// defines a callback function to be used for consuming payload content
inline void set_payload_handler(payload_handler_t& h) { m_payload_handler = h; }
/// sets the maximum length for HTTP payload content
inline void set_max_content_length(std::size_t n) { m_max_content_length = n; }
/// resets the maximum length for HTTP payload content to the default value
inline void reset_max_content_length(void) { m_max_content_length = DEFAULT_CONTENT_MAX; }
/// sets parameter for saving raw HTTP header content
inline void set_save_raw_headers(bool b) { m_save_raw_headers = b; }
/// sets the logger to be used
inline void set_logger(logger log_ptr) { m_logger = log_ptr; }
/// returns the logger currently in use
inline logger get_logger(void) { return m_logger; }
/**
* parses a URI string
*
* @param uri the string to parse
* @param proto will be set to the protocol (i.e. "http")
* @param host will be set to the hostname (i.e. "www.cloudmeter.com")
* @param port host port number to use for connection (i.e. 80)
* @param path uri stem or file path
* @param query uri query string
*
* @return true if the URI was successfully parsed, false if there was an error
*/
static bool parse_uri(const std::string& uri, std::string& proto,
std::string& host, boost::uint16_t& port, std::string& path,
std::string& query);
/**
* parse key-value pairs out of a url-encoded string
* (i.e. this=that&a=value)
*
* @param dict dictionary for key-values pairs
* @param ptr points to the start of the encoded string
* @param len length of the encoded string, in bytes
*
* @return bool true if successful
*/
static bool parse_url_encoded(ihash_multimap& dict,
const char *ptr, const std::size_t len);
/**
* parse key-value pairs out of a multipart/form-data payload content
* (http://www.ietf.org/rfc/rfc2388.txt)
*
* @param dict dictionary for key-values pairs
* @param content_type value of the content-type HTTP header
* @param ptr points to the start of the encoded data
* @param len length of the encoded data, in bytes
*
* @return bool true if successful
*/
static bool parse_multipart_form_data(ihash_multimap& dict,
const std::string& content_type,
const char *ptr, const std::size_t len);
/**
* parse key-value pairs out of a "Cookie" request header
* (i.e. this=that; a=value)
*
* @param dict dictionary for key-values pairs
* @param ptr points to the start of the header string to be parsed
* @param len length of the encoded string, in bytes
* @param set_cookie_header set true if parsing Set-Cookie response header
*
* @return bool true if successful
*/
static bool parse_cookie_header(ihash_multimap& dict,
const char *ptr, const std::size_t len,
bool set_cookie_header);
/**
* parse key-value pairs out of a "Cookie" request header
* (i.e. this=that; a=value)
*
* @param dict dictionary for key-values pairs
* @param cookie_header header string to be parsed
* @param set_cookie_header set true if parsing Set-Cookie response header
*
* @return bool true if successful
*/
static inline bool parse_cookie_header(ihash_multimap& dict,
const std::string& cookie_header, bool set_cookie_header)
{
return parse_cookie_header(dict, cookie_header.c_str(), cookie_header.size(), set_cookie_header);
}
/**
* parse key-value pairs out of a url-encoded string
* (i.e. this=that&a=value)
*
* @param dict dictionary for key-values pairs
* @param query the encoded query string to be parsed
*
* @return bool true if successful
*/
static inline bool parse_url_encoded(ihash_multimap& dict,
const std::string& query)
{
return parse_url_encoded(dict, query.c_str(), query.size());
}
/**
* parse key-value pairs out of a multipart/form-data payload content
* (http://www.ietf.org/rfc/rfc2388.txt)
*
* @param dict dictionary for key-values pairs
* @param content_type value of the content-type HTTP header
* @param form_data the encoded form data
*
* @return bool true if successful
*/
static inline bool parse_multipart_form_data(ihash_multimap& dict,
const std::string& content_type,
const std::string& form_data)
{
return parse_multipart_form_data(dict, content_type, form_data.c_str(), form_data.size());
}
/**
* should be called after parsing HTTP headers, to prepare for payload content parsing
* available in the read buffer
*
* @param http_msg the HTTP message object to populate from parsing
* @param ec error_code contains additional information for parsing errors
*
* @return boost::tribool result of parsing:
* false = message has an error,
* true = finished parsing HTTP message (no content),
* indeterminate = payload content is available to be parsed
*/
boost::tribool finish_header_parsing(http::message& http_msg,
boost::system::error_code& ec);
/**
* parses an X-Forwarded-For HTTP header, and extracts from it an IP
* address that best matches the client's public IP address (if any are found)
*
* @param header the X-Forwarded-For HTTP header to parse
* @param public_ip the extract IP address, if found
*
* @return bool true if a public IP address was found and extracted
*/
static bool parse_forwarded_for(const std::string& header, std::string& public_ip);
/// returns an instance of parser::error_category_t
static inline error_category_t& get_error_category(void) {
boost::call_once(parser::create_error_category, m_instance_flag);
return *m_error_category_ptr;
}
protected:
/// Called after we have finished parsing the HTTP message headers
virtual void finished_parsing_headers(const boost::system::error_code& ec) {}
/**
* parses an HTTP message up to the end of the headers using bytes
* available in the read buffer
*
* @param http_msg the HTTP message object to populate from parsing
* @param ec error_code contains additional information for parsing errors
*
* @return boost::tribool result of parsing:
* false = message has an error,
* true = finished parsing HTTP headers,
* indeterminate = not yet finished parsing HTTP headers
*/
boost::tribool parse_headers(http::message& http_msg, boost::system::error_code& ec);
/**
* updates an http::message object with data obtained from parsing headers
*
* @param http_msg the HTTP message object to populate from parsing
*/
void update_message_with_header_data(http::message& http_msg) const;
/**
* parses a chunked HTTP message-body using bytes available in the read buffer
*
* @param chunk_buffers buffers to be populated from parsing chunked content
* @param ec error_code contains additional information for parsing errors
*
* @return boost::tribool result of parsing:
* false = message has an error,
* true = finished parsing message,
* indeterminate = message is not yet finished
*/
boost::tribool parse_chunks(http::message::chunk_cache_t& chunk_buffers,
boost::system::error_code& ec);
/**
* consumes payload content in the parser's read buffer
*
* @param http_msg the HTTP message object to consume content for
* @param ec error_code contains additional information for parsing errors
*
* @return boost::tribool result of parsing:
* false = message has an error,
* true = finished parsing message,
* indeterminate = message is not yet finished
*/
boost::tribool consume_content(http::message& http_msg,
boost::system::error_code& ec);
/**
* consume the bytes available in the read buffer, converting them into
* the next chunk for the HTTP message
*
* @param chunk_buffers buffers to be populated from parsing chunked content
* @return std::size_t number of content bytes consumed, if any
*/
std::size_t consume_content_as_next_chunk(http::message::chunk_cache_t& chunk_buffers);
/**
* compute and sets a HTTP Message data integrity status
* @param http_msg target HTTP message
* @param msg_parsed_ok message parsing result
*/
static void compute_msg_status(http::message& http_msg, bool msg_parsed_ok);
/**
* sets an error code
*
* @param ec error code variable to define
* @param ev error value to raise
*/
static inline void set_error(boost::system::error_code& ec, error_value_t ev) {
ec = boost::system::error_code(static_cast<int>(ev), get_error_category());
}
/// creates the unique parser error_category_t
static void create_error_category(void);
// misc functions used by the parsing functions
inline static bool is_char(int c);
inline static bool is_control(int c);
inline static bool is_special(int c);
inline static bool is_digit(int c);
inline static bool is_hex_digit(int c);
inline static bool is_cookie_attribute(const std::string& name, bool set_cookie_header);
/// maximum length for response status message
static const boost::uint32_t STATUS_MESSAGE_MAX;
/// maximum length for the request method
static const boost::uint32_t METHOD_MAX;
/// maximum length for the resource requested
static const boost::uint32_t RESOURCE_MAX;
/// maximum length for the query string
static const boost::uint32_t QUERY_STRING_MAX;
/// maximum length for an HTTP header name
static const boost::uint32_t HEADER_NAME_MAX;
/// maximum length for an HTTP header value
static const boost::uint32_t HEADER_VALUE_MAX;
/// maximum length for the name of a query string variable
static const boost::uint32_t QUERY_NAME_MAX;
/// maximum length for the value of a query string variable
static const boost::uint32_t QUERY_VALUE_MAX;
/// maximum length for the name of a cookie name
static const boost::uint32_t COOKIE_NAME_MAX;
/// maximum length for the value of a cookie; also used for path and domain
static const boost::uint32_t COOKIE_VALUE_MAX;
/// primary logging interface used by this class
mutable logger m_logger;
/// true if the message is an HTTP request; false if it is an HTTP response
const bool m_is_request;
/// points to the next character to be consumed in the read_buffer
const char * m_read_ptr;
/// points to the end of the read_buffer (last byte + 1)
const char * m_read_end_ptr;
private:
/// state used to keep track of where we are in parsing the HTTP message
enum message_parse_state_t {
PARSE_START, PARSE_HEADERS, PARSE_FOOTERS, PARSE_CONTENT,
PARSE_CONTENT_NO_LENGTH, PARSE_CHUNKS, PARSE_END
};
/// state used to keep track of where we are in parsing the HTTP headers
/// (only used if message_parse_state_t == PARSE_HEADERS)
enum header_parse_state_t {
PARSE_METHOD_START, PARSE_METHOD, PARSE_URI_STEM, PARSE_URI_QUERY,
PARSE_HTTP_VERSION_H, PARSE_HTTP_VERSION_T_1, PARSE_HTTP_VERSION_T_2,
PARSE_HTTP_VERSION_P, PARSE_HTTP_VERSION_SLASH,
PARSE_HTTP_VERSION_MAJOR_START, PARSE_HTTP_VERSION_MAJOR,
PARSE_HTTP_VERSION_MINOR_START, PARSE_HTTP_VERSION_MINOR,
PARSE_STATUS_CODE_START, PARSE_STATUS_CODE, PARSE_STATUS_MESSAGE,
PARSE_EXPECTING_NEWLINE, PARSE_EXPECTING_CR,
PARSE_HEADER_WHITESPACE, PARSE_HEADER_START, PARSE_HEADER_NAME,
PARSE_SPACE_BEFORE_HEADER_VALUE, PARSE_HEADER_VALUE,
PARSE_EXPECTING_FINAL_NEWLINE, PARSE_EXPECTING_FINAL_CR
};
/// state used to keep track of where we are in parsing chunked content
/// (only used if message_parse_state_t == PARSE_CHUNKS)
enum chunk_parse_state_t {
PARSE_CHUNK_SIZE_START, PARSE_CHUNK_SIZE,
PARSE_EXPECTING_IGNORED_TEXT_AFTER_CHUNK_SIZE,
PARSE_EXPECTING_CR_AFTER_CHUNK_SIZE,
PARSE_EXPECTING_LF_AFTER_CHUNK_SIZE, PARSE_CHUNK,
PARSE_EXPECTING_CR_AFTER_CHUNK, PARSE_EXPECTING_LF_AFTER_CHUNK,
PARSE_EXPECTING_FINAL_CR_OR_FOOTERS_AFTER_LAST_CHUNK,
PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK
};
/// the current state of parsing HTTP headers
message_parse_state_t m_message_parse_state;
/// the current state of parsing HTTP headers
header_parse_state_t m_headers_parse_state;
/// the current state of parsing chunked content
chunk_parse_state_t m_chunked_content_parse_state;
/// if defined, this function is used to consume payload content
payload_handler_t m_payload_handler;
/// Used for parsing the HTTP response status code
boost::uint16_t m_status_code;
/// Used for parsing the HTTP response status message
std::string m_status_message;
/// Used for parsing the request method
std::string m_method;
/// Used for parsing the name of resource requested
std::string m_resource;
/// Used for parsing the query string portion of a URI
std::string m_query_string;
/// Used to store the raw contents of HTTP headers when m_save_raw_headers is true
std::string m_raw_headers;
/// Used for parsing the name of HTTP headers
std::string m_header_name;
/// Used for parsing the value of HTTP headers
std::string m_header_value;
/// Used for parsing the chunk size
std::string m_chunk_size_str;
/// number of bytes in the chunk currently being parsed
std::size_t m_size_of_current_chunk;
/// number of bytes read so far in the chunk currently being parsed
std::size_t m_bytes_read_in_current_chunk;
/// number of payload content bytes that have not yet been read
std::size_t m_bytes_content_remaining;
/// number of bytes read so far into the message's payload content
std::size_t m_bytes_content_read;
/// number of bytes read during last parse operation
std::size_t m_bytes_last_read;
/// total number of bytes read while parsing the HTTP message
std::size_t m_bytes_total_read;
/// maximum length for HTTP payload content
std::size_t m_max_content_length;
/// if true, then only HTTP headers will be parsed (no content parsing)
bool m_parse_headers_only;
/// if true, the raw contents of HTTP headers are stored into m_raw_headers
bool m_save_raw_headers;
/// points to a single and unique instance of the parser error_category_t
static error_category_t * m_error_category_ptr;
/// used to ensure thread safety of the parser error_category_t
static boost::once_flag m_instance_flag;
};
// inline functions for parser
inline bool parser::is_char(int c)
{
return(c >= 0 && c <= 127);
}
inline bool parser::is_control(int c)
{
return( (c >= 0 && c <= 31) || c == 127);
}
inline bool parser::is_special(int c)
{
switch (c) {
case '(': case ')': case '<': case '>': case '@':
case ',': case ';': case ':': case '\\': case '"':
case '/': case '[': case ']': case '?': case '=':
case '{': case '}': case ' ': case '\t':
return true;
default:
return false;
}
}
inline bool parser::is_digit(int c)
{
return(c >= '0' && c <= '9');
}
inline bool parser::is_hex_digit(int c)
{
return((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}
inline bool parser::is_cookie_attribute(const std::string& name, bool set_cookie_header)
{
return (name.empty() || name[0] == '$' || (set_cookie_header &&
(name=="Comment" || name=="Domain" || name=="Max-Age" || name=="Path" || name=="Secure" || name=="Version" || name=="Expires")
) );
}
} // end namespace http
} // end namespace pion
#endif
|