Azure IoT common library
Fork of azure_c_shared_utility by
httpapi_compact.c@14:b7e6599cacf5, 2016-10-21 (annotated)
- Committer:
- AzureIoTClient
- Date:
- Fri Oct 21 22:11:02 2016 +0000
- Revision:
- 14:b7e6599cacf5
- Parent:
- 13:920e00014ee3
- Child:
- 15:956c6d205aa7
patch http
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Azure.IoT Build | 6:c55b013dfc2a | 1 | // Copyright (c) Microsoft. All rights reserved. |
Azure.IoT Build | 6:c55b013dfc2a | 2 | // Licensed under the MIT license. See LICENSE file in the project root for full license information. |
Azure.IoT Build | 6:c55b013dfc2a | 3 | |
Azure.IoT Build | 6:c55b013dfc2a | 4 | #include <stdlib.h> |
Azure.IoT Build | 6:c55b013dfc2a | 5 | #ifdef _CRTDBG_MAP_ALLOC |
Azure.IoT Build | 6:c55b013dfc2a | 6 | #include <crtdbg.h> |
Azure.IoT Build | 6:c55b013dfc2a | 7 | #endif |
Azure.IoT Build | 6:c55b013dfc2a | 8 | |
Azure.IoT Build | 6:c55b013dfc2a | 9 | #include <stdio.h> |
Azure.IoT Build | 6:c55b013dfc2a | 10 | #include <ctype.h> |
AzureIoTClient | 11:77df6d7e65ae | 11 | #include "azure_c_shared_utility/gballoc.h" |
Azure.IoT Build | 6:c55b013dfc2a | 12 | #include "azure_c_shared_utility/httpheaders.h" |
Azure.IoT Build | 6:c55b013dfc2a | 13 | #include "azure_c_shared_utility/crt_abstractions.h" |
Azure.IoT Build | 6:c55b013dfc2a | 14 | #include "azure_c_shared_utility/xlogging.h" |
Azure.IoT Build | 6:c55b013dfc2a | 15 | #include "azure_c_shared_utility/xio.h" |
Azure.IoT Build | 6:c55b013dfc2a | 16 | #include "azure_c_shared_utility/platform.h" |
Azure.IoT Build | 6:c55b013dfc2a | 17 | #include "azure_c_shared_utility/tlsio.h" |
Azure.IoT Build | 6:c55b013dfc2a | 18 | #include "azure_c_shared_utility/threadapi.h" |
Azure.IoT Build | 6:c55b013dfc2a | 19 | #include <string.h> |
AzureIoTClient | 7:1af47e3a19b6 | 20 | #include <limits.h> |
Azure.IoT Build | 6:c55b013dfc2a | 21 | |
AzureIoTClient | 11:77df6d7e65ae | 22 | /*Codes_SRS_HTTPAPI_COMPACT_21_001: [ The httpapi_compact shall implement the methods defined by the `httpapi.h`. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 23 | /*Codes_SRS_HTTPAPI_COMPACT_21_002: [ The httpapi_compact shall support the http requests. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 24 | /*Codes_SRS_HTTPAPI_COMPACT_21_003: [ The httpapi_compact shall return error codes defined by HTTPAPI_RESULT. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 25 | #include "azure_c_shared_utility/httpapi.h" |
AzureIoTClient | 11:77df6d7e65ae | 26 | |
Azure.IoT Build | 6:c55b013dfc2a | 27 | #define MAX_HOSTNAME 64 |
AzureIoTClient | 11:77df6d7e65ae | 28 | #define TEMP_BUFFER_SIZE 1024 |
Azure.IoT Build | 6:c55b013dfc2a | 29 | |
AzureIoTClient | 13:920e00014ee3 | 30 | /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 times. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 31 | /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 14:b7e6599cacf5 | 32 | #define MAX_RECEIVE_RETRY 70 |
AzureIoTClient | 13:920e00014ee3 | 33 | /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 34 | #define RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS 100 |
AzureIoTClient | 13:920e00014ee3 | 35 | #define OPEN_RETRY_INTERVAL_IN_MICROSECONDS 100 |
AzureIoTClient | 13:920e00014ee3 | 36 | |
Azure.IoT Build | 6:c55b013dfc2a | 37 | |
Azure.IoT Build | 6:c55b013dfc2a | 38 | DEFINE_ENUM_STRINGS(HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES) |
Azure.IoT Build | 6:c55b013dfc2a | 39 | |
Azure.IoT Build | 6:c55b013dfc2a | 40 | typedef struct HTTP_HANDLE_DATA_TAG |
Azure.IoT Build | 6:c55b013dfc2a | 41 | { |
Azure.IoT Build | 6:c55b013dfc2a | 42 | char* certificate; |
Azure.IoT Build | 6:c55b013dfc2a | 43 | XIO_HANDLE xio_handle; |
Azure.IoT Build | 6:c55b013dfc2a | 44 | size_t received_bytes_count; |
Azure.IoT Build | 6:c55b013dfc2a | 45 | unsigned char* received_bytes; |
Azure.IoT Build | 6:c55b013dfc2a | 46 | unsigned int is_io_error : 1; |
Azure.IoT Build | 6:c55b013dfc2a | 47 | unsigned int is_connected : 1; |
Azure.IoT Build | 6:c55b013dfc2a | 48 | } HTTP_HANDLE_DATA; |
Azure.IoT Build | 6:c55b013dfc2a | 49 | |
AzureIoTClient | 7:1af47e3a19b6 | 50 | /*the following function does the same as sscanf(pos2, "%d", &sec)*/ |
AzureIoTClient | 7:1af47e3a19b6 | 51 | /*this function only exists because some of platforms do not have sscanf. */ |
AzureIoTClient | 7:1af47e3a19b6 | 52 | static int ParseStringToDecimal(const char *src, int* dst) |
AzureIoTClient | 7:1af47e3a19b6 | 53 | { |
AzureIoTClient | 11:77df6d7e65ae | 54 | int result; |
AzureIoTClient | 7:1af47e3a19b6 | 55 | char* next; |
AzureIoTClient | 7:1af47e3a19b6 | 56 | (*dst) = strtol(src, &next, 0); |
AzureIoTClient | 7:1af47e3a19b6 | 57 | if ((src == next) || ((((*dst) == LONG_MAX) || ((*dst) == LONG_MIN)) && (errno != 0))) |
AzureIoTClient | 7:1af47e3a19b6 | 58 | { |
AzureIoTClient | 11:77df6d7e65ae | 59 | result = EOF; |
AzureIoTClient | 7:1af47e3a19b6 | 60 | } |
AzureIoTClient | 11:77df6d7e65ae | 61 | else |
AzureIoTClient | 11:77df6d7e65ae | 62 | { |
AzureIoTClient | 11:77df6d7e65ae | 63 | result = 1; |
AzureIoTClient | 11:77df6d7e65ae | 64 | } |
AzureIoTClient | 11:77df6d7e65ae | 65 | return result; |
AzureIoTClient | 7:1af47e3a19b6 | 66 | } |
AzureIoTClient | 7:1af47e3a19b6 | 67 | |
AzureIoTClient | 7:1af47e3a19b6 | 68 | /*the following function does the same as sscanf(pos2, "%x", &sec)*/ |
AzureIoTClient | 7:1af47e3a19b6 | 69 | /*this function only exists because some of platforms do not have sscanf. This is not a full implementation; it only works with well-defined x numbers. */ |
AzureIoTClient | 7:1af47e3a19b6 | 70 | #define HEXA_DIGIT_VAL(c) (((c>='0') && (c<='9')) ? (c-'0') : ((c>='a') && (c<='f')) ? (c-'a'+10) : ((c>='A') && (c<='F')) ? (c-'A'+10) : -1) |
AzureIoTClient | 11:77df6d7e65ae | 71 | static int ParseStringToHexadecimal(const char *src, size_t* dst) |
AzureIoTClient | 7:1af47e3a19b6 | 72 | { |
AzureIoTClient | 11:77df6d7e65ae | 73 | int result; |
AzureIoTClient | 7:1af47e3a19b6 | 74 | int digitVal; |
AzureIoTClient | 11:77df6d7e65ae | 75 | if (src == NULL) |
AzureIoTClient | 11:77df6d7e65ae | 76 | { |
AzureIoTClient | 11:77df6d7e65ae | 77 | result = EOF; |
AzureIoTClient | 11:77df6d7e65ae | 78 | } |
AzureIoTClient | 11:77df6d7e65ae | 79 | else if (HEXA_DIGIT_VAL(*src) == -1) |
AzureIoTClient | 11:77df6d7e65ae | 80 | { |
AzureIoTClient | 11:77df6d7e65ae | 81 | result = EOF; |
AzureIoTClient | 11:77df6d7e65ae | 82 | } |
AzureIoTClient | 11:77df6d7e65ae | 83 | else |
AzureIoTClient | 11:77df6d7e65ae | 84 | { |
AzureIoTClient | 11:77df6d7e65ae | 85 | (*dst) = 0; |
AzureIoTClient | 11:77df6d7e65ae | 86 | while ((digitVal = HEXA_DIGIT_VAL(*src)) != -1) |
AzureIoTClient | 11:77df6d7e65ae | 87 | { |
AzureIoTClient | 11:77df6d7e65ae | 88 | (*dst) *= 0x10; |
AzureIoTClient | 11:77df6d7e65ae | 89 | (*dst) += (size_t)digitVal; |
AzureIoTClient | 11:77df6d7e65ae | 90 | src++; |
AzureIoTClient | 11:77df6d7e65ae | 91 | } |
AzureIoTClient | 11:77df6d7e65ae | 92 | result = 1; |
AzureIoTClient | 11:77df6d7e65ae | 93 | } |
AzureIoTClient | 11:77df6d7e65ae | 94 | return result; |
AzureIoTClient | 7:1af47e3a19b6 | 95 | } |
AzureIoTClient | 7:1af47e3a19b6 | 96 | |
AzureIoTClient | 7:1af47e3a19b6 | 97 | /*the following function does the same as sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) */ |
AzureIoTClient | 7:1af47e3a19b6 | 98 | /*this function only exists because some of platforms do not have sscanf. This is not a full implementation; it only works with well-defined HTTP response. */ |
AzureIoTClient | 11:77df6d7e65ae | 99 | static int ParseHttpResponse(const char* src, int* dst) |
AzureIoTClient | 7:1af47e3a19b6 | 100 | { |
AzureIoTClient | 11:77df6d7e65ae | 101 | int result; |
AzureIoTClient | 11:77df6d7e65ae | 102 | static const char HTTPPrefix[] = "HTTP/"; |
AzureIoTClient | 11:77df6d7e65ae | 103 | bool fail; |
AzureIoTClient | 11:77df6d7e65ae | 104 | const char* runPrefix; |
AzureIoTClient | 11:77df6d7e65ae | 105 | |
AzureIoTClient | 11:77df6d7e65ae | 106 | if ((src == NULL) || (dst == NULL)) |
AzureIoTClient | 11:77df6d7e65ae | 107 | { |
AzureIoTClient | 11:77df6d7e65ae | 108 | result = EOF; |
AzureIoTClient | 11:77df6d7e65ae | 109 | } |
AzureIoTClient | 11:77df6d7e65ae | 110 | else |
AzureIoTClient | 11:77df6d7e65ae | 111 | { |
AzureIoTClient | 11:77df6d7e65ae | 112 | fail = false; |
AzureIoTClient | 11:77df6d7e65ae | 113 | runPrefix = HTTPPrefix; |
AzureIoTClient | 11:77df6d7e65ae | 114 | |
AzureIoTClient | 11:77df6d7e65ae | 115 | while((*runPrefix) != '\0') |
AzureIoTClient | 11:77df6d7e65ae | 116 | { |
AzureIoTClient | 11:77df6d7e65ae | 117 | if ((*runPrefix) != (*src)) |
AzureIoTClient | 11:77df6d7e65ae | 118 | { |
AzureIoTClient | 11:77df6d7e65ae | 119 | fail = true; |
AzureIoTClient | 11:77df6d7e65ae | 120 | break; |
AzureIoTClient | 11:77df6d7e65ae | 121 | } |
AzureIoTClient | 11:77df6d7e65ae | 122 | src++; |
AzureIoTClient | 11:77df6d7e65ae | 123 | runPrefix++; |
AzureIoTClient | 11:77df6d7e65ae | 124 | } |
AzureIoTClient | 7:1af47e3a19b6 | 125 | |
AzureIoTClient | 11:77df6d7e65ae | 126 | if (!fail) |
AzureIoTClient | 11:77df6d7e65ae | 127 | { |
AzureIoTClient | 11:77df6d7e65ae | 128 | while ((*src) != '.') |
AzureIoTClient | 11:77df6d7e65ae | 129 | { |
AzureIoTClient | 11:77df6d7e65ae | 130 | if ((*src) == '\0') |
AzureIoTClient | 11:77df6d7e65ae | 131 | { |
AzureIoTClient | 11:77df6d7e65ae | 132 | fail = true; |
AzureIoTClient | 11:77df6d7e65ae | 133 | break; |
AzureIoTClient | 11:77df6d7e65ae | 134 | } |
AzureIoTClient | 11:77df6d7e65ae | 135 | src++; |
AzureIoTClient | 11:77df6d7e65ae | 136 | } |
AzureIoTClient | 11:77df6d7e65ae | 137 | } |
AzureIoTClient | 7:1af47e3a19b6 | 138 | |
AzureIoTClient | 11:77df6d7e65ae | 139 | if (!fail) |
AzureIoTClient | 11:77df6d7e65ae | 140 | { |
AzureIoTClient | 11:77df6d7e65ae | 141 | while ((*src) != ' ') |
AzureIoTClient | 11:77df6d7e65ae | 142 | { |
AzureIoTClient | 11:77df6d7e65ae | 143 | if ((*src) == '\0') |
AzureIoTClient | 11:77df6d7e65ae | 144 | { |
AzureIoTClient | 11:77df6d7e65ae | 145 | fail = true; |
AzureIoTClient | 11:77df6d7e65ae | 146 | break; |
AzureIoTClient | 11:77df6d7e65ae | 147 | } |
AzureIoTClient | 11:77df6d7e65ae | 148 | src++; |
AzureIoTClient | 11:77df6d7e65ae | 149 | } |
AzureIoTClient | 11:77df6d7e65ae | 150 | } |
AzureIoTClient | 7:1af47e3a19b6 | 151 | |
AzureIoTClient | 11:77df6d7e65ae | 152 | if (fail) |
AzureIoTClient | 11:77df6d7e65ae | 153 | { |
AzureIoTClient | 11:77df6d7e65ae | 154 | result = EOF; |
AzureIoTClient | 11:77df6d7e65ae | 155 | } |
AzureIoTClient | 11:77df6d7e65ae | 156 | else |
AzureIoTClient | 11:77df6d7e65ae | 157 | { |
AzureIoTClient | 11:77df6d7e65ae | 158 | result = ParseStringToDecimal(src, dst); |
AzureIoTClient | 11:77df6d7e65ae | 159 | } |
AzureIoTClient | 11:77df6d7e65ae | 160 | } |
AzureIoTClient | 11:77df6d7e65ae | 161 | |
AzureIoTClient | 11:77df6d7e65ae | 162 | return result; |
AzureIoTClient | 7:1af47e3a19b6 | 163 | } |
AzureIoTClient | 7:1af47e3a19b6 | 164 | |
Azure.IoT Build | 6:c55b013dfc2a | 165 | HTTPAPI_RESULT HTTPAPI_Init(void) |
Azure.IoT Build | 6:c55b013dfc2a | 166 | { |
AzureIoTClient | 11:77df6d7e65ae | 167 | /*Codes_SRS_HTTPAPI_COMPACT_21_004: [ The HTTPAPI_Init shall allocate all memory to control the http protocol. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 168 | /*Codes_SRS_HTTPAPI_COMPACT_21_007: [ If there is not enough memory to control the http protocol, the HTTPAPI_Init shall return HTTPAPI_ALLOC_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 169 | /** |
AzureIoTClient | 11:77df6d7e65ae | 170 | * No memory is necessary. |
AzureIoTClient | 11:77df6d7e65ae | 171 | */ |
AzureIoTClient | 11:77df6d7e65ae | 172 | |
AzureIoTClient | 11:77df6d7e65ae | 173 | /*Codes_SRS_HTTPAPI_COMPACT_21_006: [ If HTTPAPI_Init succeed allocating all the needed memory, it shall return HTTPAPI_OK. ]*/ |
Azure.IoT Build | 6:c55b013dfc2a | 174 | return HTTPAPI_OK; |
Azure.IoT Build | 6:c55b013dfc2a | 175 | } |
Azure.IoT Build | 6:c55b013dfc2a | 176 | |
Azure.IoT Build | 6:c55b013dfc2a | 177 | void HTTPAPI_Deinit(void) |
Azure.IoT Build | 6:c55b013dfc2a | 178 | { |
AzureIoTClient | 11:77df6d7e65ae | 179 | /*Codes_SRS_HTTPAPI_COMPACT_21_009: [ The HTTPAPI_Init shall release all memory allocated by the httpapi_compact. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 180 | /** |
AzureIoTClient | 11:77df6d7e65ae | 181 | * No memory was necessary. |
AzureIoTClient | 11:77df6d7e65ae | 182 | */ |
Azure.IoT Build | 6:c55b013dfc2a | 183 | } |
Azure.IoT Build | 6:c55b013dfc2a | 184 | |
AzureIoTClient | 11:77df6d7e65ae | 185 | /*Codes_SRS_HTTPAPI_COMPACT_21_011: [ The HTTPAPI_CreateConnection shall create an http connection to the host specified by the hostName parameter. ]*/ |
Azure.IoT Build | 6:c55b013dfc2a | 186 | HTTP_HANDLE HTTPAPI_CreateConnection(const char* hostName) |
Azure.IoT Build | 6:c55b013dfc2a | 187 | { |
AzureIoTClient | 13:920e00014ee3 | 188 | HTTP_HANDLE_DATA* http_instance; |
AzureIoTClient | 11:77df6d7e65ae | 189 | TLSIO_CONFIG tlsio_config; |
Azure.IoT Build | 6:c55b013dfc2a | 190 | |
AzureIoTClient | 11:77df6d7e65ae | 191 | if (hostName == NULL) |
AzureIoTClient | 11:77df6d7e65ae | 192 | { |
AzureIoTClient | 11:77df6d7e65ae | 193 | /*Codes_SRS_HTTPAPI_COMPACT_21_014: [ If the hostName is NULL, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 194 | LogError("Invalid host name. Null hostName parameter."); |
AzureIoTClient | 13:920e00014ee3 | 195 | http_instance = NULL; |
AzureIoTClient | 11:77df6d7e65ae | 196 | } |
AzureIoTClient | 11:77df6d7e65ae | 197 | else if (*hostName == '\0') |
AzureIoTClient | 11:77df6d7e65ae | 198 | { |
AzureIoTClient | 11:77df6d7e65ae | 199 | /*Codes_SRS_HTTPAPI_COMPACT_21_015: [ If the hostName is empty, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 200 | LogError("Invalid host name. Empty string."); |
AzureIoTClient | 13:920e00014ee3 | 201 | http_instance = NULL; |
AzureIoTClient | 11:77df6d7e65ae | 202 | } |
AzureIoTClient | 11:77df6d7e65ae | 203 | else |
AzureIoTClient | 11:77df6d7e65ae | 204 | { |
AzureIoTClient | 13:920e00014ee3 | 205 | http_instance = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA)); |
AzureIoTClient | 11:77df6d7e65ae | 206 | /*Codes_SRS_HTTPAPI_COMPACT_21_013: [ If there is not enough memory to control the http connection, the HTTPAPI_CreateConnection shall return NULL as the handle. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 207 | if (http_instance == NULL) |
AzureIoTClient | 11:77df6d7e65ae | 208 | { |
AzureIoTClient | 11:77df6d7e65ae | 209 | LogError("There is no memory to control the http connection"); |
AzureIoTClient | 11:77df6d7e65ae | 210 | } |
AzureIoTClient | 11:77df6d7e65ae | 211 | else |
AzureIoTClient | 11:77df6d7e65ae | 212 | { |
AzureIoTClient | 11:77df6d7e65ae | 213 | tlsio_config.hostname = hostName; |
AzureIoTClient | 11:77df6d7e65ae | 214 | tlsio_config.port = 443; |
Azure.IoT Build | 6:c55b013dfc2a | 215 | |
AzureIoTClient | 13:920e00014ee3 | 216 | http_instance->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config); |
AzureIoTClient | 11:77df6d7e65ae | 217 | |
AzureIoTClient | 11:77df6d7e65ae | 218 | /*Codes_SRS_HTTPAPI_COMPACT_21_016: [ If the HTTPAPI_CreateConnection failed to create the connection, it shall return NULL as the handle. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 219 | if (http_instance->xio_handle == NULL) |
AzureIoTClient | 11:77df6d7e65ae | 220 | { |
AzureIoTClient | 11:77df6d7e65ae | 221 | LogError("Create connection failed"); |
AzureIoTClient | 13:920e00014ee3 | 222 | free(http_instance); |
AzureIoTClient | 13:920e00014ee3 | 223 | http_instance = NULL; |
AzureIoTClient | 11:77df6d7e65ae | 224 | } |
AzureIoTClient | 11:77df6d7e65ae | 225 | else |
AzureIoTClient | 11:77df6d7e65ae | 226 | { |
AzureIoTClient | 13:920e00014ee3 | 227 | http_instance->is_connected = 0; |
AzureIoTClient | 13:920e00014ee3 | 228 | http_instance->is_io_error = 0; |
AzureIoTClient | 13:920e00014ee3 | 229 | http_instance->received_bytes_count = 0; |
AzureIoTClient | 13:920e00014ee3 | 230 | http_instance->received_bytes = NULL; |
AzureIoTClient | 13:920e00014ee3 | 231 | http_instance->certificate = NULL; |
AzureIoTClient | 11:77df6d7e65ae | 232 | } |
AzureIoTClient | 11:77df6d7e65ae | 233 | } |
AzureIoTClient | 11:77df6d7e65ae | 234 | } |
AzureIoTClient | 11:77df6d7e65ae | 235 | |
AzureIoTClient | 11:77df6d7e65ae | 236 | /*Codes_SRS_HTTPAPI_COMPACT_21_012: [ The HTTPAPI_CreateConnection shall return a non-NULL handle on success. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 237 | return (HTTP_HANDLE)http_instance; |
Azure.IoT Build | 6:c55b013dfc2a | 238 | } |
Azure.IoT Build | 6:c55b013dfc2a | 239 | |
Azure.IoT Build | 6:c55b013dfc2a | 240 | void HTTPAPI_CloseConnection(HTTP_HANDLE handle) |
Azure.IoT Build | 6:c55b013dfc2a | 241 | { |
AzureIoTClient | 13:920e00014ee3 | 242 | HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle; |
Azure.IoT Build | 6:c55b013dfc2a | 243 | |
AzureIoTClient | 11:77df6d7e65ae | 244 | /*Codes_SRS_HTTPAPI_COMPACT_21_020: [ If the connection handle is NULL, the HTTPAPI_CloseConnection shall not do anything. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 245 | if (http_instance != NULL) |
Azure.IoT Build | 6:c55b013dfc2a | 246 | { |
AzureIoTClient | 11:77df6d7e65ae | 247 | /*Codes_SRS_HTTPAPI_COMPACT_21_019: [ If there is no previous connection, the HTTPAPI_CloseConnection shall not do anything. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 248 | if (http_instance->xio_handle != NULL) |
Azure.IoT Build | 6:c55b013dfc2a | 249 | { |
AzureIoTClient | 11:77df6d7e65ae | 250 | /*Codes_SRS_HTTPAPI_COMPACT_21_017: [ The HTTPAPI_CloseConnection shall close the connection previously created in HTTPAPI_CreateConnection. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 251 | xio_destroy(http_instance->xio_handle); |
Azure.IoT Build | 6:c55b013dfc2a | 252 | } |
Azure.IoT Build | 6:c55b013dfc2a | 253 | |
AzureIoTClient | 11:77df6d7e65ae | 254 | /*Codes_SRS_HTTPAPI_COMPACT_21_018: [ If there is a certificate associated to this connection, the HTTPAPI_CloseConnection shall free all allocated memory for the certificate. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 255 | if (http_instance->certificate) |
Azure.IoT Build | 6:c55b013dfc2a | 256 | { |
AzureIoTClient | 13:920e00014ee3 | 257 | free(http_instance->certificate); |
Azure.IoT Build | 6:c55b013dfc2a | 258 | } |
Azure.IoT Build | 6:c55b013dfc2a | 259 | |
AzureIoTClient | 13:920e00014ee3 | 260 | free(http_instance); |
Azure.IoT Build | 6:c55b013dfc2a | 261 | } |
Azure.IoT Build | 6:c55b013dfc2a | 262 | } |
Azure.IoT Build | 6:c55b013dfc2a | 263 | |
Azure.IoT Build | 6:c55b013dfc2a | 264 | static void on_io_open_complete(void* context, IO_OPEN_RESULT open_result) |
Azure.IoT Build | 6:c55b013dfc2a | 265 | { |
AzureIoTClient | 13:920e00014ee3 | 266 | HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context; |
AzureIoTClient | 11:77df6d7e65ae | 267 | |
AzureIoTClient | 13:920e00014ee3 | 268 | if (http_instance != NULL) |
AzureIoTClient | 11:77df6d7e65ae | 269 | { |
AzureIoTClient | 11:77df6d7e65ae | 270 | if (open_result == IO_OPEN_OK) |
AzureIoTClient | 11:77df6d7e65ae | 271 | { |
AzureIoTClient | 13:920e00014ee3 | 272 | http_instance->is_connected = 1; |
AzureIoTClient | 13:920e00014ee3 | 273 | http_instance->is_io_error = 0; |
AzureIoTClient | 11:77df6d7e65ae | 274 | } |
AzureIoTClient | 11:77df6d7e65ae | 275 | else |
AzureIoTClient | 11:77df6d7e65ae | 276 | { |
AzureIoTClient | 13:920e00014ee3 | 277 | http_instance->is_io_error = 1; |
AzureIoTClient | 11:77df6d7e65ae | 278 | } |
AzureIoTClient | 11:77df6d7e65ae | 279 | } |
Azure.IoT Build | 6:c55b013dfc2a | 280 | } |
Azure.IoT Build | 6:c55b013dfc2a | 281 | |
AzureIoTClient | 11:77df6d7e65ae | 282 | #define TOLOWER(c) (((c>='A') && (c<='Z'))?c-'A'+'a':c) |
AzureIoTClient | 11:77df6d7e65ae | 283 | static int InternStrnicmp(const char* s1, const char* s2, size_t n) |
Azure.IoT Build | 6:c55b013dfc2a | 284 | { |
AzureIoTClient | 11:77df6d7e65ae | 285 | int result; |
Azure.IoT Build | 6:c55b013dfc2a | 286 | |
AzureIoTClient | 11:77df6d7e65ae | 287 | if ((s1 == NULL) || (s2 == NULL)) |
AzureIoTClient | 11:77df6d7e65ae | 288 | { |
AzureIoTClient | 11:77df6d7e65ae | 289 | result = -1; |
AzureIoTClient | 11:77df6d7e65ae | 290 | } |
AzureIoTClient | 11:77df6d7e65ae | 291 | else |
AzureIoTClient | 11:77df6d7e65ae | 292 | { |
AzureIoTClient | 11:77df6d7e65ae | 293 | result = 0; |
AzureIoTClient | 11:77df6d7e65ae | 294 | while (((n--) >= 0) && ((*s1) != '\0') && ((*s2) != '\0') && (result == 0)) |
AzureIoTClient | 11:77df6d7e65ae | 295 | { |
AzureIoTClient | 11:77df6d7e65ae | 296 | /* compute the difference between the chars */ |
AzureIoTClient | 11:77df6d7e65ae | 297 | result = TOLOWER(*s1) - TOLOWER(*s2); |
AzureIoTClient | 11:77df6d7e65ae | 298 | s1++; |
AzureIoTClient | 11:77df6d7e65ae | 299 | s2++; |
AzureIoTClient | 11:77df6d7e65ae | 300 | } |
Azure.IoT Build | 6:c55b013dfc2a | 301 | |
AzureIoTClient | 11:77df6d7e65ae | 302 | if ((*s2) != '\0') |
Azure.IoT Build | 6:c55b013dfc2a | 303 | { |
AzureIoTClient | 11:77df6d7e65ae | 304 | result = -1; |
Azure.IoT Build | 6:c55b013dfc2a | 305 | } |
AzureIoTClient | 11:77df6d7e65ae | 306 | } |
Azure.IoT Build | 6:c55b013dfc2a | 307 | |
Azure.IoT Build | 6:c55b013dfc2a | 308 | return result; |
Azure.IoT Build | 6:c55b013dfc2a | 309 | } |
Azure.IoT Build | 6:c55b013dfc2a | 310 | |
Azure.IoT Build | 6:c55b013dfc2a | 311 | static void on_bytes_received(void* context, const unsigned char* buffer, size_t size) |
Azure.IoT Build | 6:c55b013dfc2a | 312 | { |
AzureIoTClient | 11:77df6d7e65ae | 313 | unsigned char* new_received_bytes; |
AzureIoTClient | 13:920e00014ee3 | 314 | HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context; |
AzureIoTClient | 11:77df6d7e65ae | 315 | |
AzureIoTClient | 13:920e00014ee3 | 316 | if (http_instance != NULL) |
AzureIoTClient | 13:920e00014ee3 | 317 | { |
Azure.IoT Build | 6:c55b013dfc2a | 318 | |
AzureIoTClient | 11:77df6d7e65ae | 319 | if (buffer == NULL) |
AzureIoTClient | 11:77df6d7e65ae | 320 | { |
AzureIoTClient | 13:920e00014ee3 | 321 | http_instance->is_io_error = 1; |
AzureIoTClient | 13:920e00014ee3 | 322 | LogError("NULL pointer error"); |
AzureIoTClient | 11:77df6d7e65ae | 323 | } |
AzureIoTClient | 11:77df6d7e65ae | 324 | else |
AzureIoTClient | 11:77df6d7e65ae | 325 | { |
AzureIoTClient | 11:77df6d7e65ae | 326 | /* Here we got some bytes so we'll buffer them so the receive functions can consumer it */ |
AzureIoTClient | 13:920e00014ee3 | 327 | new_received_bytes = (unsigned char*)realloc(http_instance->received_bytes, http_instance->received_bytes_count + size); |
AzureIoTClient | 11:77df6d7e65ae | 328 | if (new_received_bytes == NULL) |
AzureIoTClient | 11:77df6d7e65ae | 329 | { |
AzureIoTClient | 13:920e00014ee3 | 330 | http_instance->is_io_error = 1; |
AzureIoTClient | 13:920e00014ee3 | 331 | LogError("Error allocating memory for received data"); |
AzureIoTClient | 11:77df6d7e65ae | 332 | } |
AzureIoTClient | 11:77df6d7e65ae | 333 | else |
AzureIoTClient | 11:77df6d7e65ae | 334 | { |
AzureIoTClient | 13:920e00014ee3 | 335 | http_instance->received_bytes = new_received_bytes; |
AzureIoTClient | 13:920e00014ee3 | 336 | if (memcpy(http_instance->received_bytes + http_instance->received_bytes_count, buffer, size) == NULL) |
AzureIoTClient | 11:77df6d7e65ae | 337 | { |
AzureIoTClient | 13:920e00014ee3 | 338 | http_instance->is_io_error = 1; |
AzureIoTClient | 13:920e00014ee3 | 339 | LogError("Error copping received data to the HTTP bufffer"); |
AzureIoTClient | 11:77df6d7e65ae | 340 | } |
AzureIoTClient | 11:77df6d7e65ae | 341 | else |
AzureIoTClient | 11:77df6d7e65ae | 342 | { |
AzureIoTClient | 13:920e00014ee3 | 343 | http_instance->received_bytes_count += size; |
AzureIoTClient | 11:77df6d7e65ae | 344 | } |
AzureIoTClient | 11:77df6d7e65ae | 345 | } |
AzureIoTClient | 11:77df6d7e65ae | 346 | } |
AzureIoTClient | 11:77df6d7e65ae | 347 | } |
Azure.IoT Build | 6:c55b013dfc2a | 348 | } |
Azure.IoT Build | 6:c55b013dfc2a | 349 | |
Azure.IoT Build | 6:c55b013dfc2a | 350 | static void on_io_error(void* context) |
Azure.IoT Build | 6:c55b013dfc2a | 351 | { |
AzureIoTClient | 13:920e00014ee3 | 352 | HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context; |
AzureIoTClient | 13:920e00014ee3 | 353 | if (http_instance != NULL) |
AzureIoTClient | 13:920e00014ee3 | 354 | { |
AzureIoTClient | 13:920e00014ee3 | 355 | http_instance->is_io_error = 1; |
AzureIoTClient | 13:920e00014ee3 | 356 | LogError("Error signalled by underlying IO"); |
AzureIoTClient | 13:920e00014ee3 | 357 | } |
Azure.IoT Build | 6:c55b013dfc2a | 358 | } |
Azure.IoT Build | 6:c55b013dfc2a | 359 | |
Azure.IoT Build | 6:c55b013dfc2a | 360 | static int conn_receive(HTTP_HANDLE_DATA* http_instance, char* buffer, int count) |
Azure.IoT Build | 6:c55b013dfc2a | 361 | { |
AzureIoTClient | 11:77df6d7e65ae | 362 | int result; |
Azure.IoT Build | 6:c55b013dfc2a | 363 | |
AzureIoTClient | 11:77df6d7e65ae | 364 | if ((http_instance == NULL) || (buffer == NULL) || (count < 0)) |
AzureIoTClient | 11:77df6d7e65ae | 365 | { |
AzureIoTClient | 11:77df6d7e65ae | 366 | LogError("conn_receive: %s", ((http_instance == NULL) ? "Invalid HTTP instance" : "Invalid HTTP buffer")); |
Azure.IoT Build | 6:c55b013dfc2a | 367 | result = -1; |
AzureIoTClient | 11:77df6d7e65ae | 368 | } |
AzureIoTClient | 11:77df6d7e65ae | 369 | else |
AzureIoTClient | 11:77df6d7e65ae | 370 | { |
AzureIoTClient | 11:77df6d7e65ae | 371 | result = 0; |
AzureIoTClient | 11:77df6d7e65ae | 372 | while (result < count) |
AzureIoTClient | 11:77df6d7e65ae | 373 | { |
AzureIoTClient | 11:77df6d7e65ae | 374 | xio_dowork(http_instance->xio_handle); |
Azure.IoT Build | 6:c55b013dfc2a | 375 | |
AzureIoTClient | 11:77df6d7e65ae | 376 | /* if any error was detected while receiving then simply break and report it */ |
AzureIoTClient | 11:77df6d7e65ae | 377 | if (http_instance->is_io_error != 0) |
AzureIoTClient | 11:77df6d7e65ae | 378 | { |
AzureIoTClient | 13:920e00014ee3 | 379 | LogError("xio reported error on dowork"); |
Azure.IoT Build | 6:c55b013dfc2a | 380 | result = -1; |
AzureIoTClient | 11:77df6d7e65ae | 381 | break; |
AzureIoTClient | 11:77df6d7e65ae | 382 | } |
Azure.IoT Build | 6:c55b013dfc2a | 383 | |
AzureIoTClient | 11:77df6d7e65ae | 384 | if (http_instance->received_bytes_count >= (size_t)count) |
AzureIoTClient | 11:77df6d7e65ae | 385 | { |
AzureIoTClient | 11:77df6d7e65ae | 386 | /* Consuming bytes from the receive buffer */ |
AzureIoTClient | 11:77df6d7e65ae | 387 | (void)memcpy(buffer, http_instance->received_bytes, count); |
AzureIoTClient | 11:77df6d7e65ae | 388 | (void)memmove(http_instance->received_bytes, http_instance->received_bytes + count, http_instance->received_bytes_count - count); |
AzureIoTClient | 11:77df6d7e65ae | 389 | http_instance->received_bytes_count -= count; |
Azure.IoT Build | 6:c55b013dfc2a | 390 | |
AzureIoTClient | 11:77df6d7e65ae | 391 | /* we're not reallocating at each consumption so that we don't trash due to byte by byte consumption */ |
AzureIoTClient | 11:77df6d7e65ae | 392 | if (http_instance->received_bytes_count == 0) |
AzureIoTClient | 11:77df6d7e65ae | 393 | { |
AzureIoTClient | 11:77df6d7e65ae | 394 | free(http_instance->received_bytes); |
AzureIoTClient | 11:77df6d7e65ae | 395 | http_instance->received_bytes = NULL; |
AzureIoTClient | 11:77df6d7e65ae | 396 | } |
Azure.IoT Build | 6:c55b013dfc2a | 397 | |
AzureIoTClient | 11:77df6d7e65ae | 398 | result = count; |
AzureIoTClient | 11:77df6d7e65ae | 399 | break; |
AzureIoTClient | 11:77df6d7e65ae | 400 | } |
Azure.IoT Build | 6:c55b013dfc2a | 401 | |
AzureIoTClient | 13:920e00014ee3 | 402 | ThreadAPI_Sleep(RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS); |
AzureIoTClient | 11:77df6d7e65ae | 403 | } |
AzureIoTClient | 11:77df6d7e65ae | 404 | } |
Azure.IoT Build | 6:c55b013dfc2a | 405 | |
Azure.IoT Build | 6:c55b013dfc2a | 406 | return result; |
Azure.IoT Build | 6:c55b013dfc2a | 407 | } |
Azure.IoT Build | 6:c55b013dfc2a | 408 | |
AzureIoTClient | 11:77df6d7e65ae | 409 | static void conn_receive_discard_buffer(HTTP_HANDLE_DATA* http_instance) |
AzureIoTClient | 11:77df6d7e65ae | 410 | { |
AzureIoTClient | 13:920e00014ee3 | 411 | if (http_instance != NULL) |
AzureIoTClient | 11:77df6d7e65ae | 412 | { |
AzureIoTClient | 13:920e00014ee3 | 413 | if (http_instance->received_bytes != NULL) |
AzureIoTClient | 13:920e00014ee3 | 414 | { |
AzureIoTClient | 13:920e00014ee3 | 415 | free(http_instance->received_bytes); |
AzureIoTClient | 13:920e00014ee3 | 416 | http_instance->received_bytes = NULL; |
AzureIoTClient | 13:920e00014ee3 | 417 | } |
AzureIoTClient | 13:920e00014ee3 | 418 | http_instance->received_bytes_count = 0; |
AzureIoTClient | 11:77df6d7e65ae | 419 | } |
AzureIoTClient | 11:77df6d7e65ae | 420 | } |
AzureIoTClient | 11:77df6d7e65ae | 421 | |
AzureIoTClient | 13:920e00014ee3 | 422 | static int readLine(HTTP_HANDLE_DATA* http_instance, char* buf, const size_t maxBufSize) |
Azure.IoT Build | 6:c55b013dfc2a | 423 | { |
AzureIoTClient | 13:920e00014ee3 | 424 | int resultLineSize; |
Azure.IoT Build | 6:c55b013dfc2a | 425 | |
AzureIoTClient | 13:920e00014ee3 | 426 | if ((http_instance == NULL) || (buf == NULL) || (maxBufSize < 0)) |
AzureIoTClient | 13:920e00014ee3 | 427 | { |
AzureIoTClient | 13:920e00014ee3 | 428 | LogError("%s", ((http_instance == NULL) ? "Invalid HTTP instance" : "Invalid HTTP buffer")); |
AzureIoTClient | 13:920e00014ee3 | 429 | resultLineSize = -1; |
Azure.IoT Build | 6:c55b013dfc2a | 430 | } |
Azure.IoT Build | 6:c55b013dfc2a | 431 | else |
Azure.IoT Build | 6:c55b013dfc2a | 432 | { |
AzureIoTClient | 13:920e00014ee3 | 433 | char* destByte = buf; |
AzureIoTClient | 13:920e00014ee3 | 434 | /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 times. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 435 | int countRetry = MAX_RECEIVE_RETRY; |
AzureIoTClient | 13:920e00014ee3 | 436 | bool endOfSearch = false; |
AzureIoTClient | 13:920e00014ee3 | 437 | resultLineSize = -1; |
AzureIoTClient | 13:920e00014ee3 | 438 | while (!endOfSearch) |
Azure.IoT Build | 6:c55b013dfc2a | 439 | { |
AzureIoTClient | 13:920e00014ee3 | 440 | xio_dowork(http_instance->xio_handle); |
AzureIoTClient | 13:920e00014ee3 | 441 | |
AzureIoTClient | 13:920e00014ee3 | 442 | /* if any error was detected while receiving then simply break and report it */ |
AzureIoTClient | 13:920e00014ee3 | 443 | if (http_instance->is_io_error != 0) |
AzureIoTClient | 13:920e00014ee3 | 444 | { |
AzureIoTClient | 13:920e00014ee3 | 445 | LogError("xio reported error on dowork"); |
AzureIoTClient | 13:920e00014ee3 | 446 | endOfSearch = true; |
AzureIoTClient | 13:920e00014ee3 | 447 | } |
AzureIoTClient | 13:920e00014ee3 | 448 | else |
Azure.IoT Build | 6:c55b013dfc2a | 449 | { |
AzureIoTClient | 13:920e00014ee3 | 450 | unsigned char* receivedByte = http_instance->received_bytes; |
AzureIoTClient | 13:920e00014ee3 | 451 | while (receivedByte < (http_instance->received_bytes + http_instance->received_bytes_count)) |
Azure.IoT Build | 6:c55b013dfc2a | 452 | { |
AzureIoTClient | 13:920e00014ee3 | 453 | if ((*receivedByte) != '\r') |
AzureIoTClient | 13:920e00014ee3 | 454 | { |
AzureIoTClient | 13:920e00014ee3 | 455 | (*destByte) = (*receivedByte); |
AzureIoTClient | 13:920e00014ee3 | 456 | destByte++; |
AzureIoTClient | 13:920e00014ee3 | 457 | receivedByte++; |
Azure.IoT Build | 6:c55b013dfc2a | 458 | |
AzureIoTClient | 13:920e00014ee3 | 459 | if (destByte >= (buf + maxBufSize - 1)) |
AzureIoTClient | 13:920e00014ee3 | 460 | { |
AzureIoTClient | 13:920e00014ee3 | 461 | LogError("Received message is bigger than the http buffer"); |
AzureIoTClient | 13:920e00014ee3 | 462 | receivedByte = http_instance->received_bytes + http_instance->received_bytes_count; |
AzureIoTClient | 13:920e00014ee3 | 463 | endOfSearch = true; |
AzureIoTClient | 13:920e00014ee3 | 464 | break; |
AzureIoTClient | 13:920e00014ee3 | 465 | } |
AzureIoTClient | 13:920e00014ee3 | 466 | } |
AzureIoTClient | 13:920e00014ee3 | 467 | else |
AzureIoTClient | 13:920e00014ee3 | 468 | { |
AzureIoTClient | 13:920e00014ee3 | 469 | receivedByte++; |
AzureIoTClient | 13:920e00014ee3 | 470 | if ((receivedByte < (http_instance->received_bytes + http_instance->received_bytes_count)) && ((*receivedByte) == '\n')) |
AzureIoTClient | 13:920e00014ee3 | 471 | { |
AzureIoTClient | 13:920e00014ee3 | 472 | receivedByte++; |
AzureIoTClient | 13:920e00014ee3 | 473 | } |
AzureIoTClient | 13:920e00014ee3 | 474 | (*destByte) = '\0'; |
AzureIoTClient | 13:920e00014ee3 | 475 | resultLineSize = (int)(destByte - buf); |
AzureIoTClient | 13:920e00014ee3 | 476 | endOfSearch = true; |
AzureIoTClient | 13:920e00014ee3 | 477 | break; |
AzureIoTClient | 13:920e00014ee3 | 478 | } |
Azure.IoT Build | 6:c55b013dfc2a | 479 | } |
Azure.IoT Build | 6:c55b013dfc2a | 480 | |
AzureIoTClient | 13:920e00014ee3 | 481 | http_instance->received_bytes_count -= (receivedByte - http_instance->received_bytes); |
AzureIoTClient | 13:920e00014ee3 | 482 | if (http_instance->received_bytes_count != 0) |
AzureIoTClient | 13:920e00014ee3 | 483 | { |
AzureIoTClient | 13:920e00014ee3 | 484 | (void)memmove(http_instance->received_bytes, receivedByte, http_instance->received_bytes_count); |
AzureIoTClient | 13:920e00014ee3 | 485 | } |
AzureIoTClient | 13:920e00014ee3 | 486 | else |
AzureIoTClient | 13:920e00014ee3 | 487 | { |
AzureIoTClient | 13:920e00014ee3 | 488 | conn_receive_discard_buffer(http_instance); |
AzureIoTClient | 13:920e00014ee3 | 489 | } |
Azure.IoT Build | 6:c55b013dfc2a | 490 | } |
Azure.IoT Build | 6:c55b013dfc2a | 491 | |
AzureIoTClient | 13:920e00014ee3 | 492 | if (!endOfSearch) |
Azure.IoT Build | 6:c55b013dfc2a | 493 | { |
AzureIoTClient | 13:920e00014ee3 | 494 | if ((countRetry--) > 0) |
AzureIoTClient | 13:920e00014ee3 | 495 | { |
AzureIoTClient | 13:920e00014ee3 | 496 | /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 497 | ThreadAPI_Sleep(RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS); |
AzureIoTClient | 13:920e00014ee3 | 498 | } |
AzureIoTClient | 13:920e00014ee3 | 499 | else |
AzureIoTClient | 13:920e00014ee3 | 500 | { |
AzureIoTClient | 13:920e00014ee3 | 501 | /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 502 | LogError("Timeout. The HTTP request is incomplete"); |
AzureIoTClient | 13:920e00014ee3 | 503 | endOfSearch = true; |
AzureIoTClient | 13:920e00014ee3 | 504 | } |
Azure.IoT Build | 6:c55b013dfc2a | 505 | } |
Azure.IoT Build | 6:c55b013dfc2a | 506 | } |
Azure.IoT Build | 6:c55b013dfc2a | 507 | } |
Azure.IoT Build | 6:c55b013dfc2a | 508 | |
AzureIoTClient | 13:920e00014ee3 | 509 | return resultLineSize; |
Azure.IoT Build | 6:c55b013dfc2a | 510 | } |
Azure.IoT Build | 6:c55b013dfc2a | 511 | |
Azure.IoT Build | 6:c55b013dfc2a | 512 | static int readChunk(HTTP_HANDLE_DATA* http_instance, char* buf, size_t size) |
Azure.IoT Build | 6:c55b013dfc2a | 513 | { |
AzureIoTClient | 11:77df6d7e65ae | 514 | int cur, offset; |
Azure.IoT Build | 6:c55b013dfc2a | 515 | |
Azure.IoT Build | 6:c55b013dfc2a | 516 | // read content with specified length, even if it is received |
Azure.IoT Build | 6:c55b013dfc2a | 517 | // only in chunks due to fragmentation in the networking layer. |
Azure.IoT Build | 6:c55b013dfc2a | 518 | // returns -1 in case of error. |
Azure.IoT Build | 6:c55b013dfc2a | 519 | offset = 0; |
AzureIoTClient | 11:77df6d7e65ae | 520 | while (size > (size_t)0) |
Azure.IoT Build | 6:c55b013dfc2a | 521 | { |
AzureIoTClient | 11:77df6d7e65ae | 522 | cur = conn_receive(http_instance, buf + offset, (int)size); |
Azure.IoT Build | 6:c55b013dfc2a | 523 | |
Azure.IoT Build | 6:c55b013dfc2a | 524 | // end of stream reached |
AzureIoTClient | 11:77df6d7e65ae | 525 | if (cur == 0) |
AzureIoTClient | 11:77df6d7e65ae | 526 | { |
AzureIoTClient | 11:77df6d7e65ae | 527 | break; |
AzureIoTClient | 11:77df6d7e65ae | 528 | } |
Azure.IoT Build | 6:c55b013dfc2a | 529 | |
Azure.IoT Build | 6:c55b013dfc2a | 530 | // read cur bytes (might be less than requested) |
AzureIoTClient | 11:77df6d7e65ae | 531 | size -= (size_t)cur; |
Azure.IoT Build | 6:c55b013dfc2a | 532 | offset += cur; |
Azure.IoT Build | 6:c55b013dfc2a | 533 | } |
Azure.IoT Build | 6:c55b013dfc2a | 534 | |
Azure.IoT Build | 6:c55b013dfc2a | 535 | return offset; |
Azure.IoT Build | 6:c55b013dfc2a | 536 | } |
Azure.IoT Build | 6:c55b013dfc2a | 537 | |
AzureIoTClient | 13:920e00014ee3 | 538 | static int skipN(HTTP_HANDLE_DATA* http_instance, size_t n) |
Azure.IoT Build | 6:c55b013dfc2a | 539 | { |
Azure.IoT Build | 6:c55b013dfc2a | 540 | // read and abandon response content with specified length |
Azure.IoT Build | 6:c55b013dfc2a | 541 | // returns -1 in case of error. |
AzureIoTClient | 13:920e00014ee3 | 542 | |
AzureIoTClient | 13:920e00014ee3 | 543 | int result; |
AzureIoTClient | 13:920e00014ee3 | 544 | |
AzureIoTClient | 13:920e00014ee3 | 545 | if (http_instance == NULL) |
AzureIoTClient | 13:920e00014ee3 | 546 | { |
AzureIoTClient | 13:920e00014ee3 | 547 | LogError("Invalid HTTP instance"); |
AzureIoTClient | 13:920e00014ee3 | 548 | result = -1; |
AzureIoTClient | 13:920e00014ee3 | 549 | } |
AzureIoTClient | 13:920e00014ee3 | 550 | else |
Azure.IoT Build | 6:c55b013dfc2a | 551 | { |
AzureIoTClient | 13:920e00014ee3 | 552 | /*Codes_SRS_HTTPAPI_COMPACT_21_076: [ The HTTPAPI_ExecuteRequest shall try to read the message with the response up to 20 times. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 553 | int countRetry = MAX_RECEIVE_RETRY; |
AzureIoTClient | 13:920e00014ee3 | 554 | result = (int)n; |
AzureIoTClient | 13:920e00014ee3 | 555 | while (n > 0) |
AzureIoTClient | 13:920e00014ee3 | 556 | { |
AzureIoTClient | 13:920e00014ee3 | 557 | xio_dowork(http_instance->xio_handle); |
Azure.IoT Build | 6:c55b013dfc2a | 558 | |
AzureIoTClient | 13:920e00014ee3 | 559 | /* if any error was detected while receiving then simply break and report it */ |
AzureIoTClient | 13:920e00014ee3 | 560 | if (http_instance->is_io_error != 0) |
AzureIoTClient | 13:920e00014ee3 | 561 | { |
AzureIoTClient | 13:920e00014ee3 | 562 | LogError("xio reported error on dowork"); |
AzureIoTClient | 13:920e00014ee3 | 563 | result = -1; |
AzureIoTClient | 13:920e00014ee3 | 564 | n = 0; |
AzureIoTClient | 13:920e00014ee3 | 565 | } |
AzureIoTClient | 13:920e00014ee3 | 566 | else |
AzureIoTClient | 13:920e00014ee3 | 567 | { |
AzureIoTClient | 13:920e00014ee3 | 568 | if (http_instance->received_bytes_count <= n) |
AzureIoTClient | 13:920e00014ee3 | 569 | { |
AzureIoTClient | 13:920e00014ee3 | 570 | n -= http_instance->received_bytes_count; |
AzureIoTClient | 13:920e00014ee3 | 571 | http_instance->received_bytes_count = 0; |
AzureIoTClient | 13:920e00014ee3 | 572 | } |
AzureIoTClient | 13:920e00014ee3 | 573 | else |
AzureIoTClient | 13:920e00014ee3 | 574 | { |
AzureIoTClient | 13:920e00014ee3 | 575 | http_instance->received_bytes_count -= n; |
AzureIoTClient | 13:920e00014ee3 | 576 | (void)memmove(http_instance->received_bytes, http_instance->received_bytes + n, http_instance->received_bytes_count); |
AzureIoTClient | 13:920e00014ee3 | 577 | n = 0; |
AzureIoTClient | 13:920e00014ee3 | 578 | } |
AzureIoTClient | 13:920e00014ee3 | 579 | |
AzureIoTClient | 13:920e00014ee3 | 580 | if (n > 0) |
AzureIoTClient | 13:920e00014ee3 | 581 | { |
AzureIoTClient | 13:920e00014ee3 | 582 | if ((countRetry--) > 0) |
AzureIoTClient | 13:920e00014ee3 | 583 | { |
AzureIoTClient | 13:920e00014ee3 | 584 | /*Codes_SRS_HTTPAPI_COMPACT_21_078: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 585 | ThreadAPI_Sleep(RECEIVE_RETRY_INTERVAL_IN_MICROSECONDS); |
AzureIoTClient | 13:920e00014ee3 | 586 | } |
AzureIoTClient | 13:920e00014ee3 | 587 | else |
AzureIoTClient | 13:920e00014ee3 | 588 | { |
AzureIoTClient | 13:920e00014ee3 | 589 | /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 590 | LogError("Timeout. The HTTP request is incomplete"); |
AzureIoTClient | 13:920e00014ee3 | 591 | n = 0; |
AzureIoTClient | 13:920e00014ee3 | 592 | result = -1; |
AzureIoTClient | 13:920e00014ee3 | 593 | } |
AzureIoTClient | 13:920e00014ee3 | 594 | } |
AzureIoTClient | 13:920e00014ee3 | 595 | } |
AzureIoTClient | 13:920e00014ee3 | 596 | } |
Azure.IoT Build | 6:c55b013dfc2a | 597 | } |
Azure.IoT Build | 6:c55b013dfc2a | 598 | |
AzureIoTClient | 13:920e00014ee3 | 599 | return result; |
Azure.IoT Build | 6:c55b013dfc2a | 600 | } |
Azure.IoT Build | 6:c55b013dfc2a | 601 | |
AzureIoTClient | 11:77df6d7e65ae | 602 | |
AzureIoTClient | 11:77df6d7e65ae | 603 | /*Codes_SRS_HTTPAPI_COMPACT_21_021: [ The HTTPAPI_ExecuteRequest shall execute the http communtication with the provided host, sending a request and reciving the response. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 604 | static HTTPAPI_RESULT OpenXIOConnection(HTTP_HANDLE_DATA* http_instance) |
AzureIoTClient | 11:77df6d7e65ae | 605 | { |
AzureIoTClient | 11:77df6d7e65ae | 606 | HTTPAPI_RESULT result; |
AzureIoTClient | 11:77df6d7e65ae | 607 | |
AzureIoTClient | 13:920e00014ee3 | 608 | if (http_instance->is_connected != 0) |
AzureIoTClient | 11:77df6d7e65ae | 609 | { |
AzureIoTClient | 11:77df6d7e65ae | 610 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 611 | result = HTTPAPI_OK; |
AzureIoTClient | 11:77df6d7e65ae | 612 | } |
AzureIoTClient | 11:77df6d7e65ae | 613 | else |
AzureIoTClient | 11:77df6d7e65ae | 614 | { |
AzureIoTClient | 11:77df6d7e65ae | 615 | /*Codes_SRS_HTTPAPI_COMPACT_21_022: [ If a Certificate was provided, the HTTPAPI_ExecuteRequest shall set this option on the transport layer. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 616 | if ((http_instance->certificate != NULL) && |
AzureIoTClient | 13:920e00014ee3 | 617 | (xio_setoption(http_instance->xio_handle, "TrustedCerts", http_instance->certificate) != 0)) |
AzureIoTClient | 11:77df6d7e65ae | 618 | { |
AzureIoTClient | 11:77df6d7e65ae | 619 | /*Codes_SRS_HTTPAPI_COMPACT_21_023: [ If the transport failed setting the Certificate, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_SET_OPTION_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 620 | result = HTTPAPI_SET_OPTION_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 621 | LogInfo("Could not load certificate"); |
AzureIoTClient | 11:77df6d7e65ae | 622 | } |
AzureIoTClient | 11:77df6d7e65ae | 623 | else |
AzureIoTClient | 11:77df6d7e65ae | 624 | { |
AzureIoTClient | 11:77df6d7e65ae | 625 | /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 626 | if (xio_open(http_instance->xio_handle, on_io_open_complete, http_instance, on_bytes_received, http_instance, on_io_error, http_instance) != 0) |
AzureIoTClient | 11:77df6d7e65ae | 627 | { |
AzureIoTClient | 11:77df6d7e65ae | 628 | /*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 629 | result = HTTPAPI_OPEN_REQUEST_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 630 | } |
AzureIoTClient | 11:77df6d7e65ae | 631 | else |
AzureIoTClient | 11:77df6d7e65ae | 632 | { |
AzureIoTClient | 11:77df6d7e65ae | 633 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 634 | result = HTTPAPI_OK; |
AzureIoTClient | 13:920e00014ee3 | 635 | while ((http_instance->is_connected == 0) && |
AzureIoTClient | 13:920e00014ee3 | 636 | (http_instance->is_io_error == 0)) |
AzureIoTClient | 11:77df6d7e65ae | 637 | { |
AzureIoTClient | 13:920e00014ee3 | 638 | xio_dowork(http_instance->xio_handle); |
AzureIoTClient | 11:77df6d7e65ae | 639 | LogInfo("Waiting for TLS connection"); |
AzureIoTClient | 13:920e00014ee3 | 640 | ThreadAPI_Sleep(OPEN_RETRY_INTERVAL_IN_MICROSECONDS); |
AzureIoTClient | 11:77df6d7e65ae | 641 | } |
AzureIoTClient | 11:77df6d7e65ae | 642 | } |
AzureIoTClient | 11:77df6d7e65ae | 643 | } |
AzureIoTClient | 11:77df6d7e65ae | 644 | } |
AzureIoTClient | 11:77df6d7e65ae | 645 | |
AzureIoTClient | 13:920e00014ee3 | 646 | if ((http_instance->is_io_error != 0) && (result == HTTPAPI_OK)) |
AzureIoTClient | 11:77df6d7e65ae | 647 | { |
AzureIoTClient | 11:77df6d7e65ae | 648 | /*Codes_SRS_HTTPAPI_COMPACT_21_025: [ If the open process failed, the HTTPAPI_ExecuteRequest shall not send any request and return HTTPAPI_OPEN_REQUEST_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 649 | result = HTTPAPI_OPEN_REQUEST_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 650 | } |
AzureIoTClient | 11:77df6d7e65ae | 651 | |
AzureIoTClient | 11:77df6d7e65ae | 652 | return result; |
AzureIoTClient | 11:77df6d7e65ae | 653 | } |
AzureIoTClient | 11:77df6d7e65ae | 654 | |
AzureIoTClient | 11:77df6d7e65ae | 655 | /*Codes_SRS_HTTPAPI_COMPACT_21_035: [ The HTTPAPI_ExecuteRequest shall execute resquest for types `GET`, `POST`, `PUT`, `DELETE`, `PATCH`. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 656 | const char httpapiRequestString[5][7] = { "GET", "POST", "PUT", "DELETE", "PATCH" }; |
AzureIoTClient | 11:77df6d7e65ae | 657 | const char* get_request_type(HTTPAPI_REQUEST_TYPE requestType) |
AzureIoTClient | 11:77df6d7e65ae | 658 | { |
AzureIoTClient | 11:77df6d7e65ae | 659 | return (const char*)httpapiRequestString[requestType]; |
AzureIoTClient | 11:77df6d7e65ae | 660 | } |
AzureIoTClient | 11:77df6d7e65ae | 661 | |
AzureIoTClient | 11:77df6d7e65ae | 662 | /*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 663 | static HTTPAPI_RESULT SendHeadsToXIO(HTTP_HANDLE_DATA* http_instance, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE httpHeadersHandle, size_t headersCount) |
AzureIoTClient | 11:77df6d7e65ae | 664 | { |
AzureIoTClient | 11:77df6d7e65ae | 665 | HTTPAPI_RESULT result; |
AzureIoTClient | 11:77df6d7e65ae | 666 | char buf[TEMP_BUFFER_SIZE]; |
AzureIoTClient | 11:77df6d7e65ae | 667 | int ret; |
AzureIoTClient | 11:77df6d7e65ae | 668 | |
AzureIoTClient | 11:77df6d7e65ae | 669 | //Send request |
AzureIoTClient | 11:77df6d7e65ae | 670 | /*Codes_SRS_HTTPAPI_COMPACT_21_038: [ The HTTPAPI_ExecuteRequest shall execute the resquest for the path in relativePath parameter. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 671 | /*Codes_SRS_HTTPAPI_COMPACT_21_036: [ The request type shall be provided in the parameter requestType. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 672 | if (((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", get_request_type(requestType), relativePath)) < 0) || |
AzureIoTClient | 11:77df6d7e65ae | 673 | (ret >= sizeof(buf))) |
AzureIoTClient | 11:77df6d7e65ae | 674 | { |
AzureIoTClient | 11:77df6d7e65ae | 675 | /*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 676 | result = HTTPAPI_STRING_PROCESSING_ERROR; |
AzureIoTClient | 11:77df6d7e65ae | 677 | } |
AzureIoTClient | 13:920e00014ee3 | 678 | else if (xio_send(http_instance->xio_handle, (const unsigned char*)buf, strlen(buf), NULL, NULL) != 0) |
AzureIoTClient | 13:920e00014ee3 | 679 | { |
AzureIoTClient | 11:77df6d7e65ae | 680 | /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 681 | result = HTTPAPI_SEND_REQUEST_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 682 | } |
AzureIoTClient | 11:77df6d7e65ae | 683 | else |
AzureIoTClient | 11:77df6d7e65ae | 684 | { |
AzureIoTClient | 11:77df6d7e65ae | 685 | //Send default headers |
AzureIoTClient | 11:77df6d7e65ae | 686 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 687 | result = HTTPAPI_OK; |
AzureIoTClient | 11:77df6d7e65ae | 688 | for (size_t i = 0; ((i < headersCount) && (result == HTTPAPI_OK)); i++) |
AzureIoTClient | 11:77df6d7e65ae | 689 | { |
AzureIoTClient | 11:77df6d7e65ae | 690 | char* header; |
AzureIoTClient | 11:77df6d7e65ae | 691 | if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK) |
AzureIoTClient | 11:77df6d7e65ae | 692 | { |
AzureIoTClient | 11:77df6d7e65ae | 693 | /*Codes_SRS_HTTPAPI_COMPACT_21_027: [ If the HTTPAPI_ExecuteRequest cannot create a buffer to send the request, it shall not send any request and return HTTPAPI_STRING_PROCESSING_ERROR. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 694 | result = HTTPAPI_STRING_PROCESSING_ERROR; |
AzureIoTClient | 11:77df6d7e65ae | 695 | } |
AzureIoTClient | 11:77df6d7e65ae | 696 | else |
AzureIoTClient | 11:77df6d7e65ae | 697 | { |
AzureIoTClient | 13:920e00014ee3 | 698 | if (xio_send(http_instance->xio_handle, (const unsigned char*)header, strlen(header), NULL, NULL) != 0) |
AzureIoTClient | 13:920e00014ee3 | 699 | { |
AzureIoTClient | 11:77df6d7e65ae | 700 | /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 701 | result = HTTPAPI_SEND_REQUEST_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 702 | } |
AzureIoTClient | 13:920e00014ee3 | 703 | if (xio_send(http_instance->xio_handle, (const unsigned char*)"\r\n", (size_t)2, NULL, NULL) != 0) |
AzureIoTClient | 13:920e00014ee3 | 704 | { |
AzureIoTClient | 11:77df6d7e65ae | 705 | /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 706 | result = HTTPAPI_SEND_REQUEST_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 707 | } |
AzureIoTClient | 11:77df6d7e65ae | 708 | free(header); |
AzureIoTClient | 11:77df6d7e65ae | 709 | } |
AzureIoTClient | 11:77df6d7e65ae | 710 | } |
AzureIoTClient | 11:77df6d7e65ae | 711 | |
AzureIoTClient | 11:77df6d7e65ae | 712 | //Close headers |
AzureIoTClient | 13:920e00014ee3 | 713 | if (xio_send(http_instance->xio_handle, (const unsigned char*)"\r\n", (size_t)2, NULL, NULL) != 0) |
AzureIoTClient | 13:920e00014ee3 | 714 | { |
AzureIoTClient | 11:77df6d7e65ae | 715 | /*Codes_SRS_HTTPAPI_COMPACT_21_028: [ If the HTTPAPI_ExecuteRequest cannot send the request header, it shall return HTTPAPI_HTTP_HEADERS_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 716 | result = HTTPAPI_SEND_REQUEST_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 717 | } |
AzureIoTClient | 11:77df6d7e65ae | 718 | } |
AzureIoTClient | 11:77df6d7e65ae | 719 | return result; |
AzureIoTClient | 11:77df6d7e65ae | 720 | } |
AzureIoTClient | 11:77df6d7e65ae | 721 | |
AzureIoTClient | 11:77df6d7e65ae | 722 | /*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 723 | static HTTPAPI_RESULT SendContentToXIO(HTTP_HANDLE_DATA* http_instance, const unsigned char* content, size_t contentLength) |
AzureIoTClient | 11:77df6d7e65ae | 724 | { |
AzureIoTClient | 11:77df6d7e65ae | 725 | HTTPAPI_RESULT result; |
AzureIoTClient | 11:77df6d7e65ae | 726 | |
AzureIoTClient | 11:77df6d7e65ae | 727 | //Send data (if available) |
AzureIoTClient | 11:77df6d7e65ae | 728 | /*Codes_SRS_HTTPAPI_COMPACT_21_045: [ If the contentLength is lower than one, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 729 | if (content && contentLength > 0) |
AzureIoTClient | 11:77df6d7e65ae | 730 | { |
AzureIoTClient | 11:77df6d7e65ae | 731 | /*Codes_SRS_HTTPAPI_COMPACT_21_044: [ If the content is not NULL, the number of bytes in the content shall be provided in contentLength parameter. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 732 | if (xio_send(http_instance->xio_handle, content, contentLength, NULL, NULL) != 0) |
AzureIoTClient | 13:920e00014ee3 | 733 | { |
AzureIoTClient | 11:77df6d7e65ae | 734 | /*Codes_SRS_HTTPAPI_COMPACT_21_029: [ If the HTTPAPI_ExecuteRequest cannot send the buffer with the request, it shall return HTTPAPI_SEND_REQUEST_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 735 | result = HTTPAPI_SEND_REQUEST_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 736 | } |
AzureIoTClient | 11:77df6d7e65ae | 737 | else |
AzureIoTClient | 11:77df6d7e65ae | 738 | { |
AzureIoTClient | 11:77df6d7e65ae | 739 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 740 | result = HTTPAPI_OK; |
AzureIoTClient | 11:77df6d7e65ae | 741 | } |
AzureIoTClient | 11:77df6d7e65ae | 742 | } |
AzureIoTClient | 11:77df6d7e65ae | 743 | else |
AzureIoTClient | 11:77df6d7e65ae | 744 | { |
AzureIoTClient | 11:77df6d7e65ae | 745 | /*Codes_SRS_HTTPAPI_COMPACT_21_043: [ If the content is NULL, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 746 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 747 | result = HTTPAPI_OK; |
AzureIoTClient | 11:77df6d7e65ae | 748 | } |
AzureIoTClient | 11:77df6d7e65ae | 749 | return result; |
AzureIoTClient | 11:77df6d7e65ae | 750 | } |
AzureIoTClient | 11:77df6d7e65ae | 751 | |
AzureIoTClient | 11:77df6d7e65ae | 752 | /*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 753 | static HTTPAPI_RESULT RecieveHeaderFromXIO(HTTP_HANDLE_DATA* http_instance, unsigned int* statusCode) |
AzureIoTClient | 11:77df6d7e65ae | 754 | { |
AzureIoTClient | 11:77df6d7e65ae | 755 | HTTPAPI_RESULT result; |
AzureIoTClient | 11:77df6d7e65ae | 756 | char buf[TEMP_BUFFER_SIZE]; |
AzureIoTClient | 11:77df6d7e65ae | 757 | int ret; |
AzureIoTClient | 11:77df6d7e65ae | 758 | |
AzureIoTClient | 11:77df6d7e65ae | 759 | //Receive response |
AzureIoTClient | 13:920e00014ee3 | 760 | if (readLine(http_instance, buf, TEMP_BUFFER_SIZE) < 0) |
AzureIoTClient | 11:77df6d7e65ae | 761 | { |
AzureIoTClient | 11:77df6d7e65ae | 762 | /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 763 | /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 764 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 765 | } |
AzureIoTClient | 11:77df6d7e65ae | 766 | //Parse HTTP response |
AzureIoTClient | 11:77df6d7e65ae | 767 | else if (ParseHttpResponse(buf, &ret) != 1) |
AzureIoTClient | 11:77df6d7e65ae | 768 | { |
AzureIoTClient | 11:77df6d7e65ae | 769 | //Cannot match string, error |
AzureIoTClient | 11:77df6d7e65ae | 770 | /*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the recived message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 771 | LogInfo("Not a correct HTTP answer"); |
AzureIoTClient | 11:77df6d7e65ae | 772 | result = HTTPAPI_RECEIVE_RESPONSE_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 773 | } |
AzureIoTClient | 11:77df6d7e65ae | 774 | else |
AzureIoTClient | 11:77df6d7e65ae | 775 | { |
AzureIoTClient | 11:77df6d7e65ae | 776 | /*Codes_SRS_HTTPAPI_COMPACT_21_046: [ The HTTPAPI_ExecuteRequest shall return the http status reported by the host in the received response. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 777 | /*Codes_SRS_HTTPAPI_COMPACT_21_048: [ If the statusCode is NULL, the HTTPAPI_ExecuteRequest shall report not report any status. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 778 | if (statusCode) |
AzureIoTClient | 11:77df6d7e65ae | 779 | { |
AzureIoTClient | 11:77df6d7e65ae | 780 | /*Codes_SRS_HTTPAPI_COMPACT_21_047: [ The HTTPAPI_ExecuteRequest shall report the status in the statusCode parameter. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 781 | *statusCode = ret; |
AzureIoTClient | 11:77df6d7e65ae | 782 | } |
AzureIoTClient | 11:77df6d7e65ae | 783 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 784 | result = HTTPAPI_OK; |
AzureIoTClient | 11:77df6d7e65ae | 785 | } |
AzureIoTClient | 11:77df6d7e65ae | 786 | |
AzureIoTClient | 11:77df6d7e65ae | 787 | return result; |
AzureIoTClient | 11:77df6d7e65ae | 788 | } |
AzureIoTClient | 11:77df6d7e65ae | 789 | |
AzureIoTClient | 13:920e00014ee3 | 790 | static HTTPAPI_RESULT RecieveContentInfoFromXIO(HTTP_HANDLE_DATA* http_instance, HTTP_HEADERS_HANDLE responseHeadersHandle, size_t* bodyLength, bool* chunked) |
AzureIoTClient | 11:77df6d7e65ae | 791 | { |
AzureIoTClient | 11:77df6d7e65ae | 792 | HTTPAPI_RESULT result; |
AzureIoTClient | 11:77df6d7e65ae | 793 | char buf[TEMP_BUFFER_SIZE]; |
AzureIoTClient | 11:77df6d7e65ae | 794 | const char* substr; |
AzureIoTClient | 11:77df6d7e65ae | 795 | char* whereIsColon; |
AzureIoTClient | 11:77df6d7e65ae | 796 | int lengthInMsg; |
AzureIoTClient | 11:77df6d7e65ae | 797 | const char* ContentLength = "content-length:"; |
AzureIoTClient | 11:77df6d7e65ae | 798 | const int ContentLengthSize = 16; |
AzureIoTClient | 11:77df6d7e65ae | 799 | const char* TransferEncoding = "transfer-encoding:"; |
AzureIoTClient | 11:77df6d7e65ae | 800 | const int TransferEncodingSize = 19; |
AzureIoTClient | 11:77df6d7e65ae | 801 | const char* Chunked = "chunked"; |
AzureIoTClient | 11:77df6d7e65ae | 802 | const int ChunkedSize = 8; |
AzureIoTClient | 11:77df6d7e65ae | 803 | |
AzureIoTClient | 11:77df6d7e65ae | 804 | //Read HTTP response headers |
AzureIoTClient | 13:920e00014ee3 | 805 | if (readLine(http_instance, buf, sizeof(buf)) < 0) |
AzureIoTClient | 11:77df6d7e65ae | 806 | { |
AzureIoTClient | 11:77df6d7e65ae | 807 | /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 808 | /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 809 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 810 | } |
AzureIoTClient | 11:77df6d7e65ae | 811 | else |
AzureIoTClient | 11:77df6d7e65ae | 812 | { |
AzureIoTClient | 11:77df6d7e65ae | 813 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 814 | result = HTTPAPI_OK; |
AzureIoTClient | 11:77df6d7e65ae | 815 | |
AzureIoTClient | 11:77df6d7e65ae | 816 | while (*buf && (result == HTTPAPI_OK)) |
AzureIoTClient | 11:77df6d7e65ae | 817 | { |
AzureIoTClient | 11:77df6d7e65ae | 818 | if (InternStrnicmp(buf, ContentLength, ContentLengthSize) == 0) |
AzureIoTClient | 11:77df6d7e65ae | 819 | { |
AzureIoTClient | 11:77df6d7e65ae | 820 | substr = buf + ContentLengthSize - 1; |
AzureIoTClient | 11:77df6d7e65ae | 821 | if (ParseStringToDecimal(substr, &lengthInMsg) != 1) |
AzureIoTClient | 11:77df6d7e65ae | 822 | { |
AzureIoTClient | 11:77df6d7e65ae | 823 | /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 824 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 825 | } |
AzureIoTClient | 11:77df6d7e65ae | 826 | else |
AzureIoTClient | 11:77df6d7e65ae | 827 | { |
AzureIoTClient | 11:77df6d7e65ae | 828 | (*bodyLength) = (size_t)lengthInMsg; |
AzureIoTClient | 11:77df6d7e65ae | 829 | } |
AzureIoTClient | 11:77df6d7e65ae | 830 | } |
AzureIoTClient | 11:77df6d7e65ae | 831 | else if (InternStrnicmp(buf, TransferEncoding, TransferEncodingSize) == 0) |
AzureIoTClient | 11:77df6d7e65ae | 832 | { |
AzureIoTClient | 11:77df6d7e65ae | 833 | substr = buf + TransferEncodingSize - 1; |
AzureIoTClient | 11:77df6d7e65ae | 834 | |
AzureIoTClient | 11:77df6d7e65ae | 835 | while (isspace(*substr)) substr++; |
AzureIoTClient | 11:77df6d7e65ae | 836 | |
AzureIoTClient | 11:77df6d7e65ae | 837 | if (InternStrnicmp(substr, Chunked, ChunkedSize) == 0) |
AzureIoTClient | 11:77df6d7e65ae | 838 | { |
AzureIoTClient | 11:77df6d7e65ae | 839 | (*chunked) = true; |
AzureIoTClient | 11:77df6d7e65ae | 840 | } |
AzureIoTClient | 11:77df6d7e65ae | 841 | } |
AzureIoTClient | 11:77df6d7e65ae | 842 | |
AzureIoTClient | 11:77df6d7e65ae | 843 | if (result == HTTPAPI_OK) |
AzureIoTClient | 11:77df6d7e65ae | 844 | { |
AzureIoTClient | 11:77df6d7e65ae | 845 | whereIsColon = strchr((char*)buf, ':'); |
AzureIoTClient | 11:77df6d7e65ae | 846 | /*Codes_SRS_HTTPAPI_COMPACT_21_049: [ If responseHeadersHandle is provide, the HTTPAPI_ExecuteRequest shall prepare a Response Header usign the HTTPHeaders_AddHeaderNameValuePair. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 847 | if (whereIsColon && (responseHeadersHandle != NULL)) |
AzureIoTClient | 11:77df6d7e65ae | 848 | { |
AzureIoTClient | 11:77df6d7e65ae | 849 | *whereIsColon = '\0'; |
AzureIoTClient | 11:77df6d7e65ae | 850 | HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1); |
AzureIoTClient | 11:77df6d7e65ae | 851 | } |
AzureIoTClient | 11:77df6d7e65ae | 852 | |
AzureIoTClient | 13:920e00014ee3 | 853 | if (readLine(http_instance, buf, sizeof(buf)) < 0) |
AzureIoTClient | 11:77df6d7e65ae | 854 | { |
AzureIoTClient | 11:77df6d7e65ae | 855 | /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 856 | /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 857 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 858 | } |
AzureIoTClient | 11:77df6d7e65ae | 859 | } |
AzureIoTClient | 11:77df6d7e65ae | 860 | } |
AzureIoTClient | 11:77df6d7e65ae | 861 | } |
AzureIoTClient | 11:77df6d7e65ae | 862 | |
AzureIoTClient | 11:77df6d7e65ae | 863 | return result; |
AzureIoTClient | 11:77df6d7e65ae | 864 | } |
AzureIoTClient | 11:77df6d7e65ae | 865 | |
AzureIoTClient | 13:920e00014ee3 | 866 | static HTTPAPI_RESULT ReadHTTPResponseBodyFromXIO(HTTP_HANDLE_DATA* http_instance, size_t bodyLength, bool chunked, BUFFER_HANDLE responseContent) |
AzureIoTClient | 11:77df6d7e65ae | 867 | { |
AzureIoTClient | 11:77df6d7e65ae | 868 | HTTPAPI_RESULT result; |
AzureIoTClient | 11:77df6d7e65ae | 869 | char buf[TEMP_BUFFER_SIZE]; |
AzureIoTClient | 11:77df6d7e65ae | 870 | const unsigned char* receivedContent; |
AzureIoTClient | 11:77df6d7e65ae | 871 | |
AzureIoTClient | 11:77df6d7e65ae | 872 | //Read HTTP response body |
AzureIoTClient | 11:77df6d7e65ae | 873 | if (!chunked) |
AzureIoTClient | 11:77df6d7e65ae | 874 | { |
AzureIoTClient | 11:77df6d7e65ae | 875 | if (bodyLength) |
AzureIoTClient | 11:77df6d7e65ae | 876 | { |
AzureIoTClient | 11:77df6d7e65ae | 877 | if (responseContent != NULL) |
AzureIoTClient | 11:77df6d7e65ae | 878 | { |
AzureIoTClient | 11:77df6d7e65ae | 879 | if (BUFFER_pre_build(responseContent, bodyLength) != 0) |
AzureIoTClient | 11:77df6d7e65ae | 880 | { |
AzureIoTClient | 11:77df6d7e65ae | 881 | /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 882 | result = HTTPAPI_ALLOC_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 883 | } |
AzureIoTClient | 11:77df6d7e65ae | 884 | else if (BUFFER_content(responseContent, &receivedContent) != 0) |
AzureIoTClient | 11:77df6d7e65ae | 885 | { |
AzureIoTClient | 11:77df6d7e65ae | 886 | (void)BUFFER_unbuild(responseContent); |
AzureIoTClient | 11:77df6d7e65ae | 887 | |
AzureIoTClient | 11:77df6d7e65ae | 888 | /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 889 | result = HTTPAPI_ALLOC_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 890 | } |
AzureIoTClient | 13:920e00014ee3 | 891 | else if (readChunk(http_instance, (char*)receivedContent, bodyLength) < 0) |
AzureIoTClient | 11:77df6d7e65ae | 892 | { |
AzureIoTClient | 11:77df6d7e65ae | 893 | /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 894 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 895 | } |
AzureIoTClient | 11:77df6d7e65ae | 896 | else |
AzureIoTClient | 11:77df6d7e65ae | 897 | { |
AzureIoTClient | 11:77df6d7e65ae | 898 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 899 | result = HTTPAPI_OK; |
AzureIoTClient | 11:77df6d7e65ae | 900 | } |
AzureIoTClient | 11:77df6d7e65ae | 901 | } |
AzureIoTClient | 13:920e00014ee3 | 902 | else |
AzureIoTClient | 13:920e00014ee3 | 903 | { |
AzureIoTClient | 13:920e00014ee3 | 904 | /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 905 | if (skipN(http_instance, bodyLength) < 0) |
AzureIoTClient | 13:920e00014ee3 | 906 | { |
AzureIoTClient | 13:920e00014ee3 | 907 | /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 908 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 13:920e00014ee3 | 909 | } |
AzureIoTClient | 13:920e00014ee3 | 910 | else |
AzureIoTClient | 13:920e00014ee3 | 911 | { |
AzureIoTClient | 13:920e00014ee3 | 912 | result = HTTPAPI_OK; |
AzureIoTClient | 13:920e00014ee3 | 913 | } |
AzureIoTClient | 13:920e00014ee3 | 914 | } |
AzureIoTClient | 11:77df6d7e65ae | 915 | } |
AzureIoTClient | 11:77df6d7e65ae | 916 | else |
AzureIoTClient | 11:77df6d7e65ae | 917 | { |
AzureIoTClient | 11:77df6d7e65ae | 918 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 919 | result = HTTPAPI_OK; |
AzureIoTClient | 11:77df6d7e65ae | 920 | } |
AzureIoTClient | 11:77df6d7e65ae | 921 | } |
AzureIoTClient | 11:77df6d7e65ae | 922 | else |
AzureIoTClient | 11:77df6d7e65ae | 923 | { |
AzureIoTClient | 11:77df6d7e65ae | 924 | size_t size = 0; |
AzureIoTClient | 11:77df6d7e65ae | 925 | /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 926 | result = HTTPAPI_OK; |
AzureIoTClient | 11:77df6d7e65ae | 927 | while (result == HTTPAPI_OK) |
AzureIoTClient | 11:77df6d7e65ae | 928 | { |
AzureIoTClient | 11:77df6d7e65ae | 929 | size_t chunkSize; |
AzureIoTClient | 13:920e00014ee3 | 930 | if (readLine(http_instance, buf, sizeof(buf)) < 0) // read [length in hex]/r/n |
AzureIoTClient | 11:77df6d7e65ae | 931 | { |
AzureIoTClient | 11:77df6d7e65ae | 932 | /*Codes_SRS_HTTPAPI_COMPACT_21_032: [ If the HTTPAPI_ExecuteRequest cannot read the message with the request result, it shall return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 933 | /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 934 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 935 | } |
AzureIoTClient | 11:77df6d7e65ae | 936 | else if (ParseStringToHexadecimal(buf, &chunkSize) != 1) // chunkSize is length of next line (/r/n is not counted) |
AzureIoTClient | 11:77df6d7e65ae | 937 | { |
AzureIoTClient | 11:77df6d7e65ae | 938 | //Cannot match string, error |
AzureIoTClient | 11:77df6d7e65ae | 939 | /*Codes_SRS_HTTPAPI_COMPACT_21_055: [ If the HTTPAPI_ExecuteRequest cannot parser the recived message, it shall return HTTPAPI_RECEIVE_RESPONSE_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 940 | result = HTTPAPI_RECEIVE_RESPONSE_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 941 | } |
AzureIoTClient | 11:77df6d7e65ae | 942 | else if (chunkSize == 0) |
AzureIoTClient | 11:77df6d7e65ae | 943 | { |
AzureIoTClient | 11:77df6d7e65ae | 944 | // 0 length means next line is just '\r\n' and end of chunks |
AzureIoTClient | 13:920e00014ee3 | 945 | if (readChunk(http_instance, (char*)buf, (size_t)2) < 0 |
AzureIoTClient | 11:77df6d7e65ae | 946 | || buf[0] != '\r' || buf[1] != '\n') // skip /r/n |
AzureIoTClient | 11:77df6d7e65ae | 947 | { |
AzureIoTClient | 11:77df6d7e65ae | 948 | (void)BUFFER_unbuild(responseContent); |
AzureIoTClient | 11:77df6d7e65ae | 949 | |
AzureIoTClient | 11:77df6d7e65ae | 950 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 951 | } |
AzureIoTClient | 11:77df6d7e65ae | 952 | break; |
AzureIoTClient | 11:77df6d7e65ae | 953 | } |
AzureIoTClient | 11:77df6d7e65ae | 954 | else |
AzureIoTClient | 11:77df6d7e65ae | 955 | { |
AzureIoTClient | 11:77df6d7e65ae | 956 | if (responseContent != NULL) |
AzureIoTClient | 11:77df6d7e65ae | 957 | { |
AzureIoTClient | 11:77df6d7e65ae | 958 | if (BUFFER_enlarge(responseContent, chunkSize) != 0) |
AzureIoTClient | 11:77df6d7e65ae | 959 | { |
AzureIoTClient | 11:77df6d7e65ae | 960 | (void)BUFFER_unbuild(responseContent); |
AzureIoTClient | 11:77df6d7e65ae | 961 | |
AzureIoTClient | 11:77df6d7e65ae | 962 | /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 963 | result = HTTPAPI_ALLOC_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 964 | } |
AzureIoTClient | 11:77df6d7e65ae | 965 | else if (BUFFER_content(responseContent, &receivedContent) != 0) |
AzureIoTClient | 11:77df6d7e65ae | 966 | { |
AzureIoTClient | 11:77df6d7e65ae | 967 | (void)BUFFER_unbuild(responseContent); |
AzureIoTClient | 11:77df6d7e65ae | 968 | |
AzureIoTClient | 11:77df6d7e65ae | 969 | /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 970 | result = HTTPAPI_ALLOC_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 971 | } |
AzureIoTClient | 13:920e00014ee3 | 972 | else if (readChunk(http_instance, (char*)receivedContent + size, chunkSize) < 0) |
AzureIoTClient | 11:77df6d7e65ae | 973 | { |
AzureIoTClient | 11:77df6d7e65ae | 974 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 975 | } |
AzureIoTClient | 11:77df6d7e65ae | 976 | } |
AzureIoTClient | 11:77df6d7e65ae | 977 | else |
AzureIoTClient | 11:77df6d7e65ae | 978 | { |
AzureIoTClient | 11:77df6d7e65ae | 979 | /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 980 | if (skipN(http_instance, chunkSize) < 0) |
AzureIoTClient | 11:77df6d7e65ae | 981 | { |
AzureIoTClient | 13:920e00014ee3 | 982 | /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ If the HTTPAPI_ExecuteRequest retries 20 times to receive the message without success, it shall fail and return HTTPAPI_READ_DATA_FAILED. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 983 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 984 | } |
AzureIoTClient | 11:77df6d7e65ae | 985 | } |
AzureIoTClient | 11:77df6d7e65ae | 986 | |
AzureIoTClient | 11:77df6d7e65ae | 987 | if (result == HTTPAPI_OK) |
AzureIoTClient | 11:77df6d7e65ae | 988 | { |
AzureIoTClient | 13:920e00014ee3 | 989 | if (readChunk(http_instance, (char*)buf, (size_t)2) < 0 |
AzureIoTClient | 11:77df6d7e65ae | 990 | || buf[0] != '\r' || buf[1] != '\n') // skip /r/n |
AzureIoTClient | 11:77df6d7e65ae | 991 | { |
AzureIoTClient | 11:77df6d7e65ae | 992 | result = HTTPAPI_READ_DATA_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 993 | } |
AzureIoTClient | 11:77df6d7e65ae | 994 | size += chunkSize; |
AzureIoTClient | 11:77df6d7e65ae | 995 | } |
AzureIoTClient | 11:77df6d7e65ae | 996 | } |
AzureIoTClient | 11:77df6d7e65ae | 997 | } |
AzureIoTClient | 11:77df6d7e65ae | 998 | |
AzureIoTClient | 11:77df6d7e65ae | 999 | } |
AzureIoTClient | 11:77df6d7e65ae | 1000 | return result; |
AzureIoTClient | 11:77df6d7e65ae | 1001 | } |
AzureIoTClient | 11:77df6d7e65ae | 1002 | |
AzureIoTClient | 11:77df6d7e65ae | 1003 | |
AzureIoTClient | 11:77df6d7e65ae | 1004 | /*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1005 | static bool validRequestType(HTTPAPI_REQUEST_TYPE requestType) |
AzureIoTClient | 11:77df6d7e65ae | 1006 | { |
AzureIoTClient | 11:77df6d7e65ae | 1007 | bool result; |
AzureIoTClient | 11:77df6d7e65ae | 1008 | |
AzureIoTClient | 11:77df6d7e65ae | 1009 | if ((requestType == HTTPAPI_REQUEST_GET) || |
AzureIoTClient | 11:77df6d7e65ae | 1010 | (requestType == HTTPAPI_REQUEST_POST) || |
AzureIoTClient | 11:77df6d7e65ae | 1011 | (requestType == HTTPAPI_REQUEST_PUT) || |
AzureIoTClient | 11:77df6d7e65ae | 1012 | (requestType == HTTPAPI_REQUEST_DELETE) || |
AzureIoTClient | 11:77df6d7e65ae | 1013 | (requestType == HTTPAPI_REQUEST_PATCH)) |
AzureIoTClient | 11:77df6d7e65ae | 1014 | { |
AzureIoTClient | 11:77df6d7e65ae | 1015 | result = true; |
AzureIoTClient | 11:77df6d7e65ae | 1016 | } |
AzureIoTClient | 11:77df6d7e65ae | 1017 | else |
AzureIoTClient | 11:77df6d7e65ae | 1018 | { |
AzureIoTClient | 11:77df6d7e65ae | 1019 | result = false; |
AzureIoTClient | 11:77df6d7e65ae | 1020 | } |
AzureIoTClient | 11:77df6d7e65ae | 1021 | |
AzureIoTClient | 11:77df6d7e65ae | 1022 | return result; |
AzureIoTClient | 11:77df6d7e65ae | 1023 | } |
AzureIoTClient | 11:77df6d7e65ae | 1024 | |
AzureIoTClient | 11:77df6d7e65ae | 1025 | /*Codes_SRS_HTTPAPI_COMPACT_21_021: [ The HTTPAPI_ExecuteRequest shall execute the http communtication with the provided host, sending a request and reciving the response. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1026 | /*Codes_SRS_HTTPAPI_COMPACT_21_050: [ If there is a content in the response, the HTTPAPI_ExecuteRequest shall copy it in the responseContent buffer. ]*/ |
Azure.IoT Build | 6:c55b013dfc2a | 1027 | //Note: This function assumes that "Host:" and "Content-Length:" headers are setup |
Azure.IoT Build | 6:c55b013dfc2a | 1028 | // by the caller of HTTPAPI_ExecuteRequest() (which is true for httptransport.c). |
Azure.IoT Build | 6:c55b013dfc2a | 1029 | HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, |
Azure.IoT Build | 6:c55b013dfc2a | 1030 | HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content, |
Azure.IoT Build | 6:c55b013dfc2a | 1031 | size_t contentLength, unsigned int* statusCode, |
Azure.IoT Build | 6:c55b013dfc2a | 1032 | HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent) |
Azure.IoT Build | 6:c55b013dfc2a | 1033 | { |
AzureIoTClient | 11:77df6d7e65ae | 1034 | HTTPAPI_RESULT result = HTTPAPI_ERROR; |
Azure.IoT Build | 6:c55b013dfc2a | 1035 | size_t headersCount; |
Azure.IoT Build | 6:c55b013dfc2a | 1036 | size_t bodyLength = 0; |
Azure.IoT Build | 6:c55b013dfc2a | 1037 | bool chunked = false; |
AzureIoTClient | 13:920e00014ee3 | 1038 | HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle; |
Azure.IoT Build | 6:c55b013dfc2a | 1039 | |
AzureIoTClient | 11:77df6d7e65ae | 1040 | /*Codes_SRS_HTTPAPI_COMPACT_21_034: [ If there is no previous connection, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1041 | /*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1042 | /*Codes_SRS_HTTPAPI_COMPACT_21_039: [ If the relativePath is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1043 | /*Codes_SRS_HTTPAPI_COMPACT_21_041: [ If the httpHeadersHandle is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1044 | /*Codes_SRS_HTTPAPI_COMPACT_21_053: [ The HTTPAPI_ExecuteRequest shall produce a set of http header to send to the host. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1045 | /*Codes_SRS_HTTPAPI_COMPACT_21_040: [ The request shall contain the http header provided in httpHeadersHandle parameter. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1046 | /*Codes_SRS_HTTPAPI_COMPACT_21_054: [ If Http header maker cannot provide the number of headers, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 1047 | if (http_instance == NULL || |
Azure.IoT Build | 6:c55b013dfc2a | 1048 | relativePath == NULL || |
Azure.IoT Build | 6:c55b013dfc2a | 1049 | httpHeadersHandle == NULL || |
AzureIoTClient | 11:77df6d7e65ae | 1050 | !validRequestType(requestType) || |
Azure.IoT Build | 6:c55b013dfc2a | 1051 | HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK) |
Azure.IoT Build | 6:c55b013dfc2a | 1052 | { |
Azure.IoT Build | 6:c55b013dfc2a | 1053 | result = HTTPAPI_INVALID_ARG; |
Azure.IoT Build | 6:c55b013dfc2a | 1054 | LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); |
Azure.IoT Build | 6:c55b013dfc2a | 1055 | } |
AzureIoTClient | 11:77df6d7e65ae | 1056 | /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 1057 | else if ((result = OpenXIOConnection(http_instance)) != HTTPAPI_OK) |
AzureIoTClient | 11:77df6d7e65ae | 1058 | { |
AzureIoTClient | 11:77df6d7e65ae | 1059 | LogError("Open HTTP connection failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); |
AzureIoTClient | 11:77df6d7e65ae | 1060 | } |
AzureIoTClient | 11:77df6d7e65ae | 1061 | /*Codes_SRS_HTTPAPI_COMPACT_21_026: [ If the open process succeed, the HTTPAPI_ExecuteRequest shall send the request message to the host. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 1062 | else if ((result = SendHeadsToXIO(http_instance, requestType, relativePath, httpHeadersHandle, headersCount)) != HTTPAPI_OK) |
AzureIoTClient | 11:77df6d7e65ae | 1063 | { |
AzureIoTClient | 11:77df6d7e65ae | 1064 | LogError("Send heads to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); |
AzureIoTClient | 11:77df6d7e65ae | 1065 | } |
AzureIoTClient | 11:77df6d7e65ae | 1066 | /*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 1067 | else if ((result = SendContentToXIO(http_instance, content, contentLength)) != HTTPAPI_OK) |
AzureIoTClient | 11:77df6d7e65ae | 1068 | { |
AzureIoTClient | 11:77df6d7e65ae | 1069 | LogError("Send content to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); |
AzureIoTClient | 11:77df6d7e65ae | 1070 | } |
AzureIoTClient | 11:77df6d7e65ae | 1071 | /*Codes_SRS_HTTPAPI_COMPACT_21_030: [ At the end of the transmission, the HTTPAPI_ExecuteRequest shall receive the response from the host. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1072 | /*Codes_SRS_HTTPAPI_COMPACT_21_073: [ The message recived by the HTTPAPI_ExecuteRequest shall starts with a valid header. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 1073 | else if ((result = RecieveHeaderFromXIO(http_instance, statusCode)) != HTTPAPI_OK) |
AzureIoTClient | 11:77df6d7e65ae | 1074 | { |
AzureIoTClient | 11:77df6d7e65ae | 1075 | LogError("Receive header from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); |
AzureIoTClient | 11:77df6d7e65ae | 1076 | } |
AzureIoTClient | 11:77df6d7e65ae | 1077 | /*Codes_SRS_HTTPAPI_COMPACT_21_074: [ After the header, the message recieved by the HTTPAPI_ExecuteRequest can contain addition information about the content. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 1078 | else if ((result = RecieveContentInfoFromXIO(http_instance, responseHeadersHandle, &bodyLength, &chunked)) != HTTPAPI_OK) |
AzureIoTClient | 11:77df6d7e65ae | 1079 | { |
AzureIoTClient | 11:77df6d7e65ae | 1080 | LogError("Receive content information from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); |
AzureIoTClient | 11:77df6d7e65ae | 1081 | } |
AzureIoTClient | 11:77df6d7e65ae | 1082 | /*Codes_SRS_HTTPAPI_COMPACT_21_075: [ The message recieved by the HTTPAPI_ExecuteRequest can contain a body with the message content. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 1083 | else if ((result = ReadHTTPResponseBodyFromXIO(http_instance, bodyLength, chunked, responseContent)) != HTTPAPI_OK) |
AzureIoTClient | 11:77df6d7e65ae | 1084 | { |
AzureIoTClient | 11:77df6d7e65ae | 1085 | LogError("Read HTTP response body from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result)); |
AzureIoTClient | 11:77df6d7e65ae | 1086 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1087 | |
AzureIoTClient | 13:920e00014ee3 | 1088 | conn_receive_discard_buffer(http_instance); |
AzureIoTClient | 13:920e00014ee3 | 1089 | |
AzureIoTClient | 13:920e00014ee3 | 1090 | /*Codes_SRS_HTTPAPI_COMPACT_21_031: [ After receive the response, the HTTPAPI_ExecuteRequest shall close the transport connection with the host. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 1091 | if ((http_instance != NULL) && |
AzureIoTClient | 13:920e00014ee3 | 1092 | (http_instance->is_connected != 0)) |
Azure.IoT Build | 6:c55b013dfc2a | 1093 | { |
AzureIoTClient | 13:920e00014ee3 | 1094 | xio_close(http_instance->xio_handle, NULL, NULL); |
AzureIoTClient | 13:920e00014ee3 | 1095 | http_instance->is_connected = 0; |
Azure.IoT Build | 6:c55b013dfc2a | 1096 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1097 | |
AzureIoTClient | 11:77df6d7e65ae | 1098 | return result; |
AzureIoTClient | 11:77df6d7e65ae | 1099 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1100 | |
AzureIoTClient | 11:77df6d7e65ae | 1101 | /*Codes_SRS_HTTPAPI_COMPACT_21_056: [ The HTTPAPI_SetOption shall change the HTTP options. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1102 | /*Codes_SRS_HTTPAPI_COMPACT_21_057: [ The HTTPAPI_SetOption shall recieve a handle that identiry the HTTP connection. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1103 | /*Codes_SRS_HTTPAPI_COMPACT_21_058: [ The HTTPAPI_SetOption shall recieve the option as a pair optionName/value. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1104 | HTTPAPI_RESULT HTTPAPI_SetOption(HTTP_HANDLE handle, const char* optionName, const void* value) |
AzureIoTClient | 11:77df6d7e65ae | 1105 | { |
AzureIoTClient | 11:77df6d7e65ae | 1106 | HTTPAPI_RESULT result; |
AzureIoTClient | 13:920e00014ee3 | 1107 | HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle; |
Azure.IoT Build | 6:c55b013dfc2a | 1108 | |
AzureIoTClient | 11:77df6d7e65ae | 1109 | if ( |
AzureIoTClient | 13:920e00014ee3 | 1110 | (http_instance == NULL) || |
AzureIoTClient | 11:77df6d7e65ae | 1111 | (optionName == NULL) || |
AzureIoTClient | 11:77df6d7e65ae | 1112 | (value == NULL) |
AzureIoTClient | 11:77df6d7e65ae | 1113 | ) |
Azure.IoT Build | 6:c55b013dfc2a | 1114 | { |
AzureIoTClient | 11:77df6d7e65ae | 1115 | /*Codes_SRS_HTTPAPI_COMPACT_21_059: [ If the handle is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1116 | /*Codes_SRS_HTTPAPI_COMPACT_21_060: [ If the optionName is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1117 | /*Codes_SRS_HTTPAPI_COMPACT_21_061: [ If the value is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1118 | result = HTTPAPI_INVALID_ARG; |
Azure.IoT Build | 6:c55b013dfc2a | 1119 | } |
AzureIoTClient | 11:77df6d7e65ae | 1120 | else if (strcmp("TrustedCerts", optionName) == 0) |
Azure.IoT Build | 6:c55b013dfc2a | 1121 | { |
AzureIoTClient | 13:920e00014ee3 | 1122 | if (http_instance->certificate) |
Azure.IoT Build | 6:c55b013dfc2a | 1123 | { |
AzureIoTClient | 13:920e00014ee3 | 1124 | free(http_instance->certificate); |
Azure.IoT Build | 6:c55b013dfc2a | 1125 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1126 | |
AzureIoTClient | 11:77df6d7e65ae | 1127 | int len = (int)strlen((char*)value); |
AzureIoTClient | 13:920e00014ee3 | 1128 | http_instance->certificate = (char*)malloc((len + 1) * sizeof(char)); |
AzureIoTClient | 13:920e00014ee3 | 1129 | if (http_instance->certificate == NULL) |
Azure.IoT Build | 6:c55b013dfc2a | 1130 | { |
AzureIoTClient | 11:77df6d7e65ae | 1131 | /*SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1132 | result = HTTPAPI_ALLOC_FAILED; |
AzureIoTClient | 11:77df6d7e65ae | 1133 | LogInfo("unable to allocate memory for the certificate in HTTPAPI_SetOption"); |
Azure.IoT Build | 6:c55b013dfc2a | 1134 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1135 | else |
Azure.IoT Build | 6:c55b013dfc2a | 1136 | { |
AzureIoTClient | 11:77df6d7e65ae | 1137 | /*SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/ |
AzureIoTClient | 13:920e00014ee3 | 1138 | (void)strcpy(http_instance->certificate, (const char*)value); |
Azure.IoT Build | 6:c55b013dfc2a | 1139 | result = HTTPAPI_OK; |
Azure.IoT Build | 6:c55b013dfc2a | 1140 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1141 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1142 | else |
Azure.IoT Build | 6:c55b013dfc2a | 1143 | { |
AzureIoTClient | 11:77df6d7e65ae | 1144 | /*Codes_SRS_HTTPAPI_COMPACT_21_063: [ If the HTTP do not support the optionName, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/ |
Azure.IoT Build | 6:c55b013dfc2a | 1145 | result = HTTPAPI_INVALID_ARG; |
AzureIoTClient | 11:77df6d7e65ae | 1146 | LogInfo("unknown option %s", optionName); |
Azure.IoT Build | 6:c55b013dfc2a | 1147 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1148 | return result; |
Azure.IoT Build | 6:c55b013dfc2a | 1149 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1150 | |
AzureIoTClient | 11:77df6d7e65ae | 1151 | /*Codes_SRS_HTTPAPI_COMPACT_21_065: [ The HTTPAPI_CloneOption shall provide the means to clone the HTTP option. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1152 | /*Codes_SRS_HTTPAPI_COMPACT_21_066: [ The HTTPAPI_CloneOption shall return a clone of the value identified by the optionName. ]*/ |
Azure.IoT Build | 6:c55b013dfc2a | 1153 | HTTPAPI_RESULT HTTPAPI_CloneOption(const char* optionName, const void* value, const void** savedValue) |
Azure.IoT Build | 6:c55b013dfc2a | 1154 | { |
Azure.IoT Build | 6:c55b013dfc2a | 1155 | HTTPAPI_RESULT result; |
AzureIoTClient | 11:77df6d7e65ae | 1156 | size_t certLen; |
AzureIoTClient | 11:77df6d7e65ae | 1157 | char* tempCert; |
AzureIoTClient | 11:77df6d7e65ae | 1158 | |
AzureIoTClient | 11:77df6d7e65ae | 1159 | if ( |
Azure.IoT Build | 6:c55b013dfc2a | 1160 | (optionName == NULL) || |
Azure.IoT Build | 6:c55b013dfc2a | 1161 | (value == NULL) || |
Azure.IoT Build | 6:c55b013dfc2a | 1162 | (savedValue == NULL) |
Azure.IoT Build | 6:c55b013dfc2a | 1163 | ) |
Azure.IoT Build | 6:c55b013dfc2a | 1164 | { |
AzureIoTClient | 11:77df6d7e65ae | 1165 | /*Codes_SRS_HTTPAPI_COMPACT_21_067: [ If the optionName is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1166 | /*Codes_SRS_HTTPAPI_COMPACT_21_068: [ If the value is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1167 | /*Codes_SRS_HTTPAPI_COMPACT_21_069: [ If the savedValue is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1168 | result = HTTPAPI_INVALID_ARG; |
Azure.IoT Build | 6:c55b013dfc2a | 1169 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1170 | else if (strcmp("TrustedCerts", optionName) == 0) |
Azure.IoT Build | 6:c55b013dfc2a | 1171 | { |
AzureIoTClient | 11:77df6d7e65ae | 1172 | certLen = strlen((const char*)value); |
AzureIoTClient | 11:77df6d7e65ae | 1173 | tempCert = (char*)malloc((certLen + 1) * sizeof(char)); |
Azure.IoT Build | 6:c55b013dfc2a | 1174 | if (tempCert == NULL) |
Azure.IoT Build | 6:c55b013dfc2a | 1175 | { |
AzureIoTClient | 11:77df6d7e65ae | 1176 | /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1177 | result = HTTPAPI_ALLOC_FAILED; |
Azure.IoT Build | 6:c55b013dfc2a | 1178 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1179 | else |
Azure.IoT Build | 6:c55b013dfc2a | 1180 | { |
AzureIoTClient | 11:77df6d7e65ae | 1181 | /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1182 | (void)strcpy(tempCert, (const char*)value); |
Azure.IoT Build | 6:c55b013dfc2a | 1183 | *savedValue = tempCert; |
Azure.IoT Build | 6:c55b013dfc2a | 1184 | result = HTTPAPI_OK; |
Azure.IoT Build | 6:c55b013dfc2a | 1185 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1186 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1187 | else |
Azure.IoT Build | 6:c55b013dfc2a | 1188 | { |
AzureIoTClient | 11:77df6d7e65ae | 1189 | /*Codes_SRS_HTTPAPI_COMPACT_21_071: [ If the HTTP do not support the optionName, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/ |
AzureIoTClient | 11:77df6d7e65ae | 1190 | result = HTTPAPI_INVALID_ARG; |
AzureIoTClient | 11:77df6d7e65ae | 1191 | LogInfo("unknown option %s", optionName); |
Azure.IoT Build | 6:c55b013dfc2a | 1192 | } |
Azure.IoT Build | 6:c55b013dfc2a | 1193 | return result; |
Azure.IoT Build | 6:c55b013dfc2a | 1194 | } |