Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more
httpheaders.c
00001 // Copyright (c) Microsoft. All rights reserved. 00002 // Licensed under the MIT license. See LICENSE file in the project root for full license information. 00003 00004 #include <stdlib.h> 00005 #include "azure_c_shared_utility/gballoc.h" 00006 #include "azure_c_shared_utility/map.h" 00007 #include "azure_c_shared_utility/httpheaders.h" 00008 #include <string.h> 00009 #include "azure_c_shared_utility/crt_abstractions.h" 00010 #include "azure_c_shared_utility/xlogging.h" 00011 00012 DEFINE_ENUM_STRINGS(HTTP_HEADERS_RESULT, HTTP_HEADERS_RESULT_VALUES); 00013 00014 typedef struct HTTP_HEADERS_HANDLE_DATA_TAG 00015 { 00016 MAP_HANDLE headers; 00017 } HTTP_HEADERS_HANDLE_DATA; 00018 00019 HTTP_HEADERS_HANDLE HTTPHeaders_Alloc(void) 00020 { 00021 /*Codes_SRS_HTTP_HEADERS_99_002:[ This API shall produce a HTTP_HANDLE that can later be used in subsequent calls to the module.]*/ 00022 HTTP_HEADERS_HANDLE_DATA* result; 00023 result = (HTTP_HEADERS_HANDLE_DATA*)malloc(sizeof(HTTP_HEADERS_HANDLE_DATA)); 00024 00025 if (result == NULL) 00026 { 00027 LogError("malloc failed"); 00028 } 00029 else 00030 { 00031 /*Codes_SRS_HTTP_HEADERS_99_004:[ After a successful init, HTTPHeaders_GetHeaderCount shall report 0 existing headers.]*/ 00032 result->headers = Map_Create(NULL); 00033 if (result->headers == NULL) 00034 { 00035 LogError("Map_Create failed"); 00036 free(result); 00037 result = NULL; 00038 } 00039 else 00040 { 00041 /*all is fine*/ 00042 } 00043 } 00044 00045 /*Codes_SRS_HTTP_HEADERS_99_003:[ The function shall return NULL when the function cannot execute properly]*/ 00046 return (HTTP_HEADERS_HANDLE)result; 00047 } 00048 00049 /*Codes_SRS_HTTP_HEADERS_99_005:[ Calling this API shall de-allocate the data structures allocated by previous API calls to the same handle.]*/ 00050 void HTTPHeaders_Free(HTTP_HEADERS_HANDLE handle) 00051 { 00052 /*Codes_SRS_HTTP_HEADERS_02_001: [If httpHeadersHandle is NULL then HTTPHeaders_Free shall perform no action.] */ 00053 if (handle == NULL) 00054 { 00055 /*do nothing*/ 00056 } 00057 else 00058 { 00059 /*Codes_SRS_HTTP_HEADERS_99_005:[ Calling this API shall de-allocate the data structures allocated by previous API calls to the same handle.]*/ 00060 HTTP_HEADERS_HANDLE_DATA* handleData = (HTTP_HEADERS_HANDLE_DATA*)handle; 00061 00062 Map_Destroy(handleData->headers); 00063 free(handleData); 00064 } 00065 } 00066 00067 /*Codes_SRS_HTTP_HEADERS_99_012:[ Calling this API shall record a header from name and value parameters.]*/ 00068 static HTTP_HEADERS_RESULT headers_ReplaceHeaderNameValuePair(HTTP_HEADERS_HANDLE handle, const char* name, const char* value, bool replace) 00069 { 00070 HTTP_HEADERS_RESULT result; 00071 /*Codes_SRS_HTTP_HEADERS_99_014:[ The function shall return when the handle is not valid or when name parameter is NULL or when value parameter is NULL.]*/ 00072 if ( 00073 (handle == NULL) || 00074 (name == NULL) || 00075 (value == NULL) 00076 ) 00077 { 00078 result = HTTP_HEADERS_INVALID_ARG; 00079 LogError("invalid arg (NULL) , result= %s", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00080 } 00081 else 00082 { 00083 /*Codes_SRS_HTTP_HEADERS_99_036:[ If name contains the characters outside character codes 33 to 126 then the return value shall be HTTP_HEADERS_INVALID_ARG]*/ 00084 /*Codes_SRS_HTTP_HEADERS_99_031:[ If name contains the character ":" then the return value shall be HTTP_HEADERS_INVALID_ARG.]*/ 00085 size_t i; 00086 size_t nameLen = strlen(name); 00087 for (i = 0; i < nameLen; i++) 00088 { 00089 if ((name[i] < 33) || (126 < name[i]) || (name[i] == ':')) 00090 { 00091 break; 00092 } 00093 } 00094 00095 if (i < nameLen) 00096 { 00097 result = HTTP_HEADERS_INVALID_ARG; 00098 LogError("(result = %s)", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00099 } 00100 else 00101 { 00102 HTTP_HEADERS_HANDLE_DATA* handleData = (HTTP_HEADERS_HANDLE_DATA*)handle; 00103 const char* existingValue = Map_GetValueFromKey(handleData->headers, name); 00104 /*eat up the whitespaces from value, as per RFC 2616, chapter 4.2 "The field value MAY be preceded by any amount of LWS, though a single SP is preferred."*/ 00105 /*Codes_SRS_HTTP_HEADERS_02_002: [The LWS from the beginning of the value shall not be stored.] */ 00106 while ((value[0] == ' ') || (value[0] == '\t') || (value[0] == '\r') || (value[0] == '\n')) 00107 { 00108 value++; 00109 } 00110 00111 if (!replace && (existingValue != NULL)) 00112 { 00113 size_t existingValueLen = strlen(existingValue); 00114 size_t valueLen = strlen(value); 00115 char* newValue = (char*)malloc(sizeof(char) * (existingValueLen + /*COMMA_AND_SPACE_LENGTH*/ 2 + valueLen + /*EOL*/ 1)); 00116 if (newValue == NULL) 00117 { 00118 /*Codes_SRS_HTTP_HEADERS_99_015:[ The function shall return HTTP_HEADERS_ALLOC_FAILED when an internal request to allocate memory fails.]*/ 00119 result = HTTP_HEADERS_ALLOC_FAILED; 00120 LogError("failed to malloc , result= %s", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00121 } 00122 else 00123 { 00124 char* runNewValue; 00125 /*Codes_SRS_HTTP_HEADERS_99_017:[ If the name already exists in the collection of headers, the function shall concatenate the new value after the existing value, separated by a comma and a space as in: old-value+", "+new-value.]*/ 00126 (void)memcpy(newValue, existingValue, existingValueLen); 00127 runNewValue = newValue + existingValueLen; 00128 (*runNewValue++) = ','; 00129 (*runNewValue++) = ' '; 00130 (void)memcpy(runNewValue, value, valueLen + /*EOL*/ 1); 00131 00132 /*Codes_SRS_HTTP_HEADERS_99_016:[ The function shall store the name:value pair in such a way that when later retrieved by a call to GetHeader it will return a string that shall strcmp equal to the name+": "+value.]*/ 00133 if (Map_AddOrUpdate(handleData->headers, name, newValue) != MAP_OK) 00134 { 00135 /*Codes_SRS_HTTP_HEADERS_99_015:[ The function shall return HTTP_HEADERS_ALLOC_FAILED when an internal request to allocate memory fails.]*/ 00136 result = HTTP_HEADERS_ERROR; 00137 LogError("failed to Map_AddOrUpdate, result= %s", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00138 } 00139 else 00140 { 00141 /*Codes_SRS_HTTP_HEADERS_99_013:[ The function shall return HTTP_HEADERS_OK when execution is successful.]*/ 00142 result = HTTP_HEADERS_OK; 00143 } 00144 free(newValue); 00145 } 00146 } 00147 else 00148 { 00149 /*Codes_SRS_HTTP_HEADERS_99_016:[ The function shall store the name:value pair in such a way that when later retrieved by a call to GetHeader it will return a string that shall strcmp equal to the name+": "+value.]*/ 00150 if (Map_AddOrUpdate(handleData->headers, name, value) != MAP_OK) 00151 { 00152 /*Codes_SRS_HTTP_HEADERS_99_015:[ The function shall return HTTP_HEADERS_ALLOC_FAILED when an internal request to allocate memory fails.]*/ 00153 result = HTTP_HEADERS_ALLOC_FAILED; 00154 LogError("failed to Map_AddOrUpdate, result= %s", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00155 } 00156 else 00157 { 00158 result = HTTP_HEADERS_OK; 00159 } 00160 } 00161 } 00162 } 00163 00164 return result; 00165 } 00166 00167 HTTP_HEADERS_RESULT HTTPHeaders_AddHeaderNameValuePair(HTTP_HEADERS_HANDLE httpHeadersHandle, const char* name, const char* value) 00168 { 00169 return headers_ReplaceHeaderNameValuePair(httpHeadersHandle, name, value, false); 00170 } 00171 00172 /* Codes_SRS_HTTP_HEADERS_06_001: [This API will perform exactly as HTTPHeaders_AddHeaderNameValuePair except that if the header name already exists the already existing value will be replaced as opposed to concatenated to.] */ 00173 HTTP_HEADERS_RESULT HTTPHeaders_ReplaceHeaderNameValuePair(HTTP_HEADERS_HANDLE httpHeadersHandle, const char* name, const char* value) 00174 { 00175 return headers_ReplaceHeaderNameValuePair(httpHeadersHandle, name, value, true); 00176 } 00177 00178 00179 const char* HTTPHeaders_FindHeaderValue(HTTP_HEADERS_HANDLE httpHeadersHandle, const char* name) 00180 { 00181 const char* result; 00182 /*Codes_SRS_HTTP_HEADERS_99_022:[ The return value shall be NULL if name parameter is NULL or if httpHeadersHandle is NULL]*/ 00183 if ( 00184 (httpHeadersHandle == NULL) || 00185 (name == NULL) 00186 ) 00187 { 00188 result = NULL; 00189 } 00190 else 00191 { 00192 /*Codes_SRS_HTTP_HEADERS_99_018:[ Calling this API shall retrieve the value for a previously stored name.]*/ 00193 /*Codes_SRS_HTTP_HEADERS_99_020:[ The return value shall be different than NULL when the name matches the name of a previously stored name:value pair.] */ 00194 /*Codes_SRS_HTTP_HEADERS_99_021:[ In this case the return value shall point to a string that shall strcmp equal to the original stored string.]*/ 00195 HTTP_HEADERS_HANDLE_DATA* handleData = (HTTP_HEADERS_HANDLE_DATA*)httpHeadersHandle; 00196 result = Map_GetValueFromKey(handleData->headers, name); 00197 } 00198 return result; 00199 00200 } 00201 00202 HTTP_HEADERS_RESULT HTTPHeaders_GetHeaderCount(HTTP_HEADERS_HANDLE handle, size_t* headerCount) 00203 { 00204 HTTP_HEADERS_RESULT result; 00205 /*Codes_SRS_HTTP_HEADERS_99_024:[ The function shall return HTTP_HEADERS_INVALID_ARG when an invalid handle is passed.]*/ 00206 /*Codes_SRS_HTTP_HEADERS_99_025:[ The function shall return HTTP_HEADERS_INVALID_ARG when headersCount is NULL.]*/ 00207 if ((handle == NULL) || 00208 (headerCount == NULL)) 00209 { 00210 result = HTTP_HEADERS_INVALID_ARG; 00211 LogError("(result = %s)", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00212 } 00213 else 00214 { 00215 HTTP_HEADERS_HANDLE_DATA *handleData = (HTTP_HEADERS_HANDLE_DATA *)handle; 00216 const char*const* keys; 00217 const char*const* values; 00218 /*Codes_SRS_HTTP_HEADERS_99_023:[ Calling this API shall provide the number of stored headers.]*/ 00219 if (Map_GetInternals(handleData->headers, &keys, &values, headerCount) != MAP_OK) 00220 { 00221 /*Codes_SRS_HTTP_HEADERS_99_037:[ The function shall return HTTP_HEADERS_ERROR when an internal error occurs.]*/ 00222 result = HTTP_HEADERS_ERROR; 00223 LogError("Map_GetInternals failed, result= %s", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00224 } 00225 else 00226 { 00227 /*Codes_SRS_HTTP_HEADERS_99_026:[ The function shall write in *headersCount the number of currently stored headers and shall return HTTP_HEADERS_OK]*/ 00228 result = HTTP_HEADERS_OK; 00229 } 00230 } 00231 00232 return result; 00233 } 00234 00235 /*produces a string in *destination that is equal to name: value*/ 00236 HTTP_HEADERS_RESULT HTTPHeaders_GetHeader(HTTP_HEADERS_HANDLE handle, size_t index, char** destination) 00237 { 00238 HTTP_HEADERS_RESULT result = HTTP_HEADERS_OK; 00239 00240 /*Codes_SRS_HTTP_HEADERS_99_028:[ The function shall return NULL if the handle is invalid.]*/ 00241 /*Codes_SRS_HTTP_HEADERS_99_032:[ The function shall return HTTP_HEADERS_INVALID_ARG if the destination is NULL]*/ 00242 if ( 00243 (handle == NULL) || 00244 (destination == NULL) 00245 ) 00246 { 00247 result = HTTP_HEADERS_INVALID_ARG; 00248 LogError("invalid arg (NULL), result= %s", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00249 } 00250 /*Codes_SRS_HTTP_HEADERS_99_029:[ The function shall return HTTP_HEADERS_INVALID_ARG if index is not valid (for example, out of range) for the currently stored headers.]*/ 00251 else 00252 { 00253 HTTP_HEADERS_HANDLE_DATA* handleData = (HTTP_HEADERS_HANDLE_DATA*)handle; 00254 const char*const* keys; 00255 const char*const* values; 00256 size_t headerCount; 00257 if (Map_GetInternals(handleData->headers, &keys, &values, &headerCount) != MAP_OK) 00258 { 00259 /*Codes_SRS_HTTP_HEADERS_99_034:[ The function shall return HTTP_HEADERS_ERROR when an internal error occurs]*/ 00260 result = HTTP_HEADERS_ERROR; 00261 LogError("Map_GetInternals failed, result= %s", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00262 } 00263 else 00264 { 00265 /*Codes_SRS_HTTP_HEADERS_99_029:[ The function shall return HTTP_HEADERS_INVALID_ARG if index is not valid (for example, out of range) for the currently stored headers.]*/ 00266 if (index >= headerCount) 00267 { 00268 result = HTTP_HEADERS_INVALID_ARG; 00269 LogError("index out of bounds, result= %s", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00270 } 00271 else 00272 { 00273 size_t keyLen = strlen(keys[index]); 00274 size_t valueLen = strlen(values[index]); 00275 *destination = (char*)malloc(sizeof(char) * (keyLen + /*COLON_AND_SPACE_LENGTH*/ 2 + valueLen + /*EOL*/ 1)); 00276 if (*destination == NULL) 00277 { 00278 /*Codes_SRS_HTTP_HEADERS_99_034:[ The function shall return HTTP_HEADERS_ERROR when an internal error occurs]*/ 00279 result = HTTP_HEADERS_ERROR; 00280 LogError("unable to malloc, result= %s", ENUM_TO_STRING(HTTP_HEADERS_RESULT, result)); 00281 } 00282 else 00283 { 00284 /*Codes_SRS_HTTP_HEADERS_99_016:[ The function shall store the name:value pair in such a way that when later retrieved by a call to GetHeader it will return a string that shall strcmp equal to the name+": "+value.]*/ 00285 /*Codes_SRS_HTTP_HEADERS_99_027:[ Calling this API shall produce the string value+": "+pair) for the index header in the *destination parameter.]*/ 00286 char* runDestination = (*destination); 00287 (void)memcpy(runDestination, keys[index], keyLen); 00288 runDestination += keyLen; 00289 (*runDestination++) = ':'; 00290 (*runDestination++) = ' '; 00291 (void)memcpy(runDestination, values[index], valueLen + /*EOL*/ 1); 00292 /*Codes_SRS_HTTP_HEADERS_99_035:[ The function shall return HTTP_HEADERS_OK when the function executed without error.]*/ 00293 result = HTTP_HEADERS_OK; 00294 } 00295 } 00296 } 00297 } 00298 00299 return result; 00300 } 00301 00302 HTTP_HEADERS_HANDLE HTTPHeaders_Clone(HTTP_HEADERS_HANDLE handle) 00303 { 00304 HTTP_HEADERS_HANDLE_DATA* result; 00305 /*Codes_SRS_HTTP_HEADERS_02_003: [If handle is NULL then HTTPHeaders_Clone shall return NULL.] */ 00306 if (handle == NULL) 00307 { 00308 result = NULL; 00309 } 00310 else 00311 { 00312 /*Codes_SRS_HTTP_HEADERS_02_004: [Otherwise HTTPHeaders_Clone shall clone the content of handle to a new handle.] */ 00313 result = (HTTP_HEADERS_HANDLE_DATA*)malloc(sizeof(HTTP_HEADERS_HANDLE_DATA)); 00314 if (result == NULL) 00315 { 00316 /*Codes_SRS_HTTP_HEADERS_02_005: [If cloning fails for any reason, then HTTPHeaders_Clone shall return NULL.] */ 00317 } 00318 else 00319 { 00320 HTTP_HEADERS_HANDLE_DATA* handleData = handle; 00321 result->headers = Map_Clone(handleData->headers); 00322 if (result->headers == NULL) 00323 { 00324 /*Codes_SRS_HTTP_HEADERS_02_005: [If cloning fails for any reason, then HTTPHeaders_Clone shall return NULL.] */ 00325 free(result); 00326 result = NULL; 00327 } 00328 else 00329 { 00330 /*all is fine*/ 00331 } 00332 } 00333 } 00334 return result; 00335 }
Generated on Wed Jul 13 2022 23:38:02 by
1.7.2
