Home | History | Annotate | Download | only in include
      1 /* ------------------------------------------------------------------
      2  * Copyright (C) 1998-2009 PacketVideo
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
     13  * express or implied.
     14  * See the License for the specific language governing permissions
     15  * and limitations under the License.
     16  * -------------------------------------------------------------------
     17  */
     18 #ifndef HTTP_PARSER_H_
     19 #define HTTP_PARSER_H_
     20 
     21 
     22 ///////////////////////////////////////////////////////////////////////////////////////
     23 
     24 #include "oscl_base.h"
     25 #include "oscl_mem.h"
     26 #include "oscl_str_ptr_len.h"
     27 #include "http_parser_external.h" // define struct HTTPContentInfo and class RefCountHTTPEntityUnit
     28 
     29 // forward declarations
     30 struct HTTPContentInfoInternal;
     31 class  HTTPParserInput;
     32 class  HTTPParserHeaderObject;
     33 class  HTTPParserEntityBodyObject;
     34 
     35 class HTTPParser
     36 {
     37 
     38     public:
     39 
     40         /**
     41          * the sole parsing function to parse both HTTP header and entity body. Since the input data stream is a fragment of a complete
     42          * HTTP response message (for client), the input data fragment is assumed arbitrary, i.e, its starting and ending position could
     43          * be anywhere in a complete HTTP response message. Considering HTTP header could spread among multiple input data stream
     44          * fragments, like the entity body case, parsing header and parsing entity body can be handled in a unified way. The output is
     45          * entity unit which could be a complete HTTP header (FIRST entity unit), or a complete chunk of data for partial content, or the
     46          * whole input data fragment. To avoid memory copy, we do inplace processing, i.e. the output entity unit is represented by a set
     47          * of memory fragment pointers to point to the actual memory fragments inside the input data streams that may inlude the previous
     48          * input data streams. Considering an entity unit may need one or mulitple input data fragments and an input data fragment could
     49          * constain multiple entity units, the memory for an input data fragment can only be released after all the related entity units
     50          * it has have been parsed and used. So the input data fragment needs to reference counted. Also the output entity unit needs to
     51          * be reference counted. This lets the user not worry about how to release and re-use the existing memory fragment. Each time,
     52          * user just need to create new memory fragment from a memory pool and pass it down to library in normal cases. Reference counter
     53          * will automatically take care of memory deallocation. In the case where the previous input data fragment contains multiple entity
     54          * units, user needs to input EMPTY fragment or the previous fragment again to let the library send out the next entity unit (since
     55          * each time this function only sends out ONE enity unit if it has multiple).
     56          * Return value: see the following enum. For PARSE_HEADER_AVAILABLE, user need to call getHTTPStatusCode() to get status code
     57          * @param aInputDataStream, ref-counted input data fragment
     58          * @param aEntityUnit, ref-counted output entity unit
     59          * @return following PARSE_RETURN_CODES
     60          *
     61          * NOTE: as long as the return code is non-negative, user need to check the output entity unit to see whether there is something
     62          * inside, and also user needs to do concatenation for the output fragments.
     63          **/
     64         OSCL_IMPORT_REF int32 parse(const OsclRefCounterMemFrag &aInputDataStream, RefCountHTTPEntityUnit &aEntityUnit);
     65 
     66 
     67         /**
     68          * If http response header is available, status code is ok (though parse() already does some sanity check for status code),
     69          * there still could be some headers that need further check, i.e. some headers are only supported in HTTP/1.1, such as Transfer-Encoding
     70          * @return following PARSE_RETURN_CODES, list the unsupported items.
     71          **/
     72         OSCL_IMPORT_REF int32 doSanityCheckForResponseHeader();
     73 
     74 
     75         // return codes for parse function
     76         enum PARSE_RETURN_CODES
     77         {
     78             PARSE_SUCCESS                        = 0,   // success with left over of the current input, don't send the new input next time
     79             PARSE_SUCCESS_END_OF_INPUT           = 1,   // success with end of the current input
     80             PARSE_SUCCESS_END_OF_MESSAGE         = 2,   // success with end of the message (get data with the size of content-length)
     81             PARSE_SUCCESS_END_OF_MESSAGE_WITH_EXTRA_DATA = 3, // success with end of the message (get data with the size of content-length), but input has more extra data
     82 
     83             PARSE_HEADER_AVAILABLE               = 4,   // HTTP header is parsed
     84             PARSE_STATUS_LINE_SHOW_NOT_SUCCESSFUL = 5,  // parse the first http status line,
     85             // got status code >= 300, 3xx=>redirection, 4xx=>client error, 5xx=>server error
     86             // note that this is return code when parser just finishes parsing the first line,
     87             // user can continue calling parse function to get the complete http header
     88             PARSE_NEED_MORE_DATA                 = 6,   // no ouput, no entity units
     89 
     90             // errors
     91             PARSE_GENERAL_ERROR = -1,
     92             PARSE_SYNTAX_ERROR = -2,                // syntax is not understandable
     93             PARSE_HTTP_VERSION_NOT_SUPPORTED = -3,  // no HTTP version or HTTP version is different from 1.0 or 1.1.
     94             PARSE_TRANSFER_ENCODING_NOT_SUPPORTED = -4,
     95             PARSE_MEMORY_ALLOCATION_FAILURE = -5,   // memory allocation for entity units
     96             PARSE_HEADER_NOT_PARSED_YET = -6        // HTTP header hasn't been parsed yet, so shouldn't expect parsing entity body
     97         };
     98 
     99 
    100         // After parsing HTTP header(parse() return PARSE_HEADER_AVAILABLE), use the following functions to get the related information
    101         // get content info
    102         OSCL_IMPORT_REF void getContentInfo(HTTPContentInfo &aContentInfo);
    103         // get total fields inside the header
    104         OSCL_IMPORT_REF uint32 getTotalFieldsInHeader();
    105         // get a list of all field keys inside the header
    106         OSCL_IMPORT_REF uint32 getFieldKeyListInHeader(StrPtrLen *&aFieldKeyList);
    107         // get the field value with the given field key, which can be retrieved from getFieldKeyListInHeader()
    108         // There could be a case where one field key correponds to multiple field values, so input argument "index" is for
    109         // getting which value for the given field key
    110         OSCL_IMPORT_REF bool getField(const StrCSumPtrLen &aNewFieldName, StrPtrLen &aNewFieldValue, const uint32 index = 0);
    111         // get the number of field key-value pairs with the same field key. 0 => no such key, 1 or more => number of key-value pairs
    112         OSCL_IMPORT_REF uint32 getNumberOfFieldsByKey(const StrCSumPtrLen &aNewFieldName);
    113         // get the status code, 1xx, 2xx, 3xx, 4xx, 5xx
    114         OSCL_IMPORT_REF uint32 getHTTPStatusCode();
    115         /////////////////////////////////////////////////////////////////////////////////////////////
    116 
    117         // reset the parser to parse a new HTTP response
    118         OSCL_IMPORT_REF void reset();
    119 
    120         // factory method
    121         OSCL_IMPORT_REF static HTTPParser *create();
    122 
    123         // destructor
    124         OSCL_IMPORT_REF ~HTTPParser();
    125 
    126     private:
    127         int32 parseEntityBody(RefCountHTTPEntityUnit &aEntityUnit);
    128 
    129         // called by create() to construct the parser
    130         bool construct();
    131 
    132         // constructor
    133         HTTPParser()
    134         {
    135             oscl_memset(this, 0, sizeof(HTTPParser));
    136         }
    137 
    138     private:
    139         // Basically, this parser is decomposed into the following objects.
    140         // HTTPParserInput handles input data stream concatenation and fragment grouping for parsing and entity unit output
    141         // HTTPContentInfo contains content type, content length and content range information and does infomation parsing.
    142         // HTTPParserHeaderObject and HTTPParserEntityBodyObject handles header and entity body parsing
    143         HTTPParserInput         *iParserInput;
    144         HTTPContentInfoInternal *iContentInfo;
    145         HTTPParserHeaderObject  *iHeader;
    146         HTTPParserEntityBodyObject *iEntityBody;
    147 };
    148 
    149 #endif // HTTP_PARSER_H_
    150 
    151