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