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