• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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          **/
setMethod(const HTTPMethod aMethod)63         void setMethod(const HTTPMethod aMethod)
64         {
65             iMethod = aMethod;
66         }
setVersion(const HTTPVersion aVersion)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
HTTPComposer()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