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