This file is indexed.

/usr/include/pion/net/HTTPParser.hpp is in libpion-net-dev 4.0.7+dfsg-3.1ubuntu4.

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
// ------------------------------------------------------------------
// pion-net: a C++ framework for building lightweight HTTP interfaces
// ------------------------------------------------------------------
// Copyright (C) 2007-2008 Atomic Labs, Inc.  (http://www.atomiclabs.com)
//
// Distributed under the Boost Software License, Version 1.0.
// See http://www.boost.org/LICENSE_1_0.txt
//

#ifndef __PION_HTTPPARSER_HEADER__
#define __PION_HTTPPARSER_HEADER__

#include <string>
#include <boost/noncopyable.hpp>
#include <boost/logic/tribool.hpp>
#include <boost/system/error_code.hpp>
#include <boost/thread/once.hpp>
#include <pion/PionConfig.hpp>
#include <pion/PionLogger.hpp>
#include <pion/net/HTTPMessage.hpp>


namespace pion {	// begin namespace pion
namespace net {		// begin namespace net (Pion Network Library)

// forward declarations used for finishing HTTP messages
class HTTPRequest;
class HTTPResponse;

///
/// HTTPParser: parses HTTP messages
///
class PION_NET_API HTTPParser :
	private boost::noncopyable
{

public:

	/// maximum length for HTTP payload content
	static const std::size_t		DEFAULT_CONTENT_MAX;

	/// class-specific error code values
	enum ErrorValue {
		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 ErrorCategory
		: public boost::system::error_category
	{
	public:
		const char *name() const { return "HTTPParser"; }
		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 "HTTPParser error";
		}
	};

	/**
	 * creates new HTTPParser 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
	 */
	HTTPParser(const bool is_request, std::size_t max_content_length = DEFAULT_CONTENT_MAX)
		: m_logger(PION_GET_LOGGER("pion.net.HTTPParser")), 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 ~HTTPParser() {}

	/**
	 * 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(HTTPMessage& 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 parseMissingData(HTTPMessage& 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(HTTPMessage& 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 setReadBuffer(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 loadReadPosition(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 checkPrematureEOF(HTTPMessage& http_msg) {
		if (m_message_parse_state != PARSE_CONTENT_NO_LENGTH)
			return true;
		m_message_parse_state = PARSE_END;
		http_msg.concatenateChunks();
		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 parseHeadersOnly(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 skipHeaderParsing(HTTPMessage& http_msg) {
		boost::system::error_code ec;
		finishHeaderParsing(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 getTotalBytesRead(void) const { return m_bytes_total_read; }

	/// returns the total number of bytes read while parsing the payload content
	inline std::size_t getContentBytesRead(void) const { return m_bytes_content_read; }

	/// returns the maximum length for HTTP payload content
	inline std::size_t getMaxContentLength(void) const { return m_max_content_length; }

	/// returns the raw HTTP headers saved by the parser
	inline const std::string& getRawHeaders(void) const { return m_raw_headers; }

	/// returns true if the parser is saving raw HTTP header contents
	inline bool getSaveRawHeaders(void) const { return m_save_raw_headers; }

	/// returns true if the parser is being used to parse an HTTP request
	inline bool isParsingRequest(void) const { return m_is_request; }

	/// returns true if the parser is being used to parse an HTTP response
	inline bool isParsingResponse(void) const { return ! m_is_request; }

	/// sets the maximum length for HTTP payload content
	inline void setMaxContentLength(std::size_t n) { m_max_content_length = n; }

	/// resets the maximum length for HTTP payload content to the default value
	inline void resetMaxContentLength(void) { m_max_content_length = DEFAULT_CONTENT_MAX; }

	/// sets parameter for saving raw HTTP header content
	inline void setSaveRawHeaders(bool b) { m_save_raw_headers = b; }

	/// sets the logger to be used
	inline void setLogger(PionLogger log_ptr) { m_logger = log_ptr; }

	/// returns the logger currently in use
	inline PionLogger getLogger(void) { return m_logger; }


	/**
	 * 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 parseURLEncoded(HTTPTypes::QueryParams& dict,
								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 parseCookieHeader(HTTPTypes::CookieParams& 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 parseCookieHeader(HTTPTypes::CookieParams& dict,
		const std::string& cookie_header, bool set_cookie_header)
	{
		return parseCookieHeader(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 parseURLEncoded(HTTPTypes::QueryParams& dict,
		const std::string& query)
	{
		return parseURLEncoded(dict, query.c_str(), query.size());
	}

	/**
	 * 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 parseForwardedFor(const std::string& header, std::string& public_ip);
	
	/// returns an instance of HTTPParser::ErrorCategory
	static inline ErrorCategory& getErrorCategory(void) {
		boost::call_once(HTTPParser::createErrorCategory, m_instance_flag);
		return *m_error_category_ptr;
	}


protected:

	/**
	 * 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 parseHeaders(HTTPMessage& http_msg, boost::system::error_code& ec);

	/**
	 * updates an HTTPMessage object with data obtained from parsing headers
	 *
	 * @param http_msg the HTTP message object to populate from parsing
	 */
	void updateMessageWithHeaderData(HTTPMessage& http_msg) const;

	/**
	 * 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 finishHeaderParsing(HTTPMessage& http_msg,
		boost::system::error_code& ec);

	/**
	 * 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 parseChunks(HTTPMessage::ChunkCache& 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 consumeContent(HTTPMessage& 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 consumeContentAsNextChunk(HTTPMessage::ChunkCache& 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 computeMsgStatus(HTTPMessage& 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 setError(boost::system::error_code& ec, ErrorValue ev) {
		ec = boost::system::error_code(static_cast<int>(ev), getErrorCategory());
	}

	/// creates the unique HTTPParser ErrorCategory
	static void createErrorCategory(void);


	// misc functions used by the parsing functions
	inline static bool isChar(int c);
	inline static bool isControl(int c);
	inline static bool isSpecial(int c);
	inline static bool isDigit(int c);
	inline static bool isHexDigit(int c);
	inline static bool isCookieAttribute(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 PionLogger					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 MessageParseState {
		PARSE_START, PARSE_HEADERS, 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 MessageParseState == PARSE_HEADERS)
	enum HeadersParseState {
		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 MessageParseState == PARSE_CHUNKS)
	enum ChunkedContentParseState {
		PARSE_CHUNK_SIZE_START, PARSE_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_AFTER_LAST_CHUNK, 
		PARSE_EXPECTING_FINAL_LF_AFTER_LAST_CHUNK
	};


	/// the current state of parsing HTTP headers
	MessageParseState					m_message_parse_state;

	/// the current state of parsing HTTP headers
	HeadersParseState					m_headers_parse_state;

	/// the current state of parsing chunked content
	ChunkedContentParseState			m_chunked_content_parse_state;

	/// 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 HTTPParser ErrorCategory
	static ErrorCategory *				m_error_category_ptr;
		
	/// used to ensure thread safety of the HTTPParser ErrorCategory
	static boost::once_flag				m_instance_flag;
};


// inline functions for HTTPParser

inline bool HTTPParser::isChar(int c)
{
	return(c >= 0 && c <= 127);
}

inline bool HTTPParser::isControl(int c)
{
	return( (c >= 0 && c <= 31) || c == 127);
}

inline bool HTTPParser::isSpecial(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 HTTPParser::isDigit(int c)
{
	return(c >= '0' && c <= '9');
}

inline bool HTTPParser::isHexDigit(int c)
{
	return((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'));
}

inline bool HTTPParser::isCookieAttribute(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 net
}	// end namespace pion

#endif