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_COMPOSER_H_
     19 #define HTTP_COMPOSER_H_
     20 
     21 
     22 ///////////////////////////////////////////////////////////////////////////////////////
     23 
     24 #include "oscl_base.h"
     25 #include "oscl_mem.h"
     26 #include "oscl_str_ptr_len.h"
     27 
     28 enum HTTPVersion
     29 {
     30     HTTP_V1_0 = 0,
     31     HTTP_V1_1
     32 };
     33 
     34 // HTTPMethod enum
     35 enum HTTPMethod
     36 {
     37     HTTP_METHOD_GET = 0,            // both HTTP 1.0 and HTTP 1.1
     38     HTTP_METHOD_HEAD,           // both HTTP 1.0 and HTTP 1.1
     39     HTTP_METHOD_POST,           // both HTTP 1.0 and HTTP 1.1
     40     HTTP_METHOD_DELETE,         // both HTTP 1.0 and HTTP 1.1
     41     HTTP_METHOD_LINK,           // HTTP 1.0 only
     42     HTTP_METHOD_UNLINK,         // HTTP 1.0 only
     43     HTTP_METHOD_OPTIONS,        // HTTP 1.1 only
     44     HTTP_METHOD_PUT,            // HTTP 1.1 only
     45     HTTP_METHOD_TRACE,          // HTTP 1.1 only
     46     HTTP_METHOD_CONNECT,        // HTTP 1.1 only
     47 };
     48 
     49 // forward declaration
     50 struct HTTPMemoryFragment;
     51 class StringKeyValueStore;
     52 
     53 class HTTPComposer
     54 {
     55     public:
     56 
     57         /**
     58          * HTTP request line:  Method SP Request-URI SP HTTP-Version CRLF
     59          * set three basic elements for a http request: method, uri and version
     60          * uri must be set; if URI is set, but method or version is not set, then
     61          * the method or version will default to GET or version 1.1
     62          **/
     63         void setMethod(const HTTPMethod aMethod)
     64         {
     65             iMethod = aMethod;
     66         }
     67         void setVersion(const HTTPVersion aVersion)
     68         {
     69             iVersion = aVersion;
     70         }
     71         /**
     72          * Set URI. Note that composer doesn't do any memory allocation and memory copy for the input URI, and just save the pointer
     73          * for the URI string. So it is composer user's reponsiblity to keep URI valid during request composing.
     74          */
     75         OSCL_IMPORT_REF void setURI(const StrPtrLen aURI);
     76 
     77         /**
     78          * set/remove a standard field or add a new extension field for the headers
     79          * if aNewFieldValue=NULL, that means removing the existing field with the field key specified by aNewFieldName
     80          * The flag aNeedReplaceOldValue tells the library whether to replace the old value with the new value for the same field, if there is,
     81          * For HTTP, there is a typical situation where multiple same fields can be set at the same time, for example, field "Pragma". The
     82          * user can set all the implementation specifics for one "Pragma", or multiple "Pragma". So by default, if we run into the same
     83          * field, we won't replace the old value with the new value unless the user requires to do it.       *
     84          * @param aNewFieldName, input field name
     85          * @param aNewFieldValue, input field value name
     86          * @param aNeedReplaceOldValue, flag of whether the new value replaces the old value
     87          * @return true for success
     88          **/
     89         OSCL_IMPORT_REF bool setField(const StrCSumPtrLen &aNewFieldName, const StrPtrLen *aNewFieldValue, const bool aNeedReplaceOldValue = false);
     90         OSCL_IMPORT_REF bool setField(const StrCSumPtrLen &aNewFieldName, const char *aNewFieldValue, const bool aNeedReplaceOldValue = false);
     91 
     92         /**
     93          * get the current total length based on the current settings, and the length includes the length for
     94          * request-line + general header + request header + entity header. Note that this length doesn't include entity body length,
     95          * since entity body is controlled by the user.
     96          * This API is used for the user to get the length after setting everything done (using above set APIs), and help the user
     97          * provide the buffer with an accurate size to hold the HTTP request with optional entity body.
     98          * Note that this API can get called in multiple times, and any time.
     99          * @param usingAbsoluteURI, flag to show absolute uri is used in the first request line. For MS http streaming, it uses relative uri + Host field to
    100          *        identify the exact source
    101          * @return the current total length or COMPOSE_BAD_URI from the following COMPOSE_RETURN_CODES.
    102          **/
    103         OSCL_IMPORT_REF int32 getCurrentRequestLength(const bool usingAbsoluteURI = true);
    104 
    105         /**
    106          * compose a HTTP request with the given message buffer, and the optional entity body.
    107          * The reason for the request buffer provided by the user is, a http request could contain entity body (e.g. POST method),
    108          * which is controlled by the user. And the entity body can be anything. So it doesn't make much sense for the composer to
    109          * allocate a buffer for holding a HTTP request, since in general, the composer has no idea about how big a request is.
    110          * To avoid extra memory copy, if the HTTP request does have entity body, the input buffer should already have the entity
    111          * body in place, i.e. the entity body is copied to the input buffer from an offset, which is header length, retrieved from
    112          * the above getCurrentRequestLength() function. The following "aEntityBodyLength" argument just shows whether there is an
    113          * enity body put into the input buffer, and whether this length matches the version from "Content-Length" (which has to be
    114          * be set)
    115          * @param aNewFielaComposedMessageBuffer, input message buffer
    116          * @param aEntityBodyLength, entity body length, 0 means no entity body
    117          * @return following enum codes
    118          **/
    119         OSCL_IMPORT_REF int32 compose(OsclMemoryFragment &aComposedMessageBuffer, const bool usingAbsoluteURI = true, const uint32 aEntityBodyLength = 0);
    120 
    121         enum COMPOSE_RETURN_CODES
    122         {
    123             COMPOSE_SUCCESS = 0,
    124 
    125             // error
    126             COMPOSE_GENERAL_ERROR    = -1,
    127             COMPOSE_BUFFER_TOO_SMALL = -2,
    128             COMPOSE_URI_NOT_SET      = -3,
    129             COMPOSE_CONTENT_TYPE_NOT_SET_FOR_ENTITY_BODY   = -4,
    130             COMPOSE_CONTENT_LENGTH_NOT_SET_FOR_ENTITY_BODY = -5,
    131             COMPOSE_CONTENT_LENGTH_NOT_MATCH_ENTITY_BODY_LENGTH = -6,
    132             COMPOSE_BAD_URI = -7  // input uri is relative uri, but request using absolute uri, or
    133             // request using relative uri, but relative uri isn't able to obtained from input uri
    134         };
    135 
    136         /**
    137          * reset the composer in order to compose a new HTTP request. Currently there are two cases in consideration.
    138          * One is reset the everything in the composer to compose brand-new HTTP request with probably new header fields,
    139          * or new method, etc. In this case, all the previous settings (method, version, uri, and all header fields) get
    140          * reset. Another useful case is the new HTTP request only has a change on URI, which is highly likely, and so
    141          * method, version and all header fields are kept the same. So in this case, we don't need to reset everything.
    142          * This offers a possiblity for fast composing a new HTTP request.
    143          * @param aKeepAllSettingsExceptURI, flag to show whether to keep all settings except URI
    144          **/
    145         OSCL_IMPORT_REF void reset(const bool aKeepAllSettingsExceptURI = false);
    146 
    147         // factory method
    148         OSCL_IMPORT_REF static HTTPComposer *create();
    149 
    150         // destructor
    151         OSCL_IMPORT_REF ~HTTPComposer();
    152 
    153     private:
    154         // sanity check for compose API
    155         int32 santityCheckForCompose(HTTPMemoryFragment &aComposedMessageBuffer, const bool usingAbsoluteURI = true, const uint32 aEntityBodyLength = 0);
    156         // compose the first request/status line of a HTTP request
    157         void composeFirstLine(HTTPMemoryFragment &aComposedMessageBuffer, const bool usingAbsoluteURI = true);
    158         // compose all headers of a HTTP request
    159         bool composeHeaders(HTTPMemoryFragment &aComposedMessageBuffer);
    160 
    161         // called by create(), construct the composer
    162         bool construct();
    163 
    164         // constructor
    165         HTTPComposer() : iKeyValueStore(NULL)
    166         {
    167             ;
    168         }
    169 
    170     private:
    171         HTTPMethod  iMethod;
    172         HTTPVersion iVersion;
    173         StrPtrLen   iURI;
    174         StrPtrLen   iRelativeURI;
    175 
    176         uint32 iHeaderLength;
    177         uint32 iFirstLineLength; // length of the request/response line in HTTP header
    178         uint32 iEntityBodyLength;
    179 
    180         // field key-value store to handle key-value operations
    181         StringKeyValueStore *iKeyValueStore;
    182 };
    183 
    184 #endif // HTTP_COMPOSER_H_
    185 
    186