/http_server/stack/parser/AWSHttpMessageParser.h
C Header | 148 lines | 43 code | 29 blank | 76 comment | 0 complexity | f7b878a0c1181b7435456233b32a438b MD5 | raw file
1/* Copyright (c) 2009 Yahoo! Inc. All rights reserved. 2 * The copyrights embodied in the content of this file are licensed by Yahoo! Inc. 3 * under the BSD (revised) open source license. 4 */ 5 6#ifndef AWS_HTTP_MESSAGE_PARSER_H 7#define AWS_HTTP_MESSAGE_PARSER_H 8 9#ifndef ESF_DISCARD_ALLOCATOR_H 10#include <ESFDiscardAllocator.h> 11#endif 12 13#ifndef ESF_BUFFER_H 14#include <ESFBuffer.h> 15#endif 16 17#ifndef AWS_HTTP_MESSAGE_H 18#include <AWSHttpMessage.h> 19#endif 20 21/** 22 * Parses a HTTP message as defined in RFC 2616 and RFC 2396 23 * 24 * TODO handle 1.x versions other than 1.0 and 1.1 25 */ 26class AWSHttpMessageParser 27{ 28public: 29 30 /** Create a new message parser 31 * 32 * @param workingBuffer Temporary storage for parsing 33 * @param allocator The discard allocator to use for allocating internal strings. 34 */ 35 AWSHttpMessageParser(ESFBuffer *workingBuffer, ESFDiscardAllocator *allocator); 36 37 virtual ~AWSHttpMessageParser(); 38 39 /** 40 * Reset the parser 41 */ 42 virtual void reset(); 43 44 /** 45 * Incrementally parse a HTTP Message up to but not including the body. 46 * 47 * generic-message = start-line 48 * *(message-header CRLF) 49 * CRLF 50 * [ message-body ] 51 * 52 * Caller should: 53 * (1) Fill buffer, closing any idle sockets, enforcing any size limits. 54 * (2) Parse buffer with this method. If ESF_AGAIN is returned, compact 55 * buffer & mark. If error or ESF_SUCCESS returned, break. 56 * (3) If no space in buffer, parser is jammed, break and close socket. 57 * (4) Otherwise goto (1) 58 * 59 * @param inputBuffer The buffer to parse 60 * @param message The http message to build 61 * @return ESF_SUCCESS if successful, ESF_AGAIN if more data needs to be read, 62 * another error code otherwise. 63 */ 64 ESFError parseHeaders(ESFBuffer *inputBuffer, AWSHttpMessage *message); 65 66 /** 67 * Parse the body. Caller should keep calling this mehtod on a given input buffer 68 * until it returns an error, ESF_AGAIN (buffer needs to be compacted and filled), 69 * or the number of bytes to be read is 0 (EOF) 70 * 71 * @param inputBuffer A buffer full of body data to be parsed. 72 * @param startingPosition If ESF_SUCCESS is returned, this will be set to the 73 * starting position of the chunk to be read 74 * @param chunkSize If ESF_SUCCESS is returned, this will be set to the number of 75 * bytes that can be read after the starting position. If 0, then there is no 76 * more data left in the body. 77 * @return ESF_SUCCESS if successful, ESF_AGAIN if the buffer needs to be 78 * compacted and filled, another error code otherwise. 79 */ 80 ESFError parseBody(ESFBuffer *inputBuffer, int *startingPosition, int *chunkSize); 81 82 /** 83 * Skips any body trailer. Necessary only if the connection will be reused. 84 * 85 * @param inputBuffer A buffer full of data to be parsed 86 * @return ESF_SUCCESS if successful, ESF_AGAIN if the buffer needs to be compacted 87 * and filled, another error code otherwise. 88 */ 89 ESFError skipTrailer(ESFBuffer *inputBuffer); 90 91protected: 92 93 virtual ESFError parseStartLine(ESFBuffer *inputBuffer, AWSHttpMessage *message) = 0; 94 95 virtual bool isBodyNotAllowed(AWSHttpMessage *message) = 0; 96 97 // HTTP-Version = "HTTP" "/" 1*DIGIT "." 1*DIGIT 98 ESFError parseVersion(ESFBuffer *inputBuffer, AWSHttpMessage *message, bool clientMode); 99 100 ESFBuffer *_workingBuffer; 101 ESFDiscardAllocator *_allocator; 102 int _state; 103 ESFUInt64 _bodyBytesRemaining; 104 105private: 106 107 // Disabled 108 AWSHttpMessageParser(const AWSHttpMessageParser &parser); 109 void operator=(const AWSHttpMessageParser &parser); 110 111 // field-name = token 112 ESFError parseFieldName(ESFBuffer *inputBuffer, AWSHttpMessage *message); 113 114 // field-value = *( field-content | LWS ) 115 // field-content = <the OCTETs making up the field-value 116 // and consisting of either *TEXT or combinations 117 // of token, separators, and quoted-string> 118 ESFError parseFieldValue(ESFBuffer *inputBuffer, AWSHttpMessage *message); 119 120 // Chunked-Body = *chunk 121 // last-chunk 122 // trailer 123 // CRLF 124 ESFError parseChunkedBody(ESFBuffer *inputBuffer, int *startingPosition, int *chunkSize); 125 126 // chunk-size = 1*HEX 127 ESFError parseChunkSize(ESFBuffer *inputBuffer); 128 129 // chunk = ... [ chunk-extension ] CRLF 130 // chunk-extension= *( ";" chunk-ext-name [ "=" chunk-ext-val ] ) 131 // chunk-ext-name = token 132 // chunk-ext-val = token | quoted-string 133 ESFError parseChunkExtension(ESFBuffer *inputBuffer); 134 135 // chunk-data = chunk-size(OCTET) 136 ESFError parseChunkData(ESFBuffer *inputBuffer, int *startingPosition, int *chunkSize); 137 138 // chunk = ... CRLF 139 ESFError parseEndChunk(ESFBuffer *inputBuffer); 140 141 ESFError parseMultipartBody(ESFBuffer *inputBuffer, int *startingPosition, int *chunkSize); 142 143 ESFError parseUnencodedBody(ESFBuffer *inputBuffer, int *startingPosition, int *chunkSize); 144 145 ESFError postParse(AWSHttpMessage *message); 146}; 147 148#endif