PageRenderTime 10ms CodeModel.GetById 5ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/http_server/stack/parser/AWSHttpMessageParser.h

http://github.com/jtblatt/duderino
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