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