Demo using MBED TLS
Dependencies: EthernetInterface NTPClient iothub_amqp_transport iothub_client mbed-rtos mbed
Fork of iothub_client_sample_amqp by
azure_c_shared_utility/httpapiex.c@58:f50b97b08851, 2017-01-05 (annotated)
- Committer:
- markrad
- Date:
- Thu Jan 05 00:20:03 2017 +0000
- Revision:
- 58:f50b97b08851
Sample using MBED TLS
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
markrad | 58:f50b97b08851 | 1 | // Copyright (c) Microsoft. All rights reserved. |
markrad | 58:f50b97b08851 | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
markrad | 58:f50b97b08851 | 3 | |
markrad | 58:f50b97b08851 | 4 | #include <stdlib.h> |
markrad | 58:f50b97b08851 | 5 | #ifdef _CRTDBG_MAP_ALLOC |
markrad | 58:f50b97b08851 | 6 | #include <crtdbg.h> |
markrad | 58:f50b97b08851 | 7 | #endif |
markrad | 58:f50b97b08851 | 8 | #include "azure_c_shared_utility/gballoc.h" |
markrad | 58:f50b97b08851 | 9 | |
markrad | 58:f50b97b08851 | 10 | #include "azure_c_shared_utility/httpapiex.h" |
markrad | 58:f50b97b08851 | 11 | #include "azure_c_shared_utility/xlogging.h" |
markrad | 58:f50b97b08851 | 12 | #include "azure_c_shared_utility/strings.h" |
markrad | 58:f50b97b08851 | 13 | #include "azure_c_shared_utility/crt_abstractions.h" |
markrad | 58:f50b97b08851 | 14 | #include "azure_c_shared_utility/vector.h" |
markrad | 58:f50b97b08851 | 15 | |
markrad | 58:f50b97b08851 | 16 | typedef struct HTTPAPIEX_SAVED_OPTION_TAG |
markrad | 58:f50b97b08851 | 17 | { |
markrad | 58:f50b97b08851 | 18 | const char* optionName; |
markrad | 58:f50b97b08851 | 19 | const void* value; |
markrad | 58:f50b97b08851 | 20 | }HTTPAPIEX_SAVED_OPTION; |
markrad | 58:f50b97b08851 | 21 | |
markrad | 58:f50b97b08851 | 22 | typedef struct HTTPAPIEX_HANDLE_DATA_TAG |
markrad | 58:f50b97b08851 | 23 | { |
markrad | 58:f50b97b08851 | 24 | STRING_HANDLE hostName; |
markrad | 58:f50b97b08851 | 25 | int k; |
markrad | 58:f50b97b08851 | 26 | HTTP_HANDLE httpHandle; |
markrad | 58:f50b97b08851 | 27 | VECTOR_HANDLE savedOptions; |
markrad | 58:f50b97b08851 | 28 | }HTTPAPIEX_HANDLE_DATA; |
markrad | 58:f50b97b08851 | 29 | |
markrad | 58:f50b97b08851 | 30 | DEFINE_ENUM_STRINGS(HTTPAPIEX_RESULT, HTTPAPIEX_RESULT_VALUES); |
markrad | 58:f50b97b08851 | 31 | |
markrad | 58:f50b97b08851 | 32 | #define LOG_HTTAPIEX_ERROR() LogError("error code = %s", ENUM_TO_STRING(HTTPAPIEX_RESULT, result)) |
markrad | 58:f50b97b08851 | 33 | |
markrad | 58:f50b97b08851 | 34 | HTTPAPIEX_HANDLE HTTPAPIEX_Create(const char* hostName) |
markrad | 58:f50b97b08851 | 35 | { |
markrad | 58:f50b97b08851 | 36 | HTTPAPIEX_HANDLE result; |
markrad | 58:f50b97b08851 | 37 | /*Codes_SRS_HTTPAPIEX_02_001: [If parameter hostName is NULL then HTTPAPIEX_Create shall return NULL.]*/ |
markrad | 58:f50b97b08851 | 38 | if (hostName == NULL) |
markrad | 58:f50b97b08851 | 39 | { |
markrad | 58:f50b97b08851 | 40 | LogError("invalid (NULL) parameter"); |
markrad | 58:f50b97b08851 | 41 | result = NULL; |
markrad | 58:f50b97b08851 | 42 | } |
markrad | 58:f50b97b08851 | 43 | else |
markrad | 58:f50b97b08851 | 44 | { |
markrad | 58:f50b97b08851 | 45 | /*Codes_SRS_HTTPAPIEX_02_005: [If creating the handle fails for any reason, then HTTAPIEX_Create shall return NULL.] */ |
markrad | 58:f50b97b08851 | 46 | HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)malloc(sizeof(HTTPAPIEX_HANDLE_DATA)); |
markrad | 58:f50b97b08851 | 47 | if (handleData == NULL) |
markrad | 58:f50b97b08851 | 48 | { |
markrad | 58:f50b97b08851 | 49 | LogError("malloc failed."); |
markrad | 58:f50b97b08851 | 50 | result = NULL; |
markrad | 58:f50b97b08851 | 51 | } |
markrad | 58:f50b97b08851 | 52 | else |
markrad | 58:f50b97b08851 | 53 | { |
markrad | 58:f50b97b08851 | 54 | /*Codes_SRS_HTTPAPIEX_02_002: [Parameter hostName shall be saved.]*/ |
markrad | 58:f50b97b08851 | 55 | handleData->hostName = STRING_construct(hostName); |
markrad | 58:f50b97b08851 | 56 | if (handleData->hostName == NULL) |
markrad | 58:f50b97b08851 | 57 | { |
markrad | 58:f50b97b08851 | 58 | free(handleData); |
markrad | 58:f50b97b08851 | 59 | LogError("unable to STRING_construct"); |
markrad | 58:f50b97b08851 | 60 | result = NULL; |
markrad | 58:f50b97b08851 | 61 | } |
markrad | 58:f50b97b08851 | 62 | else |
markrad | 58:f50b97b08851 | 63 | { |
markrad | 58:f50b97b08851 | 64 | /*Codes_SRS_HTTPAPIEX_02_004: [Otherwise, HTTPAPIEX_Create shall return a HTTAPIEX_HANDLE suitable for further calls to the module.] */ |
markrad | 58:f50b97b08851 | 65 | handleData->savedOptions = VECTOR_create(sizeof(HTTPAPIEX_SAVED_OPTION)); |
markrad | 58:f50b97b08851 | 66 | if (handleData->savedOptions == NULL) |
markrad | 58:f50b97b08851 | 67 | { |
markrad | 58:f50b97b08851 | 68 | STRING_delete(handleData->hostName); |
markrad | 58:f50b97b08851 | 69 | free(handleData); |
markrad | 58:f50b97b08851 | 70 | result = NULL; |
markrad | 58:f50b97b08851 | 71 | } |
markrad | 58:f50b97b08851 | 72 | else |
markrad | 58:f50b97b08851 | 73 | { |
markrad | 58:f50b97b08851 | 74 | handleData->k = -1; |
markrad | 58:f50b97b08851 | 75 | handleData->httpHandle = NULL; |
markrad | 58:f50b97b08851 | 76 | result = handleData; |
markrad | 58:f50b97b08851 | 77 | } |
markrad | 58:f50b97b08851 | 78 | } |
markrad | 58:f50b97b08851 | 79 | } |
markrad | 58:f50b97b08851 | 80 | } |
markrad | 58:f50b97b08851 | 81 | return result; |
markrad | 58:f50b97b08851 | 82 | } |
markrad | 58:f50b97b08851 | 83 | |
markrad | 58:f50b97b08851 | 84 | /*this function builds the default request http headers if none are specified*/ |
markrad | 58:f50b97b08851 | 85 | /*returns 0 if no error*/ |
markrad | 58:f50b97b08851 | 86 | /*any other code is error*/ |
markrad | 58:f50b97b08851 | 87 | static int buildRequestHttpHeadersHandle(HTTPAPIEX_HANDLE_DATA *handleData, BUFFER_HANDLE requestContent, HTTP_HEADERS_HANDLE originalRequestHttpHeadersHandle, bool* isOriginalRequestHttpHeadersHandle, HTTP_HEADERS_HANDLE* toBeUsedRequestHttpHeadersHandle) |
markrad | 58:f50b97b08851 | 88 | { |
markrad | 58:f50b97b08851 | 89 | int result; |
markrad | 58:f50b97b08851 | 90 | |
markrad | 58:f50b97b08851 | 91 | |
markrad | 58:f50b97b08851 | 92 | if (originalRequestHttpHeadersHandle != NULL) |
markrad | 58:f50b97b08851 | 93 | { |
markrad | 58:f50b97b08851 | 94 | *toBeUsedRequestHttpHeadersHandle = originalRequestHttpHeadersHandle; |
markrad | 58:f50b97b08851 | 95 | *isOriginalRequestHttpHeadersHandle = true; |
markrad | 58:f50b97b08851 | 96 | |
markrad | 58:f50b97b08851 | 97 | } |
markrad | 58:f50b97b08851 | 98 | else |
markrad | 58:f50b97b08851 | 99 | { |
markrad | 58:f50b97b08851 | 100 | /*Codes_SRS_HTTPAPIEX_02_009: [If parameter requestHttpHeadersHandle is NULL then HTTPAPIEX_ExecuteRequest shall allocate a temporary internal instance of HTTPHEADERS, shall add to that instance the following headers |
markrad | 58:f50b97b08851 | 101 | Host:{hostname} - as it was indicated by the call to HTTPAPIEX_Create API call |
markrad | 58:f50b97b08851 | 102 | Content-Length:the size of the requestContent parameter, and use this instance to all the subsequent calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.] |
markrad | 58:f50b97b08851 | 103 | */ |
markrad | 58:f50b97b08851 | 104 | *isOriginalRequestHttpHeadersHandle = false; |
markrad | 58:f50b97b08851 | 105 | *toBeUsedRequestHttpHeadersHandle = HTTPHeaders_Alloc(); |
markrad | 58:f50b97b08851 | 106 | } |
markrad | 58:f50b97b08851 | 107 | |
markrad | 58:f50b97b08851 | 108 | if (*toBeUsedRequestHttpHeadersHandle == NULL) |
markrad | 58:f50b97b08851 | 109 | { |
markrad | 58:f50b97b08851 | 110 | result = __LINE__; |
markrad | 58:f50b97b08851 | 111 | LogError("unable to HTTPHeaders_Alloc"); |
markrad | 58:f50b97b08851 | 112 | } |
markrad | 58:f50b97b08851 | 113 | else |
markrad | 58:f50b97b08851 | 114 | { |
markrad | 58:f50b97b08851 | 115 | char temp[22] = { 0 }; |
markrad | 58:f50b97b08851 | 116 | (void)size_tToString(temp, 22, BUFFER_length(requestContent)); /*cannot fail, MAX_uint64 has 19 digits*/ |
markrad | 58:f50b97b08851 | 117 | /*Codes_SRS_HTTPAPIEX_02_011: [If parameter requestHttpHeadersHandle is not NULL then HTTPAPIEX_ExecuteRequest shall create or update the following headers of the request: |
markrad | 58:f50b97b08851 | 118 | Host:{hostname} |
markrad | 58:f50b97b08851 | 119 | Content-Length:the size of the requestContent parameter, and shall use the so constructed HTTPHEADERS object to all calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.] |
markrad | 58:f50b97b08851 | 120 | */ |
markrad | 58:f50b97b08851 | 121 | /*Codes_SRS_HTTPAPIEX_02_009: [If parameter requestHttpHeadersHandle is NULL then HTTPAPIEX_ExecuteRequest shall allocate a temporary internal instance of HTTPHEADERS, shall add to that instance the following headers |
markrad | 58:f50b97b08851 | 122 | Host:{hostname} - as it was indicated by the call to HTTPAPIEX_Create API call |
markrad | 58:f50b97b08851 | 123 | Content-Length:the size of the requestContent parameter, and use this instance to all the subsequent calls to HTTPAPI_ExecuteRequest as parameter httpHeadersHandle.] |
markrad | 58:f50b97b08851 | 124 | */ |
markrad | 58:f50b97b08851 | 125 | if (!( |
markrad | 58:f50b97b08851 | 126 | (HTTPHeaders_ReplaceHeaderNameValuePair(*toBeUsedRequestHttpHeadersHandle, "Host", STRING_c_str(handleData->hostName)) == HTTP_HEADERS_OK) && |
markrad | 58:f50b97b08851 | 127 | (HTTPHeaders_ReplaceHeaderNameValuePair(*toBeUsedRequestHttpHeadersHandle, "Content-Length", temp) == HTTP_HEADERS_OK) |
markrad | 58:f50b97b08851 | 128 | )) |
markrad | 58:f50b97b08851 | 129 | { |
markrad | 58:f50b97b08851 | 130 | if (! *isOriginalRequestHttpHeadersHandle) |
markrad | 58:f50b97b08851 | 131 | { |
markrad | 58:f50b97b08851 | 132 | HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle); |
markrad | 58:f50b97b08851 | 133 | } |
markrad | 58:f50b97b08851 | 134 | *toBeUsedRequestHttpHeadersHandle = NULL; |
markrad | 58:f50b97b08851 | 135 | result = __LINE__; |
markrad | 58:f50b97b08851 | 136 | } |
markrad | 58:f50b97b08851 | 137 | else |
markrad | 58:f50b97b08851 | 138 | { |
markrad | 58:f50b97b08851 | 139 | result = 0; |
markrad | 58:f50b97b08851 | 140 | } |
markrad | 58:f50b97b08851 | 141 | } |
markrad | 58:f50b97b08851 | 142 | return result; |
markrad | 58:f50b97b08851 | 143 | } |
markrad | 58:f50b97b08851 | 144 | |
markrad | 58:f50b97b08851 | 145 | static int buildResponseHttpHeadersHandle(HTTP_HEADERS_HANDLE originalResponsetHttpHeadersHandle, bool* isOriginalResponseHttpHeadersHandle, HTTP_HEADERS_HANDLE* toBeUsedResponsetHttpHeadersHandle) |
markrad | 58:f50b97b08851 | 146 | { |
markrad | 58:f50b97b08851 | 147 | int result; |
markrad | 58:f50b97b08851 | 148 | if (originalResponsetHttpHeadersHandle == NULL) |
markrad | 58:f50b97b08851 | 149 | { |
markrad | 58:f50b97b08851 | 150 | if ((*toBeUsedResponsetHttpHeadersHandle = HTTPHeaders_Alloc()) == NULL) |
markrad | 58:f50b97b08851 | 151 | { |
markrad | 58:f50b97b08851 | 152 | result = __LINE__; |
markrad | 58:f50b97b08851 | 153 | } |
markrad | 58:f50b97b08851 | 154 | else |
markrad | 58:f50b97b08851 | 155 | { |
markrad | 58:f50b97b08851 | 156 | *isOriginalResponseHttpHeadersHandle = false; |
markrad | 58:f50b97b08851 | 157 | result = 0; |
markrad | 58:f50b97b08851 | 158 | } |
markrad | 58:f50b97b08851 | 159 | } |
markrad | 58:f50b97b08851 | 160 | else |
markrad | 58:f50b97b08851 | 161 | { |
markrad | 58:f50b97b08851 | 162 | *isOriginalResponseHttpHeadersHandle = true; |
markrad | 58:f50b97b08851 | 163 | *toBeUsedResponsetHttpHeadersHandle = originalResponsetHttpHeadersHandle; |
markrad | 58:f50b97b08851 | 164 | result = 0; |
markrad | 58:f50b97b08851 | 165 | } |
markrad | 58:f50b97b08851 | 166 | return result; |
markrad | 58:f50b97b08851 | 167 | } |
markrad | 58:f50b97b08851 | 168 | |
markrad | 58:f50b97b08851 | 169 | |
markrad | 58:f50b97b08851 | 170 | static int buildBufferIfNotExist(BUFFER_HANDLE originalRequestContent, bool* isOriginalRequestContent, BUFFER_HANDLE* toBeUsedRequestContent) |
markrad | 58:f50b97b08851 | 171 | { |
markrad | 58:f50b97b08851 | 172 | int result; |
markrad | 58:f50b97b08851 | 173 | if (originalRequestContent == NULL) |
markrad | 58:f50b97b08851 | 174 | { |
markrad | 58:f50b97b08851 | 175 | *toBeUsedRequestContent = BUFFER_new(); |
markrad | 58:f50b97b08851 | 176 | if (*toBeUsedRequestContent == NULL) |
markrad | 58:f50b97b08851 | 177 | { |
markrad | 58:f50b97b08851 | 178 | result = __LINE__; |
markrad | 58:f50b97b08851 | 179 | } |
markrad | 58:f50b97b08851 | 180 | else |
markrad | 58:f50b97b08851 | 181 | { |
markrad | 58:f50b97b08851 | 182 | *isOriginalRequestContent = false; |
markrad | 58:f50b97b08851 | 183 | result = 0; |
markrad | 58:f50b97b08851 | 184 | } |
markrad | 58:f50b97b08851 | 185 | } |
markrad | 58:f50b97b08851 | 186 | else |
markrad | 58:f50b97b08851 | 187 | { |
markrad | 58:f50b97b08851 | 188 | *isOriginalRequestContent = true; |
markrad | 58:f50b97b08851 | 189 | *toBeUsedRequestContent = originalRequestContent; |
markrad | 58:f50b97b08851 | 190 | result = 0; |
markrad | 58:f50b97b08851 | 191 | } |
markrad | 58:f50b97b08851 | 192 | return result; |
markrad | 58:f50b97b08851 | 193 | } |
markrad | 58:f50b97b08851 | 194 | |
markrad | 58:f50b97b08851 | 195 | static unsigned int dummyStatusCode; |
markrad | 58:f50b97b08851 | 196 | |
markrad | 58:f50b97b08851 | 197 | static int buildAllRequests(HTTPAPIEX_HANDLE_DATA* handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, |
markrad | 58:f50b97b08851 | 198 | HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode, |
markrad | 58:f50b97b08851 | 199 | HTTP_HEADERS_HANDLE responseHttpHeadersHandle, BUFFER_HANDLE responseContent, |
markrad | 58:f50b97b08851 | 200 | |
markrad | 58:f50b97b08851 | 201 | const char** toBeUsedRelativePath, |
markrad | 58:f50b97b08851 | 202 | HTTP_HEADERS_HANDLE *toBeUsedRequestHttpHeadersHandle, bool *isOriginalRequestHttpHeadersHandle, |
markrad | 58:f50b97b08851 | 203 | BUFFER_HANDLE *toBeUsedRequestContent, bool *isOriginalRequestContent, |
markrad | 58:f50b97b08851 | 204 | unsigned int** toBeUsedStatusCode, |
markrad | 58:f50b97b08851 | 205 | HTTP_HEADERS_HANDLE *toBeUsedResponseHttpHeadersHandle, bool *isOriginalResponseHttpHeadersHandle, |
markrad | 58:f50b97b08851 | 206 | BUFFER_HANDLE *toBeUsedResponseContent, bool *isOriginalResponseContent) |
markrad | 58:f50b97b08851 | 207 | { |
markrad | 58:f50b97b08851 | 208 | int result; |
markrad | 58:f50b97b08851 | 209 | (void)requestType; |
markrad | 58:f50b97b08851 | 210 | /*Codes_SRS_HTTPAPIEX_02_013: [If requestContent is NULL then HTTPAPIEX_ExecuteRequest shall behave as if a buffer of zero size would have been used, that is, it shall call HTTPAPI_ExecuteRequest with parameter content = NULL and contentLength = 0.]*/ |
markrad | 58:f50b97b08851 | 211 | /*Codes_SRS_HTTPAPIEX_02_014: [If requestContent is not NULL then its content and its size shall be used for parameters content and contentLength of HTTPAPI_ExecuteRequest.] */ |
markrad | 58:f50b97b08851 | 212 | if (buildBufferIfNotExist(requestContent, isOriginalRequestContent, toBeUsedRequestContent) != 0) |
markrad | 58:f50b97b08851 | 213 | { |
markrad | 58:f50b97b08851 | 214 | result = __LINE__; |
markrad | 58:f50b97b08851 | 215 | LogError("unable to build the request content"); |
markrad | 58:f50b97b08851 | 216 | } |
markrad | 58:f50b97b08851 | 217 | else |
markrad | 58:f50b97b08851 | 218 | { |
markrad | 58:f50b97b08851 | 219 | if (buildRequestHttpHeadersHandle(handle, *toBeUsedRequestContent, requestHttpHeadersHandle, isOriginalRequestHttpHeadersHandle, toBeUsedRequestHttpHeadersHandle) != 0) |
markrad | 58:f50b97b08851 | 220 | { |
markrad | 58:f50b97b08851 | 221 | /*Codes_SRS_HTTPAPIEX_02_010: [If any of the operations in SRS_HTTAPIEX_02_009 fails, then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */ |
markrad | 58:f50b97b08851 | 222 | result = __LINE__; |
markrad | 58:f50b97b08851 | 223 | if (*isOriginalRequestContent == false) |
markrad | 58:f50b97b08851 | 224 | { |
markrad | 58:f50b97b08851 | 225 | BUFFER_delete(*toBeUsedRequestContent); |
markrad | 58:f50b97b08851 | 226 | } |
markrad | 58:f50b97b08851 | 227 | LogError("unable to build the request http headers handle"); |
markrad | 58:f50b97b08851 | 228 | } |
markrad | 58:f50b97b08851 | 229 | else |
markrad | 58:f50b97b08851 | 230 | { |
markrad | 58:f50b97b08851 | 231 | /*Codes_SRS_HTTPAPIEX_02_008: [If parameter relativePath is NULL then HTTPAPIEX_INVALID_ARG shall not assume a relative path - that is, it will assume an empty path ("").] */ |
markrad | 58:f50b97b08851 | 232 | if (relativePath == NULL) |
markrad | 58:f50b97b08851 | 233 | { |
markrad | 58:f50b97b08851 | 234 | *toBeUsedRelativePath = ""; |
markrad | 58:f50b97b08851 | 235 | } |
markrad | 58:f50b97b08851 | 236 | else |
markrad | 58:f50b97b08851 | 237 | { |
markrad | 58:f50b97b08851 | 238 | *toBeUsedRelativePath = relativePath; |
markrad | 58:f50b97b08851 | 239 | } |
markrad | 58:f50b97b08851 | 240 | |
markrad | 58:f50b97b08851 | 241 | /*Codes_SRS_HTTPAPIEX_02_015: [If statusCode is NULL then HTTPAPIEX_ExecuteRequest shall not write in statusCode the HTTP status code, and it will use a temporary internal int for parameter statusCode to the calls of HTTPAPI_ExecuteRequest.] */ |
markrad | 58:f50b97b08851 | 242 | if (statusCode == NULL) |
markrad | 58:f50b97b08851 | 243 | { |
markrad | 58:f50b97b08851 | 244 | /*Codes_SRS_HTTPAPIEX_02_016: [If statusCode is not NULL then If statusCode is NULL then HTTPAPIEX_ExecuteRequest shall use it for parameter statusCode to the calls of HTTPAPI_ExecuteRequest.] */ |
markrad | 58:f50b97b08851 | 245 | *toBeUsedStatusCode = &dummyStatusCode; |
markrad | 58:f50b97b08851 | 246 | } |
markrad | 58:f50b97b08851 | 247 | else |
markrad | 58:f50b97b08851 | 248 | { |
markrad | 58:f50b97b08851 | 249 | *toBeUsedStatusCode = statusCode; |
markrad | 58:f50b97b08851 | 250 | } |
markrad | 58:f50b97b08851 | 251 | |
markrad | 58:f50b97b08851 | 252 | /*Codes_SRS_HTTPAPIEX_02_017: [If responseHeaders handle is NULL then HTTPAPIEX_ExecuteRequest shall create a temporary internal instance of HTTPHEADERS object and use that for responseHeaders parameter of HTTPAPI_ExecuteRequest call.] */ |
markrad | 58:f50b97b08851 | 253 | /*Codes_SRS_HTTPAPIEX_02_019: [If responseHeaders is not NULL, then then HTTPAPIEX_ExecuteRequest shall use that object as parameter responseHeaders of HTTPAPI_ExecuteRequest call.] */ |
markrad | 58:f50b97b08851 | 254 | if (buildResponseHttpHeadersHandle(responseHttpHeadersHandle, isOriginalResponseHttpHeadersHandle, toBeUsedResponseHttpHeadersHandle) != 0) |
markrad | 58:f50b97b08851 | 255 | { |
markrad | 58:f50b97b08851 | 256 | /*Codes_SRS_HTTPAPIEX_02_018: [If creating the temporary http headers in SRS_HTTPAPIEX_02_017 fails then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */ |
markrad | 58:f50b97b08851 | 257 | result = __LINE__; |
markrad | 58:f50b97b08851 | 258 | if (*isOriginalRequestContent == false) |
markrad | 58:f50b97b08851 | 259 | { |
markrad | 58:f50b97b08851 | 260 | BUFFER_delete(*toBeUsedRequestContent); |
markrad | 58:f50b97b08851 | 261 | } |
markrad | 58:f50b97b08851 | 262 | if (*isOriginalRequestHttpHeadersHandle == false) |
markrad | 58:f50b97b08851 | 263 | { |
markrad | 58:f50b97b08851 | 264 | HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle); |
markrad | 58:f50b97b08851 | 265 | } |
markrad | 58:f50b97b08851 | 266 | LogError("unable to build response content"); |
markrad | 58:f50b97b08851 | 267 | } |
markrad | 58:f50b97b08851 | 268 | else |
markrad | 58:f50b97b08851 | 269 | { |
markrad | 58:f50b97b08851 | 270 | /*Codes_SRS_HTTPAPIEX_02_020: [If responseContent is NULL then HTTPAPIEX_ExecuteRequest shall create a temporary internal BUFFER object and use that as parameter responseContent of HTTPAPI_ExecuteRequest call.] */ |
markrad | 58:f50b97b08851 | 271 | /*Codes_SRS_HTTPAPIEX_02_022: [If responseContent is not NULL then HTTPAPIEX_ExecuteRequest use that as parameter responseContent of HTTPAPI_ExecuteRequest call.] */ |
markrad | 58:f50b97b08851 | 272 | if (buildBufferIfNotExist(responseContent, isOriginalResponseContent, toBeUsedResponseContent) != 0) |
markrad | 58:f50b97b08851 | 273 | { |
markrad | 58:f50b97b08851 | 274 | /*Codes_SRS_HTTPAPIEX_02_021: [If creating the BUFFER_HANDLE in SRS_HTTPAPIEX_02_020 fails, then HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_ERROR.] */ |
markrad | 58:f50b97b08851 | 275 | result = __LINE__; |
markrad | 58:f50b97b08851 | 276 | if (*isOriginalRequestContent == false) |
markrad | 58:f50b97b08851 | 277 | { |
markrad | 58:f50b97b08851 | 278 | BUFFER_delete(*toBeUsedRequestContent); |
markrad | 58:f50b97b08851 | 279 | } |
markrad | 58:f50b97b08851 | 280 | if (*isOriginalRequestHttpHeadersHandle == false) |
markrad | 58:f50b97b08851 | 281 | { |
markrad | 58:f50b97b08851 | 282 | HTTPHeaders_Free(*toBeUsedRequestHttpHeadersHandle); |
markrad | 58:f50b97b08851 | 283 | } |
markrad | 58:f50b97b08851 | 284 | if (*isOriginalResponseHttpHeadersHandle == false) |
markrad | 58:f50b97b08851 | 285 | { |
markrad | 58:f50b97b08851 | 286 | HTTPHeaders_Free(*toBeUsedResponseHttpHeadersHandle); |
markrad | 58:f50b97b08851 | 287 | } |
markrad | 58:f50b97b08851 | 288 | LogError("unable to build response content"); |
markrad | 58:f50b97b08851 | 289 | } |
markrad | 58:f50b97b08851 | 290 | else |
markrad | 58:f50b97b08851 | 291 | { |
markrad | 58:f50b97b08851 | 292 | result = 0; |
markrad | 58:f50b97b08851 | 293 | } |
markrad | 58:f50b97b08851 | 294 | } |
markrad | 58:f50b97b08851 | 295 | } |
markrad | 58:f50b97b08851 | 296 | } |
markrad | 58:f50b97b08851 | 297 | return result; |
markrad | 58:f50b97b08851 | 298 | } |
markrad | 58:f50b97b08851 | 299 | |
markrad | 58:f50b97b08851 | 300 | HTTPAPIEX_RESULT HTTPAPIEX_ExecuteRequest(HTTPAPIEX_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, |
markrad | 58:f50b97b08851 | 301 | HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode, |
markrad | 58:f50b97b08851 | 302 | HTTP_HEADERS_HANDLE responseHttpHeadersHandle, BUFFER_HANDLE responseContent) |
markrad | 58:f50b97b08851 | 303 | { |
markrad | 58:f50b97b08851 | 304 | HTTPAPIEX_RESULT result; |
markrad | 58:f50b97b08851 | 305 | /*Codes_SRS_HTTPAPIEX_02_006: [If parameter handle is NULL then HTTPAPIEX_ExecuteRequest shall fail and return HTTPAPIEX_INVALID_ARG.]*/ |
markrad | 58:f50b97b08851 | 306 | if (handle == NULL) |
markrad | 58:f50b97b08851 | 307 | { |
markrad | 58:f50b97b08851 | 308 | result = HTTPAPIEX_INVALID_ARG; |
markrad | 58:f50b97b08851 | 309 | LOG_HTTAPIEX_ERROR(); |
markrad | 58:f50b97b08851 | 310 | } |
markrad | 58:f50b97b08851 | 311 | else |
markrad | 58:f50b97b08851 | 312 | { |
markrad | 58:f50b97b08851 | 313 | /*Codes_SRS_HTTPAPIEX_02_007: [If parameter requestType does not indicate a valid request, HTTPAPIEX_ExecuteRequest shall fail and return HTTPAPIEX_INVALID_ARG.] */ |
markrad | 58:f50b97b08851 | 314 | if (requestType >= COUNT_ARG(HTTPAPI_REQUEST_TYPE_VALUES)) |
markrad | 58:f50b97b08851 | 315 | { |
markrad | 58:f50b97b08851 | 316 | result = HTTPAPIEX_INVALID_ARG; |
markrad | 58:f50b97b08851 | 317 | LOG_HTTAPIEX_ERROR(); |
markrad | 58:f50b97b08851 | 318 | } |
markrad | 58:f50b97b08851 | 319 | else |
markrad | 58:f50b97b08851 | 320 | { |
markrad | 58:f50b97b08851 | 321 | HTTPAPIEX_HANDLE_DATA *handleData = (HTTPAPIEX_HANDLE_DATA *)handle; |
markrad | 58:f50b97b08851 | 322 | |
markrad | 58:f50b97b08851 | 323 | /*call to buildAll*/ |
markrad | 58:f50b97b08851 | 324 | const char* toBeUsedRelativePath; |
markrad | 58:f50b97b08851 | 325 | HTTP_HEADERS_HANDLE toBeUsedRequestHttpHeadersHandle; bool isOriginalRequestHttpHeadersHandle; |
markrad | 58:f50b97b08851 | 326 | BUFFER_HANDLE toBeUsedRequestContent; bool isOriginalRequestContent; |
markrad | 58:f50b97b08851 | 327 | unsigned int* toBeUsedStatusCode; |
markrad | 58:f50b97b08851 | 328 | HTTP_HEADERS_HANDLE toBeUsedResponseHttpHeadersHandle; bool isOriginalResponseHttpHeadersHandle; |
markrad | 58:f50b97b08851 | 329 | BUFFER_HANDLE toBeUsedResponseContent; bool isOriginalResponseContent; |
markrad | 58:f50b97b08851 | 330 | |
markrad | 58:f50b97b08851 | 331 | if (buildAllRequests(handleData, requestType, relativePath, requestHttpHeadersHandle, requestContent, statusCode, responseHttpHeadersHandle, responseContent, |
markrad | 58:f50b97b08851 | 332 | &toBeUsedRelativePath, |
markrad | 58:f50b97b08851 | 333 | &toBeUsedRequestHttpHeadersHandle, &isOriginalRequestHttpHeadersHandle, |
markrad | 58:f50b97b08851 | 334 | &toBeUsedRequestContent, &isOriginalRequestContent, |
markrad | 58:f50b97b08851 | 335 | &toBeUsedStatusCode, |
markrad | 58:f50b97b08851 | 336 | &toBeUsedResponseHttpHeadersHandle, &isOriginalResponseHttpHeadersHandle, |
markrad | 58:f50b97b08851 | 337 | &toBeUsedResponseContent, &isOriginalResponseContent) != 0) |
markrad | 58:f50b97b08851 | 338 | { |
markrad | 58:f50b97b08851 | 339 | result = HTTPAPIEX_ERROR; |
markrad | 58:f50b97b08851 | 340 | LOG_HTTAPIEX_ERROR(); |
markrad | 58:f50b97b08851 | 341 | } |
markrad | 58:f50b97b08851 | 342 | else |
markrad | 58:f50b97b08851 | 343 | { |
markrad | 58:f50b97b08851 | 344 | |
markrad | 58:f50b97b08851 | 345 | /*Codes_SRS_HTTPAPIEX_02_023: [HTTPAPIEX_ExecuteRequest shall try to execute the HTTP call by ensuring the following API call sequence is respected:]*/ |
markrad | 58:f50b97b08851 | 346 | /*Codes_SRS_HTTPAPIEX_02_024: [If any point in the sequence fails, HTTPAPIEX_ExecuteRequest shall attempt to recover by going back to the previous step and retrying that step.]*/ |
markrad | 58:f50b97b08851 | 347 | /*Codes_SRS_HTTPAPIEX_02_025: [If the first step fails, then the sequence fails.]*/ |
markrad | 58:f50b97b08851 | 348 | /*Codes_SRS_HTTPAPIEX_02_026: [A step shall be retried at most once.]*/ |
markrad | 58:f50b97b08851 | 349 | /*Codes_SRS_HTTPAPIEX_02_027: [If a step has been retried then all subsequent steps shall be retried too.]*/ |
markrad | 58:f50b97b08851 | 350 | bool st[3] = { false, false, false }; /*the three levels of possible failure in resilient send: HTTAPI_Init, HTTPAPI_CreateConnection, HTTPAPI_ExecuteRequest*/ |
markrad | 58:f50b97b08851 | 351 | if (handleData->k == -1) |
markrad | 58:f50b97b08851 | 352 | { |
markrad | 58:f50b97b08851 | 353 | handleData->k = 0; |
markrad | 58:f50b97b08851 | 354 | } |
markrad | 58:f50b97b08851 | 355 | |
markrad | 58:f50b97b08851 | 356 | do |
markrad | 58:f50b97b08851 | 357 | { |
markrad | 58:f50b97b08851 | 358 | bool goOn; |
markrad | 58:f50b97b08851 | 359 | |
markrad | 58:f50b97b08851 | 360 | if (handleData->k > 2) |
markrad | 58:f50b97b08851 | 361 | { |
markrad | 58:f50b97b08851 | 362 | /* error */ |
markrad | 58:f50b97b08851 | 363 | break; |
markrad | 58:f50b97b08851 | 364 | } |
markrad | 58:f50b97b08851 | 365 | |
markrad | 58:f50b97b08851 | 366 | if (st[handleData->k] == true) /*already been tried*/ |
markrad | 58:f50b97b08851 | 367 | { |
markrad | 58:f50b97b08851 | 368 | goOn = false; |
markrad | 58:f50b97b08851 | 369 | } |
markrad | 58:f50b97b08851 | 370 | else |
markrad | 58:f50b97b08851 | 371 | { |
markrad | 58:f50b97b08851 | 372 | switch (handleData->k) |
markrad | 58:f50b97b08851 | 373 | { |
markrad | 58:f50b97b08851 | 374 | case 0: |
markrad | 58:f50b97b08851 | 375 | { |
markrad | 58:f50b97b08851 | 376 | if (HTTPAPI_Init() != HTTPAPI_OK) |
markrad | 58:f50b97b08851 | 377 | { |
markrad | 58:f50b97b08851 | 378 | goOn = false; |
markrad | 58:f50b97b08851 | 379 | } |
markrad | 58:f50b97b08851 | 380 | else |
markrad | 58:f50b97b08851 | 381 | { |
markrad | 58:f50b97b08851 | 382 | goOn = true; |
markrad | 58:f50b97b08851 | 383 | } |
markrad | 58:f50b97b08851 | 384 | break; |
markrad | 58:f50b97b08851 | 385 | } |
markrad | 58:f50b97b08851 | 386 | case 1: |
markrad | 58:f50b97b08851 | 387 | { |
markrad | 58:f50b97b08851 | 388 | if ((handleData->httpHandle = HTTPAPI_CreateConnection(STRING_c_str(handleData->hostName))) == NULL) |
markrad | 58:f50b97b08851 | 389 | { |
markrad | 58:f50b97b08851 | 390 | goOn = false; |
markrad | 58:f50b97b08851 | 391 | } |
markrad | 58:f50b97b08851 | 392 | else |
markrad | 58:f50b97b08851 | 393 | { |
markrad | 58:f50b97b08851 | 394 | size_t i; |
markrad | 58:f50b97b08851 | 395 | size_t vectorSize = VECTOR_size(handleData->savedOptions); |
markrad | 58:f50b97b08851 | 396 | for (i = 0; i < vectorSize; i++) |
markrad | 58:f50b97b08851 | 397 | { |
markrad | 58:f50b97b08851 | 398 | /*Codes_SRS_HTTPAPIEX_02_035: [HTTPAPIEX_ExecuteRequest shall pass all the saved options (see HTTPAPIEX_SetOption) to the newly create HTTPAPI_HANDLE in step 2 by calling HTTPAPI_SetOption.]*/ |
markrad | 58:f50b97b08851 | 399 | /*Codes_SRS_HTTPAPIEX_02_036: [If setting the option fails, then the failure shall be ignored.] */ |
markrad | 58:f50b97b08851 | 400 | HTTPAPIEX_SAVED_OPTION* option = VECTOR_element(handleData->savedOptions, i); |
markrad | 58:f50b97b08851 | 401 | if (HTTPAPI_SetOption(handleData->httpHandle, option->optionName, option->value) != HTTPAPI_OK) |
markrad | 58:f50b97b08851 | 402 | { |
markrad | 58:f50b97b08851 | 403 | LogError("HTTPAPI_SetOption failed when called for option %s", option->optionName); |
markrad | 58:f50b97b08851 | 404 | } |
markrad | 58:f50b97b08851 | 405 | } |
markrad | 58:f50b97b08851 | 406 | goOn = true; |
markrad | 58:f50b97b08851 | 407 | } |
markrad | 58:f50b97b08851 | 408 | break; |
markrad | 58:f50b97b08851 | 409 | } |
markrad | 58:f50b97b08851 | 410 | case 2: |
markrad | 58:f50b97b08851 | 411 | { |
markrad | 58:f50b97b08851 | 412 | size_t length = BUFFER_length(toBeUsedRequestContent); |
markrad | 58:f50b97b08851 | 413 | unsigned char* buffer = BUFFER_u_char(toBeUsedRequestContent); |
markrad | 58:f50b97b08851 | 414 | if (HTTPAPI_ExecuteRequest(handleData->httpHandle, requestType, toBeUsedRelativePath, toBeUsedRequestHttpHeadersHandle, buffer, length, toBeUsedStatusCode, toBeUsedResponseHttpHeadersHandle, toBeUsedResponseContent) != HTTPAPI_OK) |
markrad | 58:f50b97b08851 | 415 | { |
markrad | 58:f50b97b08851 | 416 | goOn = false; |
markrad | 58:f50b97b08851 | 417 | } |
markrad | 58:f50b97b08851 | 418 | else |
markrad | 58:f50b97b08851 | 419 | { |
markrad | 58:f50b97b08851 | 420 | goOn = true; |
markrad | 58:f50b97b08851 | 421 | } |
markrad | 58:f50b97b08851 | 422 | break; |
markrad | 58:f50b97b08851 | 423 | } |
markrad | 58:f50b97b08851 | 424 | default: |
markrad | 58:f50b97b08851 | 425 | { |
markrad | 58:f50b97b08851 | 426 | /*serious error*/ |
markrad | 58:f50b97b08851 | 427 | goOn = false; |
markrad | 58:f50b97b08851 | 428 | break; |
markrad | 58:f50b97b08851 | 429 | } |
markrad | 58:f50b97b08851 | 430 | } |
markrad | 58:f50b97b08851 | 431 | } |
markrad | 58:f50b97b08851 | 432 | |
markrad | 58:f50b97b08851 | 433 | if (goOn) |
markrad | 58:f50b97b08851 | 434 | { |
markrad | 58:f50b97b08851 | 435 | if (handleData->k == 2) |
markrad | 58:f50b97b08851 | 436 | { |
markrad | 58:f50b97b08851 | 437 | /*Codes_SRS_HTTPAPIEX_02_028: [HTTPAPIEX_ExecuteRequest shall return HTTPAPIEX_OK when a call to HTTPAPI_ExecuteRequest has been completed successfully.]*/ |
markrad | 58:f50b97b08851 | 438 | result = HTTPAPIEX_OK; |
markrad | 58:f50b97b08851 | 439 | goto out; |
markrad | 58:f50b97b08851 | 440 | } |
markrad | 58:f50b97b08851 | 441 | else |
markrad | 58:f50b97b08851 | 442 | { |
markrad | 58:f50b97b08851 | 443 | st[handleData->k] = true; |
markrad | 58:f50b97b08851 | 444 | handleData->k++; |
markrad | 58:f50b97b08851 | 445 | st[handleData->k] = false; |
markrad | 58:f50b97b08851 | 446 | } |
markrad | 58:f50b97b08851 | 447 | } |
markrad | 58:f50b97b08851 | 448 | else |
markrad | 58:f50b97b08851 | 449 | { |
markrad | 58:f50b97b08851 | 450 | st[handleData->k] = false; |
markrad | 58:f50b97b08851 | 451 | handleData->k--; |
markrad | 58:f50b97b08851 | 452 | switch (handleData->k) |
markrad | 58:f50b97b08851 | 453 | { |
markrad | 58:f50b97b08851 | 454 | case 0: |
markrad | 58:f50b97b08851 | 455 | { |
markrad | 58:f50b97b08851 | 456 | HTTPAPI_Deinit(); |
markrad | 58:f50b97b08851 | 457 | break; |
markrad | 58:f50b97b08851 | 458 | } |
markrad | 58:f50b97b08851 | 459 | case 1: |
markrad | 58:f50b97b08851 | 460 | { |
markrad | 58:f50b97b08851 | 461 | HTTPAPI_CloseConnection(handleData->httpHandle); |
markrad | 58:f50b97b08851 | 462 | handleData->httpHandle = NULL; |
markrad | 58:f50b97b08851 | 463 | break; |
markrad | 58:f50b97b08851 | 464 | } |
markrad | 58:f50b97b08851 | 465 | case 2: |
markrad | 58:f50b97b08851 | 466 | { |
markrad | 58:f50b97b08851 | 467 | break; |
markrad | 58:f50b97b08851 | 468 | } |
markrad | 58:f50b97b08851 | 469 | default: |
markrad | 58:f50b97b08851 | 470 | { |
markrad | 58:f50b97b08851 | 471 | break; |
markrad | 58:f50b97b08851 | 472 | } |
markrad | 58:f50b97b08851 | 473 | } |
markrad | 58:f50b97b08851 | 474 | } |
markrad | 58:f50b97b08851 | 475 | } while (handleData->k >= 0); |
markrad | 58:f50b97b08851 | 476 | /*Codes_SRS_HTTPAPIEX_02_029: [Otherwise, HTTAPIEX_ExecuteRequest shall return HTTPAPIEX_RECOVERYFAILED.] */ |
markrad | 58:f50b97b08851 | 477 | result = HTTPAPIEX_RECOVERYFAILED; |
markrad | 58:f50b97b08851 | 478 | LogError("unable to recover sending to a working state"); |
markrad | 58:f50b97b08851 | 479 | out:; |
markrad | 58:f50b97b08851 | 480 | /*in all cases, unbuild the temporaries*/ |
markrad | 58:f50b97b08851 | 481 | if (isOriginalRequestContent == false) |
markrad | 58:f50b97b08851 | 482 | { |
markrad | 58:f50b97b08851 | 483 | BUFFER_delete(toBeUsedRequestContent); |
markrad | 58:f50b97b08851 | 484 | } |
markrad | 58:f50b97b08851 | 485 | if (isOriginalRequestHttpHeadersHandle == false) |
markrad | 58:f50b97b08851 | 486 | { |
markrad | 58:f50b97b08851 | 487 | HTTPHeaders_Free(toBeUsedRequestHttpHeadersHandle); |
markrad | 58:f50b97b08851 | 488 | } |
markrad | 58:f50b97b08851 | 489 | if (isOriginalResponseContent == false) |
markrad | 58:f50b97b08851 | 490 | { |
markrad | 58:f50b97b08851 | 491 | BUFFER_delete(toBeUsedResponseContent); |
markrad | 58:f50b97b08851 | 492 | } |
markrad | 58:f50b97b08851 | 493 | if (isOriginalResponseHttpHeadersHandle == false) |
markrad | 58:f50b97b08851 | 494 | { |
markrad | 58:f50b97b08851 | 495 | HTTPHeaders_Free(toBeUsedResponseHttpHeadersHandle); |
markrad | 58:f50b97b08851 | 496 | } |
markrad | 58:f50b97b08851 | 497 | } |
markrad | 58:f50b97b08851 | 498 | } |
markrad | 58:f50b97b08851 | 499 | } |
markrad | 58:f50b97b08851 | 500 | return result; |
markrad | 58:f50b97b08851 | 501 | } |
markrad | 58:f50b97b08851 | 502 | |
markrad | 58:f50b97b08851 | 503 | |
markrad | 58:f50b97b08851 | 504 | void HTTPAPIEX_Destroy(HTTPAPIEX_HANDLE handle) |
markrad | 58:f50b97b08851 | 505 | { |
markrad | 58:f50b97b08851 | 506 | if (handle != NULL) |
markrad | 58:f50b97b08851 | 507 | { |
markrad | 58:f50b97b08851 | 508 | /*Codes_SRS_HTTPAPIEX_02_042: [HTTPAPIEX_Destroy shall free all the resources used by HTTAPIEX_HANDLE.]*/ |
markrad | 58:f50b97b08851 | 509 | size_t i; |
markrad | 58:f50b97b08851 | 510 | size_t vectorSize; |
markrad | 58:f50b97b08851 | 511 | HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)handle; |
markrad | 58:f50b97b08851 | 512 | |
markrad | 58:f50b97b08851 | 513 | if (handleData->k == 2) |
markrad | 58:f50b97b08851 | 514 | { |
markrad | 58:f50b97b08851 | 515 | HTTPAPI_CloseConnection(handleData->httpHandle); |
markrad | 58:f50b97b08851 | 516 | HTTPAPI_Deinit(); |
markrad | 58:f50b97b08851 | 517 | } |
markrad | 58:f50b97b08851 | 518 | STRING_delete(handleData->hostName); |
markrad | 58:f50b97b08851 | 519 | |
markrad | 58:f50b97b08851 | 520 | vectorSize = VECTOR_size(handleData->savedOptions); |
markrad | 58:f50b97b08851 | 521 | for (i = 0; i < vectorSize; i++) |
markrad | 58:f50b97b08851 | 522 | { |
markrad | 58:f50b97b08851 | 523 | HTTPAPIEX_SAVED_OPTION*savedOption = VECTOR_element(handleData->savedOptions, i); |
markrad | 58:f50b97b08851 | 524 | free((void*)savedOption->optionName); |
markrad | 58:f50b97b08851 | 525 | free((void*)savedOption->value); |
markrad | 58:f50b97b08851 | 526 | } |
markrad | 58:f50b97b08851 | 527 | VECTOR_destroy(handleData->savedOptions); |
markrad | 58:f50b97b08851 | 528 | |
markrad | 58:f50b97b08851 | 529 | free(handle); |
markrad | 58:f50b97b08851 | 530 | } |
markrad | 58:f50b97b08851 | 531 | else |
markrad | 58:f50b97b08851 | 532 | { |
markrad | 58:f50b97b08851 | 533 | /*Codes_SRS_HTTPAPIEX_02_043: [If parameter handle is NULL then HTTPAPIEX_Destroy shall take no action.] */ |
markrad | 58:f50b97b08851 | 534 | } |
markrad | 58:f50b97b08851 | 535 | } |
markrad | 58:f50b97b08851 | 536 | |
markrad | 58:f50b97b08851 | 537 | static bool sameName(const void* element, const void* value) |
markrad | 58:f50b97b08851 | 538 | { |
markrad | 58:f50b97b08851 | 539 | return (strcmp(((HTTPAPIEX_SAVED_OPTION*)element)->optionName, value) == 0) ? true : false; |
markrad | 58:f50b97b08851 | 540 | } |
markrad | 58:f50b97b08851 | 541 | |
markrad | 58:f50b97b08851 | 542 | /*return 0 on success, any other value is error*/ |
markrad | 58:f50b97b08851 | 543 | /*obs: value is already cloned at the time of calling this function */ |
markrad | 58:f50b97b08851 | 544 | static int createOrUpdateOption(HTTPAPIEX_HANDLE_DATA* handleData, const char* optionName, const void* value) |
markrad | 58:f50b97b08851 | 545 | { |
markrad | 58:f50b97b08851 | 546 | /*this function is called after the option value has been saved (cloned)*/ |
markrad | 58:f50b97b08851 | 547 | int result; |
markrad | 58:f50b97b08851 | 548 | |
markrad | 58:f50b97b08851 | 549 | /*decide bwtween update or create*/ |
markrad | 58:f50b97b08851 | 550 | HTTPAPIEX_SAVED_OPTION* whereIsIt = VECTOR_find_if(handleData->savedOptions, sameName, optionName); |
markrad | 58:f50b97b08851 | 551 | if (whereIsIt != NULL) |
markrad | 58:f50b97b08851 | 552 | { |
markrad | 58:f50b97b08851 | 553 | free((void*)(whereIsIt->value)); |
markrad | 58:f50b97b08851 | 554 | whereIsIt->value = value; |
markrad | 58:f50b97b08851 | 555 | result = 0; |
markrad | 58:f50b97b08851 | 556 | } |
markrad | 58:f50b97b08851 | 557 | else |
markrad | 58:f50b97b08851 | 558 | { |
markrad | 58:f50b97b08851 | 559 | HTTPAPIEX_SAVED_OPTION newOption; |
markrad | 58:f50b97b08851 | 560 | if (mallocAndStrcpy_s((char**)&(newOption.optionName), optionName) != 0) |
markrad | 58:f50b97b08851 | 561 | { |
markrad | 58:f50b97b08851 | 562 | free((void*)value); |
markrad | 58:f50b97b08851 | 563 | result = __LINE__; |
markrad | 58:f50b97b08851 | 564 | } |
markrad | 58:f50b97b08851 | 565 | else |
markrad | 58:f50b97b08851 | 566 | { |
markrad | 58:f50b97b08851 | 567 | newOption.value = value; |
markrad | 58:f50b97b08851 | 568 | if (VECTOR_push_back(handleData->savedOptions, &newOption, 1) != 0) |
markrad | 58:f50b97b08851 | 569 | { |
markrad | 58:f50b97b08851 | 570 | LogError("unable to VECTOR_push_back"); |
markrad | 58:f50b97b08851 | 571 | free((void*)newOption.optionName); |
markrad | 58:f50b97b08851 | 572 | free((void*)value); |
markrad | 58:f50b97b08851 | 573 | result = __LINE__; |
markrad | 58:f50b97b08851 | 574 | } |
markrad | 58:f50b97b08851 | 575 | else |
markrad | 58:f50b97b08851 | 576 | { |
markrad | 58:f50b97b08851 | 577 | result = 0; |
markrad | 58:f50b97b08851 | 578 | } |
markrad | 58:f50b97b08851 | 579 | } |
markrad | 58:f50b97b08851 | 580 | } |
markrad | 58:f50b97b08851 | 581 | |
markrad | 58:f50b97b08851 | 582 | return result; |
markrad | 58:f50b97b08851 | 583 | } |
markrad | 58:f50b97b08851 | 584 | |
markrad | 58:f50b97b08851 | 585 | HTTPAPIEX_RESULT HTTPAPIEX_SetOption(HTTPAPIEX_HANDLE handle, const char* optionName, const void* value) |
markrad | 58:f50b97b08851 | 586 | { |
markrad | 58:f50b97b08851 | 587 | HTTPAPIEX_RESULT result; |
markrad | 58:f50b97b08851 | 588 | /*Codes_SRS_HTTPAPIEX_02_032: [If parameter handle is NULL then HTTPAPIEX_SetOption shall return HTTPAPIEX_INVALID_ARG.] */ |
markrad | 58:f50b97b08851 | 589 | /*Codes_SRS_HTTPAPIEX_02_033: [If parameter optionName is NULL then HTTPAPIEX_SetOption shall return HTTPAPIEX_INVALID_ARG.] */ |
markrad | 58:f50b97b08851 | 590 | /*Codes_SRS_HTTPAPIEX_02_034: [If parameter value is NULL then HTTPAPIEX_SetOption shall return HTTPAPIEX_INVALID_ARG.] */ |
markrad | 58:f50b97b08851 | 591 | if ( |
markrad | 58:f50b97b08851 | 592 | (handle == NULL) || |
markrad | 58:f50b97b08851 | 593 | (optionName == NULL) || |
markrad | 58:f50b97b08851 | 594 | (value == NULL) |
markrad | 58:f50b97b08851 | 595 | ) |
markrad | 58:f50b97b08851 | 596 | { |
markrad | 58:f50b97b08851 | 597 | result = HTTPAPIEX_INVALID_ARG; |
markrad | 58:f50b97b08851 | 598 | LOG_HTTAPIEX_ERROR(); |
markrad | 58:f50b97b08851 | 599 | } |
markrad | 58:f50b97b08851 | 600 | else |
markrad | 58:f50b97b08851 | 601 | { |
markrad | 58:f50b97b08851 | 602 | const void* savedOption; |
markrad | 58:f50b97b08851 | 603 | HTTPAPI_RESULT saveOptionResult; |
markrad | 58:f50b97b08851 | 604 | |
markrad | 58:f50b97b08851 | 605 | /*Codes_SRS_HTTPAPIEX_02_037: [HTTPAPIEX_SetOption shall attempt to save the value of the option by calling HTTPAPI_CloneOption passing optionName and value, irrespective of the existence of a HTTPAPI_HANDLE] */ |
markrad | 58:f50b97b08851 | 606 | saveOptionResult = HTTPAPI_CloneOption(optionName, value, &savedOption); |
markrad | 58:f50b97b08851 | 607 | |
markrad | 58:f50b97b08851 | 608 | if(saveOptionResult == HTTPAPI_INVALID_ARG) |
markrad | 58:f50b97b08851 | 609 | { |
markrad | 58:f50b97b08851 | 610 | /*Codes_SRS_HTTPAPIEX_02_038: [If HTTPAPI_CloneOption returns HTTPAPI_INVALID_ARG then HTTPAPIEX shall return HTTPAPIEX_INVALID_ARG.] */ |
markrad | 58:f50b97b08851 | 611 | result = HTTPAPIEX_INVALID_ARG; |
markrad | 58:f50b97b08851 | 612 | LOG_HTTAPIEX_ERROR(); |
markrad | 58:f50b97b08851 | 613 | } |
markrad | 58:f50b97b08851 | 614 | else if (saveOptionResult != HTTPAPI_OK) |
markrad | 58:f50b97b08851 | 615 | { |
markrad | 58:f50b97b08851 | 616 | /*Codes_SRS_HTTPAPIEX_02_040: [For all other return values of HTTPAPI_SetOption, HTTPIAPIEX_SetOption shall return HTTPAPIEX_ERROR.] */ |
markrad | 58:f50b97b08851 | 617 | result = HTTPAPIEX_ERROR; |
markrad | 58:f50b97b08851 | 618 | LOG_HTTAPIEX_ERROR(); |
markrad | 58:f50b97b08851 | 619 | } |
markrad | 58:f50b97b08851 | 620 | else |
markrad | 58:f50b97b08851 | 621 | { |
markrad | 58:f50b97b08851 | 622 | HTTPAPIEX_HANDLE_DATA* handleData = (HTTPAPIEX_HANDLE_DATA*)handle; |
markrad | 58:f50b97b08851 | 623 | /*Codes_SRS_HTTPAPIEX_02_039: [If HTTPAPI_CloneOption returns HTTPAPI_OK then HTTPAPIEX_SetOption shall create or update the pair optionName/value.]*/ |
markrad | 58:f50b97b08851 | 624 | if (createOrUpdateOption(handleData, optionName, savedOption) != 0) |
markrad | 58:f50b97b08851 | 625 | { |
markrad | 58:f50b97b08851 | 626 | /*Codes_SRS_HTTPAPIEX_02_041: [If creating or updating the pair optionName/value fails then shall return HTTPAPIEX_ERROR.] */ |
markrad | 58:f50b97b08851 | 627 | result = HTTPAPIEX_ERROR; |
markrad | 58:f50b97b08851 | 628 | LOG_HTTAPIEX_ERROR(); |
markrad | 58:f50b97b08851 | 629 | |
markrad | 58:f50b97b08851 | 630 | } |
markrad | 58:f50b97b08851 | 631 | else |
markrad | 58:f50b97b08851 | 632 | { |
markrad | 58:f50b97b08851 | 633 | /*Codes_SRS_HTTPAPIEX_02_031: [If HTTPAPI_HANDLE exists then HTTPAPIEX_SetOption shall call HTTPAPI_SetOption passing the same optionName and value and shall return a value conforming to the below table:] */ |
markrad | 58:f50b97b08851 | 634 | if (handleData->httpHandle != NULL) |
markrad | 58:f50b97b08851 | 635 | { |
markrad | 58:f50b97b08851 | 636 | HTTPAPI_RESULT HTTPAPI_result = HTTPAPI_SetOption(handleData->httpHandle, optionName, value); |
markrad | 58:f50b97b08851 | 637 | if (HTTPAPI_result == HTTPAPI_OK) |
markrad | 58:f50b97b08851 | 638 | { |
markrad | 58:f50b97b08851 | 639 | result = HTTPAPIEX_OK; |
markrad | 58:f50b97b08851 | 640 | } |
markrad | 58:f50b97b08851 | 641 | else if (HTTPAPI_result == HTTPAPI_INVALID_ARG) |
markrad | 58:f50b97b08851 | 642 | { |
markrad | 58:f50b97b08851 | 643 | result = HTTPAPIEX_INVALID_ARG; |
markrad | 58:f50b97b08851 | 644 | LOG_HTTAPIEX_ERROR(); |
markrad | 58:f50b97b08851 | 645 | } |
markrad | 58:f50b97b08851 | 646 | else |
markrad | 58:f50b97b08851 | 647 | { |
markrad | 58:f50b97b08851 | 648 | result = HTTPAPIEX_ERROR; |
markrad | 58:f50b97b08851 | 649 | LOG_HTTAPIEX_ERROR(); |
markrad | 58:f50b97b08851 | 650 | } |
markrad | 58:f50b97b08851 | 651 | } |
markrad | 58:f50b97b08851 | 652 | else |
markrad | 58:f50b97b08851 | 653 | { |
markrad | 58:f50b97b08851 | 654 | result = HTTPAPIEX_OK; |
markrad | 58:f50b97b08851 | 655 | } |
markrad | 58:f50b97b08851 | 656 | } |
markrad | 58:f50b97b08851 | 657 | } |
markrad | 58:f50b97b08851 | 658 | } |
markrad | 58:f50b97b08851 | 659 | return result; |
markrad | 58:f50b97b08851 | 660 | } |