Azure IoT common library

Dependents:   STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more

Committer:
AzureIoTClient
Date:
Thu Oct 04 09:17:16 2018 -0700
Revision:
49:6bb8b9a66642
Parent:
48:81866008bba4
1.2.10

Who changed what in which revision?

UserRevisionLine numberNew 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 49:6bb8b9a66642 312 #ifndef DO_NOT_COPY_TRUSTED_CERTS_STRING
AzureIoTClient 15:956c6d205aa7 313 /*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 314 if (http_instance->certificate)
Azure.IoT Build 6:c55b013dfc2a 315 {
AzureIoTClient 13:920e00014ee3 316 free(http_instance->certificate);
Azure.IoT Build 6:c55b013dfc2a 317 }
AzureIoTClient 49:6bb8b9a66642 318 #endif
Azure.IoT Build 6:c55b013dfc2a 319
AzureIoTClient 15:956c6d205aa7 320 /*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 321 if (http_instance->x509ClientCertificate)
AzureIoTClient 15:956c6d205aa7 322 {
AzureIoTClient 15:956c6d205aa7 323 free(http_instance->x509ClientCertificate);
AzureIoTClient 15:956c6d205aa7 324 }
AzureIoTClient 15:956c6d205aa7 325
AzureIoTClient 15:956c6d205aa7 326 /*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 327 if (http_instance->x509ClientPrivateKey)
AzureIoTClient 15:956c6d205aa7 328 {
AzureIoTClient 15:956c6d205aa7 329 free(http_instance->x509ClientPrivateKey);
AzureIoTClient 15:956c6d205aa7 330 }
AzureIoTClient 13:920e00014ee3 331 free(http_instance);
Azure.IoT Build 6:c55b013dfc2a 332 }
Azure.IoT Build 6:c55b013dfc2a 333 }
Azure.IoT Build 6:c55b013dfc2a 334
Azure.IoT Build 6:c55b013dfc2a 335 static void on_io_open_complete(void* context, IO_OPEN_RESULT open_result)
Azure.IoT Build 6:c55b013dfc2a 336 {
AzureIoTClient 13:920e00014ee3 337 HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
AzureIoTClient 15:956c6d205aa7 338
AzureIoTClient 13:920e00014ee3 339 if (http_instance != NULL)
AzureIoTClient 15:956c6d205aa7 340 {
AzureIoTClient 15:956c6d205aa7 341 if (open_result == IO_OPEN_OK)
AzureIoTClient 15:956c6d205aa7 342 {
AzureIoTClient 15:956c6d205aa7 343 http_instance->is_connected = 1;
AzureIoTClient 15:956c6d205aa7 344 http_instance->is_io_error = 0;
AzureIoTClient 15:956c6d205aa7 345 }
AzureIoTClient 15:956c6d205aa7 346 else
AzureIoTClient 15:956c6d205aa7 347 {
AzureIoTClient 15:956c6d205aa7 348 http_instance->is_io_error = 1;
AzureIoTClient 15:956c6d205aa7 349 }
AzureIoTClient 15:956c6d205aa7 350 }
AzureIoTClient 15:956c6d205aa7 351 }
AzureIoTClient 15:956c6d205aa7 352
AzureIoTClient 15:956c6d205aa7 353 static void on_send_complete(void* context, IO_SEND_RESULT send_result)
AzureIoTClient 15:956c6d205aa7 354 {
AzureIoTClient 15:956c6d205aa7 355 HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
AzureIoTClient 15:956c6d205aa7 356
AzureIoTClient 15:956c6d205aa7 357 if (http_instance != NULL)
AzureIoTClient 15:956c6d205aa7 358 {
AzureIoTClient 15:956c6d205aa7 359 if (send_result == IO_SEND_OK)
AzureIoTClient 15:956c6d205aa7 360 {
AzureIoTClient 15:956c6d205aa7 361 http_instance->send_completed = 1;
AzureIoTClient 15:956c6d205aa7 362 http_instance->is_io_error = 0;
AzureIoTClient 15:956c6d205aa7 363 }
AzureIoTClient 15:956c6d205aa7 364 else
AzureIoTClient 15:956c6d205aa7 365 {
AzureIoTClient 15:956c6d205aa7 366 http_instance->is_io_error = 1;
AzureIoTClient 15:956c6d205aa7 367 }
AzureIoTClient 15:956c6d205aa7 368 }
Azure.IoT Build 6:c55b013dfc2a 369 }
Azure.IoT Build 6:c55b013dfc2a 370
AzureIoTClient 11:77df6d7e65ae 371 #define TOLOWER(c) (((c>='A') && (c<='Z'))?c-'A'+'a':c)
AzureIoTClient 11:77df6d7e65ae 372 static int InternStrnicmp(const char* s1, const char* s2, size_t n)
Azure.IoT Build 6:c55b013dfc2a 373 {
AzureIoTClient 11:77df6d7e65ae 374 int result;
Azure.IoT Build 6:c55b013dfc2a 375
AzureIoTClient 18:6d8a413a4d9a 376 if (s1 == NULL) result = -1;
AzureIoTClient 18:6d8a413a4d9a 377 else if (s2 == NULL) result = 1;
AzureIoTClient 15:956c6d205aa7 378 else
AzureIoTClient 15:956c6d205aa7 379 {
AzureIoTClient 15:956c6d205aa7 380 result = 0;
AzureIoTClient 18:6d8a413a4d9a 381
AzureIoTClient 18:6d8a413a4d9a 382 while(n-- && result == 0)
AzureIoTClient 15:956c6d205aa7 383 {
AzureIoTClient 18:6d8a413a4d9a 384 if (*s1 == 0) result = -1;
AzureIoTClient 18:6d8a413a4d9a 385 else if (*s2 == 0) result = 1;
AzureIoTClient 18:6d8a413a4d9a 386 else
AzureIoTClient 18:6d8a413a4d9a 387 {
Azure.IoT Build 6:c55b013dfc2a 388
AzureIoTClient 18:6d8a413a4d9a 389 result = TOLOWER(*s1) - TOLOWER(*s2);
AzureIoTClient 18:6d8a413a4d9a 390 ++s1;
AzureIoTClient 18:6d8a413a4d9a 391 ++s2;
AzureIoTClient 18:6d8a413a4d9a 392 }
Azure.IoT Build 6:c55b013dfc2a 393 }
AzureIoTClient 15:956c6d205aa7 394 }
Azure.IoT Build 6:c55b013dfc2a 395
Azure.IoT Build 6:c55b013dfc2a 396 return result;
Azure.IoT Build 6:c55b013dfc2a 397 }
Azure.IoT Build 6:c55b013dfc2a 398
Azure.IoT Build 6:c55b013dfc2a 399 static void on_bytes_received(void* context, const unsigned char* buffer, size_t size)
Azure.IoT Build 6:c55b013dfc2a 400 {
AzureIoTClient 11:77df6d7e65ae 401 unsigned char* new_received_bytes;
AzureIoTClient 13:920e00014ee3 402 HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
AzureIoTClient 11:77df6d7e65ae 403
AzureIoTClient 13:920e00014ee3 404 if (http_instance != NULL)
AzureIoTClient 13:920e00014ee3 405 {
Azure.IoT Build 6:c55b013dfc2a 406
AzureIoTClient 11:77df6d7e65ae 407 if (buffer == NULL)
AzureIoTClient 11:77df6d7e65ae 408 {
AzureIoTClient 13:920e00014ee3 409 http_instance->is_io_error = 1;
AzureIoTClient 13:920e00014ee3 410 LogError("NULL pointer error");
AzureIoTClient 11:77df6d7e65ae 411 }
AzureIoTClient 11:77df6d7e65ae 412 else
AzureIoTClient 11:77df6d7e65ae 413 {
AzureIoTClient 11:77df6d7e65ae 414 /* Here we got some bytes so we'll buffer them so the receive functions can consumer it */
AzureIoTClient 13:920e00014ee3 415 new_received_bytes = (unsigned char*)realloc(http_instance->received_bytes, http_instance->received_bytes_count + size);
AzureIoTClient 11:77df6d7e65ae 416 if (new_received_bytes == NULL)
AzureIoTClient 11:77df6d7e65ae 417 {
AzureIoTClient 13:920e00014ee3 418 http_instance->is_io_error = 1;
AzureIoTClient 13:920e00014ee3 419 LogError("Error allocating memory for received data");
AzureIoTClient 11:77df6d7e65ae 420 }
AzureIoTClient 11:77df6d7e65ae 421 else
AzureIoTClient 11:77df6d7e65ae 422 {
AzureIoTClient 13:920e00014ee3 423 http_instance->received_bytes = new_received_bytes;
AzureIoTClient 13:920e00014ee3 424 if (memcpy(http_instance->received_bytes + http_instance->received_bytes_count, buffer, size) == NULL)
AzureIoTClient 11:77df6d7e65ae 425 {
AzureIoTClient 13:920e00014ee3 426 http_instance->is_io_error = 1;
AzureIoTClient 13:920e00014ee3 427 LogError("Error copping received data to the HTTP bufffer");
AzureIoTClient 11:77df6d7e65ae 428 }
AzureIoTClient 11:77df6d7e65ae 429 else
AzureIoTClient 11:77df6d7e65ae 430 {
AzureIoTClient 13:920e00014ee3 431 http_instance->received_bytes_count += size;
AzureIoTClient 11:77df6d7e65ae 432 }
AzureIoTClient 11:77df6d7e65ae 433 }
AzureIoTClient 11:77df6d7e65ae 434 }
AzureIoTClient 15:956c6d205aa7 435 }
Azure.IoT Build 6:c55b013dfc2a 436 }
Azure.IoT Build 6:c55b013dfc2a 437
Azure.IoT Build 6:c55b013dfc2a 438 static void on_io_error(void* context)
Azure.IoT Build 6:c55b013dfc2a 439 {
AzureIoTClient 13:920e00014ee3 440 HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
AzureIoTClient 13:920e00014ee3 441 if (http_instance != NULL)
AzureIoTClient 13:920e00014ee3 442 {
AzureIoTClient 13:920e00014ee3 443 http_instance->is_io_error = 1;
AzureIoTClient 13:920e00014ee3 444 LogError("Error signalled by underlying IO");
AzureIoTClient 13:920e00014ee3 445 }
Azure.IoT Build 6:c55b013dfc2a 446 }
Azure.IoT Build 6:c55b013dfc2a 447
Azure.IoT Build 6:c55b013dfc2a 448 static int conn_receive(HTTP_HANDLE_DATA* http_instance, char* buffer, int count)
Azure.IoT Build 6:c55b013dfc2a 449 {
AzureIoTClient 11:77df6d7e65ae 450 int result;
Azure.IoT Build 6:c55b013dfc2a 451
AzureIoTClient 15:956c6d205aa7 452 if ((http_instance == NULL) || (buffer == NULL) || (count < 0))
AzureIoTClient 15:956c6d205aa7 453 {
AzureIoTClient 11:77df6d7e65ae 454 LogError("conn_receive: %s", ((http_instance == NULL) ? "Invalid HTTP instance" : "Invalid HTTP buffer"));
Azure.IoT Build 6:c55b013dfc2a 455 result = -1;
AzureIoTClient 15:956c6d205aa7 456 }
AzureIoTClient 15:956c6d205aa7 457 else
AzureIoTClient 15:956c6d205aa7 458 {
AzureIoTClient 15:956c6d205aa7 459 result = 0;
AzureIoTClient 15:956c6d205aa7 460 while (result < count)
AzureIoTClient 15:956c6d205aa7 461 {
AzureIoTClient 15:956c6d205aa7 462 xio_dowork(http_instance->xio_handle);
Azure.IoT Build 6:c55b013dfc2a 463
AzureIoTClient 15:956c6d205aa7 464 /* if any error was detected while receiving then simply break and report it */
AzureIoTClient 15:956c6d205aa7 465 if (http_instance->is_io_error != 0)
AzureIoTClient 15:956c6d205aa7 466 {
AzureIoTClient 13:920e00014ee3 467 LogError("xio reported error on dowork");
Azure.IoT Build 6:c55b013dfc2a 468 result = -1;
AzureIoTClient 15:956c6d205aa7 469 break;
AzureIoTClient 15:956c6d205aa7 470 }
Azure.IoT Build 6:c55b013dfc2a 471
AzureIoTClient 15:956c6d205aa7 472 if (http_instance->received_bytes_count >= (size_t)count)
AzureIoTClient 15:956c6d205aa7 473 {
AzureIoTClient 15:956c6d205aa7 474 /* Consuming bytes from the receive buffer */
AzureIoTClient 15:956c6d205aa7 475 (void)memcpy(buffer, http_instance->received_bytes, count);
AzureIoTClient 15:956c6d205aa7 476 (void)memmove(http_instance->received_bytes, http_instance->received_bytes + count, http_instance->received_bytes_count - count);
AzureIoTClient 15:956c6d205aa7 477 http_instance->received_bytes_count -= count;
Azure.IoT Build 6:c55b013dfc2a 478
AzureIoTClient 15:956c6d205aa7 479 /* we're not reallocating at each consumption so that we don't trash due to byte by byte consumption */
AzureIoTClient 15:956c6d205aa7 480 if (http_instance->received_bytes_count == 0)
AzureIoTClient 15:956c6d205aa7 481 {
AzureIoTClient 15:956c6d205aa7 482 free(http_instance->received_bytes);
AzureIoTClient 15:956c6d205aa7 483 http_instance->received_bytes = NULL;
AzureIoTClient 15:956c6d205aa7 484 }
Azure.IoT Build 6:c55b013dfc2a 485
AzureIoTClient 15:956c6d205aa7 486 result = count;
AzureIoTClient 15:956c6d205aa7 487 break;
AzureIoTClient 15:956c6d205aa7 488 }
Azure.IoT Build 6:c55b013dfc2a 489
AzureIoTClient 15:956c6d205aa7 490 /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
AzureIoTClient 15:956c6d205aa7 491 ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
AzureIoTClient 15:956c6d205aa7 492 }
AzureIoTClient 15:956c6d205aa7 493 }
Azure.IoT Build 6:c55b013dfc2a 494
Azure.IoT Build 6:c55b013dfc2a 495 return result;
Azure.IoT Build 6:c55b013dfc2a 496 }
Azure.IoT Build 6:c55b013dfc2a 497
AzureIoTClient 11:77df6d7e65ae 498 static void conn_receive_discard_buffer(HTTP_HANDLE_DATA* http_instance)
AzureIoTClient 11:77df6d7e65ae 499 {
AzureIoTClient 13:920e00014ee3 500 if (http_instance != NULL)
AzureIoTClient 11:77df6d7e65ae 501 {
AzureIoTClient 13:920e00014ee3 502 if (http_instance->received_bytes != NULL)
AzureIoTClient 13:920e00014ee3 503 {
AzureIoTClient 13:920e00014ee3 504 free(http_instance->received_bytes);
AzureIoTClient 13:920e00014ee3 505 http_instance->received_bytes = NULL;
AzureIoTClient 13:920e00014ee3 506 }
AzureIoTClient 13:920e00014ee3 507 http_instance->received_bytes_count = 0;
AzureIoTClient 11:77df6d7e65ae 508 }
AzureIoTClient 11:77df6d7e65ae 509 }
AzureIoTClient 11:77df6d7e65ae 510
AzureIoTClient 13:920e00014ee3 511 static int readLine(HTTP_HANDLE_DATA* http_instance, char* buf, const size_t maxBufSize)
Azure.IoT Build 6:c55b013dfc2a 512 {
AzureIoTClient 13:920e00014ee3 513 int resultLineSize;
Azure.IoT Build 6:c55b013dfc2a 514
AzureIoTClient 18:6d8a413a4d9a 515 if ((http_instance == NULL) || (buf == NULL) || (maxBufSize == 0))
AzureIoTClient 13:920e00014ee3 516 {
AzureIoTClient 13:920e00014ee3 517 LogError("%s", ((http_instance == NULL) ? "Invalid HTTP instance" : "Invalid HTTP buffer"));
AzureIoTClient 13:920e00014ee3 518 resultLineSize = -1;
Azure.IoT Build 6:c55b013dfc2a 519 }
Azure.IoT Build 6:c55b013dfc2a 520 else
Azure.IoT Build 6:c55b013dfc2a 521 {
AzureIoTClient 13:920e00014ee3 522 char* destByte = buf;
AzureIoTClient 15:956c6d205aa7 523 /*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 524 int countRetry = MAX_RECEIVE_RETRY;
AzureIoTClient 13:920e00014ee3 525 bool endOfSearch = false;
AzureIoTClient 13:920e00014ee3 526 resultLineSize = -1;
AzureIoTClient 13:920e00014ee3 527 while (!endOfSearch)
Azure.IoT Build 6:c55b013dfc2a 528 {
AzureIoTClient 13:920e00014ee3 529 xio_dowork(http_instance->xio_handle);
AzureIoTClient 13:920e00014ee3 530
AzureIoTClient 13:920e00014ee3 531 /* if any error was detected while receiving then simply break and report it */
AzureIoTClient 13:920e00014ee3 532 if (http_instance->is_io_error != 0)
AzureIoTClient 13:920e00014ee3 533 {
AzureIoTClient 13:920e00014ee3 534 LogError("xio reported error on dowork");
AzureIoTClient 13:920e00014ee3 535 endOfSearch = true;
AzureIoTClient 13:920e00014ee3 536 }
AzureIoTClient 13:920e00014ee3 537 else
Azure.IoT Build 6:c55b013dfc2a 538 {
AzureIoTClient 13:920e00014ee3 539 unsigned char* receivedByte = http_instance->received_bytes;
AzureIoTClient 13:920e00014ee3 540 while (receivedByte < (http_instance->received_bytes + http_instance->received_bytes_count))
Azure.IoT Build 6:c55b013dfc2a 541 {
AzureIoTClient 13:920e00014ee3 542 if ((*receivedByte) != '\r')
AzureIoTClient 13:920e00014ee3 543 {
AzureIoTClient 13:920e00014ee3 544 (*destByte) = (*receivedByte);
AzureIoTClient 13:920e00014ee3 545 destByte++;
AzureIoTClient 13:920e00014ee3 546 receivedByte++;
Azure.IoT Build 6:c55b013dfc2a 547
AzureIoTClient 13:920e00014ee3 548 if (destByte >= (buf + maxBufSize - 1))
AzureIoTClient 13:920e00014ee3 549 {
AzureIoTClient 13:920e00014ee3 550 LogError("Received message is bigger than the http buffer");
AzureIoTClient 13:920e00014ee3 551 receivedByte = http_instance->received_bytes + http_instance->received_bytes_count;
AzureIoTClient 13:920e00014ee3 552 endOfSearch = true;
AzureIoTClient 13:920e00014ee3 553 break;
AzureIoTClient 13:920e00014ee3 554 }
AzureIoTClient 13:920e00014ee3 555 }
AzureIoTClient 13:920e00014ee3 556 else
AzureIoTClient 13:920e00014ee3 557 {
AzureIoTClient 13:920e00014ee3 558 receivedByte++;
AzureIoTClient 13:920e00014ee3 559 if ((receivedByte < (http_instance->received_bytes + http_instance->received_bytes_count)) && ((*receivedByte) == '\n'))
AzureIoTClient 13:920e00014ee3 560 {
AzureIoTClient 13:920e00014ee3 561 receivedByte++;
AzureIoTClient 13:920e00014ee3 562 }
AzureIoTClient 13:920e00014ee3 563 (*destByte) = '\0';
AzureIoTClient 13:920e00014ee3 564 resultLineSize = (int)(destByte - buf);
AzureIoTClient 13:920e00014ee3 565 endOfSearch = true;
AzureIoTClient 13:920e00014ee3 566 break;
AzureIoTClient 13:920e00014ee3 567 }
Azure.IoT Build 6:c55b013dfc2a 568 }
Azure.IoT Build 6:c55b013dfc2a 569
AzureIoTClient 13:920e00014ee3 570 http_instance->received_bytes_count -= (receivedByte - http_instance->received_bytes);
AzureIoTClient 13:920e00014ee3 571 if (http_instance->received_bytes_count != 0)
AzureIoTClient 13:920e00014ee3 572 {
AzureIoTClient 13:920e00014ee3 573 (void)memmove(http_instance->received_bytes, receivedByte, http_instance->received_bytes_count);
AzureIoTClient 13:920e00014ee3 574 }
AzureIoTClient 13:920e00014ee3 575 else
AzureIoTClient 13:920e00014ee3 576 {
AzureIoTClient 13:920e00014ee3 577 conn_receive_discard_buffer(http_instance);
AzureIoTClient 13:920e00014ee3 578 }
Azure.IoT Build 6:c55b013dfc2a 579 }
Azure.IoT Build 6:c55b013dfc2a 580
AzureIoTClient 13:920e00014ee3 581 if (!endOfSearch)
Azure.IoT Build 6:c55b013dfc2a 582 {
AzureIoTClient 13:920e00014ee3 583 if ((countRetry--) > 0)
AzureIoTClient 13:920e00014ee3 584 {
AzureIoTClient 15:956c6d205aa7 585 /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
AzureIoTClient 15:956c6d205aa7 586 ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
AzureIoTClient 13:920e00014ee3 587 }
AzureIoTClient 13:920e00014ee3 588 else
AzureIoTClient 13:920e00014ee3 589 {
AzureIoTClient 15:956c6d205aa7 590 /*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 591 LogError("Receive timeout. The HTTP request is incomplete");
AzureIoTClient 13:920e00014ee3 592 endOfSearch = true;
AzureIoTClient 13:920e00014ee3 593 }
Azure.IoT Build 6:c55b013dfc2a 594 }
Azure.IoT Build 6:c55b013dfc2a 595 }
Azure.IoT Build 6:c55b013dfc2a 596 }
Azure.IoT Build 6:c55b013dfc2a 597
AzureIoTClient 13:920e00014ee3 598 return resultLineSize;
Azure.IoT Build 6:c55b013dfc2a 599 }
Azure.IoT Build 6:c55b013dfc2a 600
Azure.IoT Build 6:c55b013dfc2a 601 static int readChunk(HTTP_HANDLE_DATA* http_instance, char* buf, size_t size)
Azure.IoT Build 6:c55b013dfc2a 602 {
AzureIoTClient 11:77df6d7e65ae 603 int cur, offset;
Azure.IoT Build 6:c55b013dfc2a 604
Azure.IoT Build 6:c55b013dfc2a 605 // read content with specified length, even if it is received
Azure.IoT Build 6:c55b013dfc2a 606 // only in chunks due to fragmentation in the networking layer.
Azure.IoT Build 6:c55b013dfc2a 607 // returns -1 in case of error.
Azure.IoT Build 6:c55b013dfc2a 608 offset = 0;
AzureIoTClient 11:77df6d7e65ae 609 while (size > (size_t)0)
Azure.IoT Build 6:c55b013dfc2a 610 {
AzureIoTClient 11:77df6d7e65ae 611 cur = conn_receive(http_instance, buf + offset, (int)size);
Azure.IoT Build 6:c55b013dfc2a 612
Azure.IoT Build 6:c55b013dfc2a 613 // end of stream reached
AzureIoTClient 15:956c6d205aa7 614 if (cur == 0)
AzureIoTClient 15:956c6d205aa7 615 {
AzureIoTClient 15:956c6d205aa7 616 break;
AzureIoTClient 15:956c6d205aa7 617 }
Azure.IoT Build 6:c55b013dfc2a 618
Azure.IoT Build 6:c55b013dfc2a 619 // read cur bytes (might be less than requested)
AzureIoTClient 11:77df6d7e65ae 620 size -= (size_t)cur;
Azure.IoT Build 6:c55b013dfc2a 621 offset += cur;
Azure.IoT Build 6:c55b013dfc2a 622 }
Azure.IoT Build 6:c55b013dfc2a 623
Azure.IoT Build 6:c55b013dfc2a 624 return offset;
Azure.IoT Build 6:c55b013dfc2a 625 }
Azure.IoT Build 6:c55b013dfc2a 626
AzureIoTClient 13:920e00014ee3 627 static int skipN(HTTP_HANDLE_DATA* http_instance, size_t n)
Azure.IoT Build 6:c55b013dfc2a 628 {
Azure.IoT Build 6:c55b013dfc2a 629 // read and abandon response content with specified length
Azure.IoT Build 6:c55b013dfc2a 630 // returns -1 in case of error.
AzureIoTClient 13:920e00014ee3 631
AzureIoTClient 13:920e00014ee3 632 int result;
AzureIoTClient 13:920e00014ee3 633
AzureIoTClient 13:920e00014ee3 634 if (http_instance == NULL)
AzureIoTClient 13:920e00014ee3 635 {
AzureIoTClient 13:920e00014ee3 636 LogError("Invalid HTTP instance");
AzureIoTClient 13:920e00014ee3 637 result = -1;
AzureIoTClient 13:920e00014ee3 638 }
AzureIoTClient 13:920e00014ee3 639 else
Azure.IoT Build 6:c55b013dfc2a 640 {
AzureIoTClient 15:956c6d205aa7 641 /*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 642 int countRetry = MAX_RECEIVE_RETRY;
AzureIoTClient 13:920e00014ee3 643 result = (int)n;
AzureIoTClient 13:920e00014ee3 644 while (n > 0)
AzureIoTClient 13:920e00014ee3 645 {
AzureIoTClient 13:920e00014ee3 646 xio_dowork(http_instance->xio_handle);
Azure.IoT Build 6:c55b013dfc2a 647
AzureIoTClient 13:920e00014ee3 648 /* if any error was detected while receiving then simply break and report it */
AzureIoTClient 13:920e00014ee3 649 if (http_instance->is_io_error != 0)
AzureIoTClient 13:920e00014ee3 650 {
AzureIoTClient 13:920e00014ee3 651 LogError("xio reported error on dowork");
AzureIoTClient 13:920e00014ee3 652 result = -1;
AzureIoTClient 13:920e00014ee3 653 n = 0;
AzureIoTClient 13:920e00014ee3 654 }
AzureIoTClient 13:920e00014ee3 655 else
AzureIoTClient 13:920e00014ee3 656 {
AzureIoTClient 13:920e00014ee3 657 if (http_instance->received_bytes_count <= n)
AzureIoTClient 13:920e00014ee3 658 {
AzureIoTClient 13:920e00014ee3 659 n -= http_instance->received_bytes_count;
AzureIoTClient 13:920e00014ee3 660 http_instance->received_bytes_count = 0;
AzureIoTClient 13:920e00014ee3 661 }
AzureIoTClient 13:920e00014ee3 662 else
AzureIoTClient 13:920e00014ee3 663 {
AzureIoTClient 13:920e00014ee3 664 http_instance->received_bytes_count -= n;
AzureIoTClient 13:920e00014ee3 665 (void)memmove(http_instance->received_bytes, http_instance->received_bytes + n, http_instance->received_bytes_count);
AzureIoTClient 13:920e00014ee3 666 n = 0;
AzureIoTClient 13:920e00014ee3 667 }
AzureIoTClient 13:920e00014ee3 668
AzureIoTClient 13:920e00014ee3 669 if (n > 0)
AzureIoTClient 13:920e00014ee3 670 {
AzureIoTClient 13:920e00014ee3 671 if ((countRetry--) > 0)
AzureIoTClient 13:920e00014ee3 672 {
AzureIoTClient 15:956c6d205aa7 673 /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
AzureIoTClient 15:956c6d205aa7 674 ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
AzureIoTClient 13:920e00014ee3 675 }
AzureIoTClient 13:920e00014ee3 676 else
AzureIoTClient 13:920e00014ee3 677 {
AzureIoTClient 15:956c6d205aa7 678 /*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 679 LogError("Receive timeout. The HTTP request is incomplete");
AzureIoTClient 13:920e00014ee3 680 n = 0;
AzureIoTClient 13:920e00014ee3 681 result = -1;
AzureIoTClient 13:920e00014ee3 682 }
AzureIoTClient 13:920e00014ee3 683 }
AzureIoTClient 13:920e00014ee3 684 }
AzureIoTClient 13:920e00014ee3 685 }
Azure.IoT Build 6:c55b013dfc2a 686 }
Azure.IoT Build 6:c55b013dfc2a 687
AzureIoTClient 13:920e00014ee3 688 return result;
Azure.IoT Build 6:c55b013dfc2a 689 }
Azure.IoT Build 6:c55b013dfc2a 690
AzureIoTClient 11:77df6d7e65ae 691
AzureIoTClient 11:77df6d7e65ae 692 /*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 693 static HTTPAPI_RESULT OpenXIOConnection(HTTP_HANDLE_DATA* http_instance)
AzureIoTClient 11:77df6d7e65ae 694 {
AzureIoTClient 15:956c6d205aa7 695 HTTPAPI_RESULT result;
AzureIoTClient 15:956c6d205aa7 696
AzureIoTClient 15:956c6d205aa7 697 if (http_instance->is_connected != 0)
AzureIoTClient 15:956c6d205aa7 698 {
AzureIoTClient 15:956c6d205aa7 699 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 700 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 701 }
AzureIoTClient 15:956c6d205aa7 702 else
AzureIoTClient 15:956c6d205aa7 703 {
AzureIoTClient 15:956c6d205aa7 704 http_instance->is_io_error = 0;
AzureIoTClient 15:956c6d205aa7 705
AzureIoTClient 15:956c6d205aa7 706 /*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 707 if ((http_instance->certificate != NULL) &&
AzureIoTClient 49:6bb8b9a66642 708 (xio_setoption(http_instance->xio_handle, OPTION_TRUSTED_CERT, http_instance->certificate) != 0))
AzureIoTClient 15:956c6d205aa7 709 {
AzureIoTClient 15:956c6d205aa7 710 /*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 711 result = HTTPAPI_SET_OPTION_FAILED;
AzureIoTClient 15:956c6d205aa7 712 LogInfo("Could not load certificate");
AzureIoTClient 15:956c6d205aa7 713 }
AzureIoTClient 15:956c6d205aa7 714 /*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 715 else if ((http_instance->x509ClientCertificate != NULL) &&
AzureIoTClient 15:956c6d205aa7 716 (xio_setoption(http_instance->xio_handle, SU_OPTION_X509_CERT, http_instance->x509ClientCertificate) != 0))
AzureIoTClient 15:956c6d205aa7 717 {
AzureIoTClient 15:956c6d205aa7 718 /*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 719 result = HTTPAPI_SET_OPTION_FAILED;
AzureIoTClient 15:956c6d205aa7 720 LogInfo("Could not load the client certificate");
AzureIoTClient 15:956c6d205aa7 721 }
AzureIoTClient 15:956c6d205aa7 722 else if ((http_instance->x509ClientPrivateKey != NULL) &&
AzureIoTClient 15:956c6d205aa7 723 (xio_setoption(http_instance->xio_handle, SU_OPTION_X509_PRIVATE_KEY, http_instance->x509ClientPrivateKey) != 0))
AzureIoTClient 15:956c6d205aa7 724 {
AzureIoTClient 11:77df6d7e65ae 725
AzureIoTClient 15:956c6d205aa7 726 /*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 727 result = HTTPAPI_SET_OPTION_FAILED;
AzureIoTClient 15:956c6d205aa7 728 LogInfo("Could not load the client certificate private key");
AzureIoTClient 15:956c6d205aa7 729 }
AzureIoTClient 15:956c6d205aa7 730 else
AzureIoTClient 15:956c6d205aa7 731 {
AzureIoTClient 15:956c6d205aa7 732 /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
AzureIoTClient 15:956c6d205aa7 733 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 734 {
AzureIoTClient 15:956c6d205aa7 735 /*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 736 result = HTTPAPI_OPEN_REQUEST_FAILED;
AzureIoTClient 15:956c6d205aa7 737 }
AzureIoTClient 15:956c6d205aa7 738 else
AzureIoTClient 15:956c6d205aa7 739 {
AzureIoTClient 48:81866008bba4 740 int countRetry;
AzureIoTClient 15:956c6d205aa7 741 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 742 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 743 /*Codes_SRS_HTTPAPI_COMPACT_21_077: [ The HTTPAPI_ExecuteRequest shall wait, at least, 10 seconds for the SSL open process. ]*/
AzureIoTClient 27:8656a313842b 744 countRetry = MAX_OPEN_RETRY;
AzureIoTClient 15:956c6d205aa7 745 while ((http_instance->is_connected == 0) &&
AzureIoTClient 15:956c6d205aa7 746 (http_instance->is_io_error == 0))
AzureIoTClient 15:956c6d205aa7 747 {
AzureIoTClient 15:956c6d205aa7 748 xio_dowork(http_instance->xio_handle);
AzureIoTClient 15:956c6d205aa7 749 LogInfo("Waiting for TLS connection");
AzureIoTClient 15:956c6d205aa7 750 if ((countRetry--) < 0)
AzureIoTClient 15:956c6d205aa7 751 {
AzureIoTClient 15:956c6d205aa7 752 /*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 753 LogError("Open timeout. The HTTP request is incomplete");
AzureIoTClient 15:956c6d205aa7 754 result = HTTPAPI_OPEN_REQUEST_FAILED;
AzureIoTClient 15:956c6d205aa7 755 break;
AzureIoTClient 15:956c6d205aa7 756 }
AzureIoTClient 15:956c6d205aa7 757 else
AzureIoTClient 15:956c6d205aa7 758 {
AzureIoTClient 15:956c6d205aa7 759 /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
AzureIoTClient 15:956c6d205aa7 760 ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
AzureIoTClient 15:956c6d205aa7 761 }
AzureIoTClient 15:956c6d205aa7 762 }
AzureIoTClient 15:956c6d205aa7 763 }
AzureIoTClient 15:956c6d205aa7 764 }
AzureIoTClient 15:956c6d205aa7 765 }
AzureIoTClient 11:77df6d7e65ae 766
AzureIoTClient 15:956c6d205aa7 767 if ((http_instance->is_io_error != 0) && (result == HTTPAPI_OK))
AzureIoTClient 15:956c6d205aa7 768 {
AzureIoTClient 15:956c6d205aa7 769 /*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 770 result = HTTPAPI_OPEN_REQUEST_FAILED;
AzureIoTClient 15:956c6d205aa7 771 }
AzureIoTClient 15:956c6d205aa7 772
AzureIoTClient 15:956c6d205aa7 773 return result;
AzureIoTClient 15:956c6d205aa7 774 }
AzureIoTClient 15:956c6d205aa7 775
AzureIoTClient 15:956c6d205aa7 776 static HTTPAPI_RESULT conn_send_all(HTTP_HANDLE_DATA* http_instance, const unsigned char* buf, size_t bufLen)
AzureIoTClient 15:956c6d205aa7 777 {
AzureIoTClient 15:956c6d205aa7 778 HTTPAPI_RESULT result;
AzureIoTClient 15:956c6d205aa7 779
AzureIoTClient 15:956c6d205aa7 780 http_instance->send_completed = 0;
AzureIoTClient 15:956c6d205aa7 781 http_instance->is_io_error = 0;
AzureIoTClient 15:956c6d205aa7 782 if (xio_send(http_instance->xio_handle, buf, bufLen, on_send_complete, http_instance) != 0)
AzureIoTClient 15:956c6d205aa7 783 {
AzureIoTClient 15:956c6d205aa7 784 /*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 785 result = HTTPAPI_SEND_REQUEST_FAILED;
AzureIoTClient 15:956c6d205aa7 786 }
AzureIoTClient 15:956c6d205aa7 787 else
AzureIoTClient 15:956c6d205aa7 788 {
AzureIoTClient 15:956c6d205aa7 789 /*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 790 int countRetry = MAX_SEND_RETRY;
AzureIoTClient 15:956c6d205aa7 791 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 792 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 793 while ((http_instance->send_completed == 0) && (result == HTTPAPI_OK))
AzureIoTClient 15:956c6d205aa7 794 {
AzureIoTClient 15:956c6d205aa7 795 xio_dowork(http_instance->xio_handle);
AzureIoTClient 15:956c6d205aa7 796 if (http_instance->is_io_error != 0)
AzureIoTClient 15:956c6d205aa7 797 {
AzureIoTClient 15:956c6d205aa7 798 /*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 799 result = HTTPAPI_SEND_REQUEST_FAILED;
AzureIoTClient 15:956c6d205aa7 800 }
AzureIoTClient 15:956c6d205aa7 801 else if ((countRetry--) <= 0)
AzureIoTClient 15:956c6d205aa7 802 {
AzureIoTClient 15:956c6d205aa7 803 /*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 804 LogError("Send timeout. The HTTP request is incomplete");
AzureIoTClient 15:956c6d205aa7 805 /*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 806 result = HTTPAPI_SEND_REQUEST_FAILED;
AzureIoTClient 15:956c6d205aa7 807 }
AzureIoTClient 15:956c6d205aa7 808 else
AzureIoTClient 15:956c6d205aa7 809 {
AzureIoTClient 15:956c6d205aa7 810 /*Codes_SRS_HTTPAPI_COMPACT_21_083: [ The HTTPAPI_ExecuteRequest shall wait, at least, 100 milliseconds between retries. ]*/
AzureIoTClient 15:956c6d205aa7 811 ThreadAPI_Sleep(RETRY_INTERVAL_IN_MICROSECONDS);
AzureIoTClient 15:956c6d205aa7 812 }
AzureIoTClient 15:956c6d205aa7 813 }
AzureIoTClient 15:956c6d205aa7 814 }
AzureIoTClient 15:956c6d205aa7 815
AzureIoTClient 15:956c6d205aa7 816 return result;
AzureIoTClient 11:77df6d7e65ae 817 }
AzureIoTClient 11:77df6d7e65ae 818
AzureIoTClient 49:6bb8b9a66642 819 /*Codes_SRS_HTTPAPI_COMPACT_21_035: [ The HTTPAPI_ExecuteRequest shall execute resquest for types `GET`, `POST`, `PUT`, `DELETE`, `PATCH`, `HEAD`. ]*/
AzureIoTClient 49:6bb8b9a66642 820 const char httpapiRequestString[6][7] = { "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD" };
AzureIoTClient 11:77df6d7e65ae 821 const char* get_request_type(HTTPAPI_REQUEST_TYPE requestType)
AzureIoTClient 11:77df6d7e65ae 822 {
AzureIoTClient 11:77df6d7e65ae 823 return (const char*)httpapiRequestString[requestType];
AzureIoTClient 11:77df6d7e65ae 824 }
AzureIoTClient 11:77df6d7e65ae 825
AzureIoTClient 11:77df6d7e65ae 826 /*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 827 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 828 {
AzureIoTClient 15:956c6d205aa7 829 HTTPAPI_RESULT result;
AzureIoTClient 15:956c6d205aa7 830 char buf[TEMP_BUFFER_SIZE];
AzureIoTClient 15:956c6d205aa7 831 int ret;
AzureIoTClient 11:77df6d7e65ae 832
AzureIoTClient 15:956c6d205aa7 833 //Send request
AzureIoTClient 15:956c6d205aa7 834 /*Codes_SRS_HTTPAPI_COMPACT_21_038: [ The HTTPAPI_ExecuteRequest shall execute the resquest for the path in relativePath parameter. ]*/
AzureIoTClient 15:956c6d205aa7 835 /*Codes_SRS_HTTPAPI_COMPACT_21_036: [ The request type shall be provided in the parameter requestType. ]*/
AzureIoTClient 15:956c6d205aa7 836 if (((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", get_request_type(requestType), relativePath)) < 0) ||
AzureIoTClient 45:1119d0f2c4d8 837 ((size_t)ret >= sizeof(buf)))
AzureIoTClient 15:956c6d205aa7 838 {
AzureIoTClient 15:956c6d205aa7 839 /*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 840 result = HTTPAPI_STRING_PROCESSING_ERROR;
AzureIoTClient 15:956c6d205aa7 841 }
AzureIoTClient 15:956c6d205aa7 842 /*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 843 else if ((result = conn_send_all(http_instance, (const unsigned char*)buf, strlen(buf))) == HTTPAPI_OK)
AzureIoTClient 13:920e00014ee3 844 {
AzureIoTClient 48:81866008bba4 845 size_t i;
AzureIoTClient 15:956c6d205aa7 846 //Send default headers
AzureIoTClient 15:956c6d205aa7 847 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 27:8656a313842b 848 for (i = 0; ((i < headersCount) && (result == HTTPAPI_OK)); i++)
AzureIoTClient 15:956c6d205aa7 849 {
AzureIoTClient 15:956c6d205aa7 850 char* header;
AzureIoTClient 15:956c6d205aa7 851 if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
AzureIoTClient 15:956c6d205aa7 852 {
AzureIoTClient 15:956c6d205aa7 853 /*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 854 result = HTTPAPI_STRING_PROCESSING_ERROR;
AzureIoTClient 15:956c6d205aa7 855 }
AzureIoTClient 15:956c6d205aa7 856 else
AzureIoTClient 15:956c6d205aa7 857 {
AzureIoTClient 15:956c6d205aa7 858 if ((result = conn_send_all(http_instance, (const unsigned char*)header, strlen(header))) == HTTPAPI_OK)
AzureIoTClient 13:920e00014ee3 859 {
AzureIoTClient 15:956c6d205aa7 860 result = conn_send_all(http_instance, (const unsigned char*)"\r\n", (size_t)2);
AzureIoTClient 15:956c6d205aa7 861 }
AzureIoTClient 15:956c6d205aa7 862 free(header);
AzureIoTClient 15:956c6d205aa7 863 }
AzureIoTClient 15:956c6d205aa7 864 }
AzureIoTClient 11:77df6d7e65ae 865
AzureIoTClient 15:956c6d205aa7 866 //Close headers
AzureIoTClient 15:956c6d205aa7 867 if (result == HTTPAPI_OK)
AzureIoTClient 13:920e00014ee3 868 {
AzureIoTClient 15:956c6d205aa7 869 result = conn_send_all(http_instance, (const unsigned char*)"\r\n", (size_t)2);
AzureIoTClient 15:956c6d205aa7 870 }
AzureIoTClient 15:956c6d205aa7 871 }
AzureIoTClient 15:956c6d205aa7 872 return result;
AzureIoTClient 11:77df6d7e65ae 873 }
AzureIoTClient 11:77df6d7e65ae 874
AzureIoTClient 11:77df6d7e65ae 875 /*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
AzureIoTClient 13:920e00014ee3 876 static HTTPAPI_RESULT SendContentToXIO(HTTP_HANDLE_DATA* http_instance, const unsigned char* content, size_t contentLength)
AzureIoTClient 11:77df6d7e65ae 877 {
AzureIoTClient 15:956c6d205aa7 878 HTTPAPI_RESULT result;
AzureIoTClient 11:77df6d7e65ae 879
AzureIoTClient 15:956c6d205aa7 880 //Send data (if available)
AzureIoTClient 15:956c6d205aa7 881 /*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 882 if (content && contentLength > 0)
AzureIoTClient 15:956c6d205aa7 883 {
AzureIoTClient 15:956c6d205aa7 884 /*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 885 result = conn_send_all(http_instance, content, contentLength);
AzureIoTClient 15:956c6d205aa7 886 }
AzureIoTClient 15:956c6d205aa7 887 else
AzureIoTClient 15:956c6d205aa7 888 {
AzureIoTClient 15:956c6d205aa7 889 /*Codes_SRS_HTTPAPI_COMPACT_21_043: [ If the content is NULL, the HTTPAPI_ExecuteRequest shall send the request without content. ]*/
AzureIoTClient 15:956c6d205aa7 890 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 891 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 892 }
AzureIoTClient 15:956c6d205aa7 893 return result;
AzureIoTClient 11:77df6d7e65ae 894 }
AzureIoTClient 11:77df6d7e65ae 895
AzureIoTClient 11:77df6d7e65ae 896 /*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 897 static HTTPAPI_RESULT ReceiveHeaderFromXIO(HTTP_HANDLE_DATA* http_instance, unsigned int* statusCode)
AzureIoTClient 11:77df6d7e65ae 898 {
AzureIoTClient 15:956c6d205aa7 899 HTTPAPI_RESULT result;
AzureIoTClient 15:956c6d205aa7 900 char buf[TEMP_BUFFER_SIZE];
AzureIoTClient 15:956c6d205aa7 901 int ret;
AzureIoTClient 15:956c6d205aa7 902
AzureIoTClient 15:956c6d205aa7 903 http_instance->is_io_error = 0;
AzureIoTClient 11:77df6d7e65ae 904
AzureIoTClient 15:956c6d205aa7 905 //Receive response
AzureIoTClient 15:956c6d205aa7 906 if (readLine(http_instance, buf, TEMP_BUFFER_SIZE) < 0)
AzureIoTClient 15:956c6d205aa7 907 {
AzureIoTClient 15:956c6d205aa7 908 /*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 909 /*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 910 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 911 }
AzureIoTClient 15:956c6d205aa7 912 //Parse HTTP response
AzureIoTClient 15:956c6d205aa7 913 else if (ParseHttpResponse(buf, &ret) != 1)
AzureIoTClient 15:956c6d205aa7 914 {
AzureIoTClient 15:956c6d205aa7 915 //Cannot match string, error
AzureIoTClient 29:e3ed192c35fb 916 /*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 917 LogInfo("Not a correct HTTP answer");
AzureIoTClient 15:956c6d205aa7 918 result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
AzureIoTClient 15:956c6d205aa7 919 }
AzureIoTClient 15:956c6d205aa7 920 else
AzureIoTClient 15:956c6d205aa7 921 {
AzureIoTClient 15:956c6d205aa7 922 /*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 923 /*Codes_SRS_HTTPAPI_COMPACT_21_048: [ If the statusCode is NULL, the HTTPAPI_ExecuteRequest shall report not report any status. ]*/
AzureIoTClient 15:956c6d205aa7 924 if (statusCode)
AzureIoTClient 15:956c6d205aa7 925 {
AzureIoTClient 15:956c6d205aa7 926 /*Codes_SRS_HTTPAPI_COMPACT_21_047: [ The HTTPAPI_ExecuteRequest shall report the status in the statusCode parameter. ]*/
AzureIoTClient 15:956c6d205aa7 927 *statusCode = ret;
AzureIoTClient 15:956c6d205aa7 928 }
AzureIoTClient 15:956c6d205aa7 929 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 930 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 931 }
AzureIoTClient 11:77df6d7e65ae 932
AzureIoTClient 15:956c6d205aa7 933 return result;
AzureIoTClient 11:77df6d7e65ae 934 }
AzureIoTClient 11:77df6d7e65ae 935
AzureIoTClient 29:e3ed192c35fb 936 static HTTPAPI_RESULT ReceiveContentInfoFromXIO(HTTP_HANDLE_DATA* http_instance, HTTP_HEADERS_HANDLE responseHeadersHandle, size_t* bodyLength, bool* chunked)
AzureIoTClient 11:77df6d7e65ae 937 {
AzureIoTClient 15:956c6d205aa7 938 HTTPAPI_RESULT result;
AzureIoTClient 15:956c6d205aa7 939 char buf[TEMP_BUFFER_SIZE];
AzureIoTClient 11:77df6d7e65ae 940 const char* substr;
AzureIoTClient 11:77df6d7e65ae 941 char* whereIsColon;
AzureIoTClient 11:77df6d7e65ae 942 int lengthInMsg;
AzureIoTClient 18:6d8a413a4d9a 943 const char ContentLength[] = "content-length:";
AzureIoTClient 18:6d8a413a4d9a 944 const size_t ContentLengthSize = sizeof(ContentLength) - 1;
AzureIoTClient 18:6d8a413a4d9a 945 const char TransferEncoding[] = "transfer-encoding:";
AzureIoTClient 18:6d8a413a4d9a 946 const size_t TransferEncodingSize = sizeof(TransferEncoding) - 1;
AzureIoTClient 18:6d8a413a4d9a 947 const char Chunked[] = "chunked";
AzureIoTClient 18:6d8a413a4d9a 948 const size_t ChunkedSize = sizeof(Chunked) - 1;
AzureIoTClient 15:956c6d205aa7 949
AzureIoTClient 15:956c6d205aa7 950 http_instance->is_io_error = 0;
AzureIoTClient 11:77df6d7e65ae 951
AzureIoTClient 15:956c6d205aa7 952 //Read HTTP response headers
AzureIoTClient 15:956c6d205aa7 953 if (readLine(http_instance, buf, sizeof(buf)) < 0)
AzureIoTClient 15:956c6d205aa7 954 {
AzureIoTClient 15:956c6d205aa7 955 /*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 956 /*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 957 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 958 }
AzureIoTClient 15:956c6d205aa7 959 else
AzureIoTClient 15:956c6d205aa7 960 {
AzureIoTClient 15:956c6d205aa7 961 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 962 result = HTTPAPI_OK;
AzureIoTClient 11:77df6d7e65ae 963
AzureIoTClient 15:956c6d205aa7 964 while (*buf && (result == HTTPAPI_OK))
AzureIoTClient 15:956c6d205aa7 965 {
AzureIoTClient 15:956c6d205aa7 966 if (InternStrnicmp(buf, ContentLength, ContentLengthSize) == 0)
AzureIoTClient 15:956c6d205aa7 967 {
AzureIoTClient 18:6d8a413a4d9a 968 substr = buf + ContentLengthSize;
AzureIoTClient 15:956c6d205aa7 969 if (ParseStringToDecimal(substr, &lengthInMsg) != 1)
AzureIoTClient 15:956c6d205aa7 970 {
AzureIoTClient 15:956c6d205aa7 971 /*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 972 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 973 }
AzureIoTClient 15:956c6d205aa7 974 else
AzureIoTClient 15:956c6d205aa7 975 {
AzureIoTClient 15:956c6d205aa7 976 (*bodyLength) = (size_t)lengthInMsg;
AzureIoTClient 15:956c6d205aa7 977 }
AzureIoTClient 15:956c6d205aa7 978 }
AzureIoTClient 15:956c6d205aa7 979 else if (InternStrnicmp(buf, TransferEncoding, TransferEncodingSize) == 0)
AzureIoTClient 15:956c6d205aa7 980 {
AzureIoTClient 18:6d8a413a4d9a 981 substr = buf + TransferEncodingSize;
AzureIoTClient 15:956c6d205aa7 982
AzureIoTClient 15:956c6d205aa7 983 while (isspace(*substr)) substr++;
AzureIoTClient 11:77df6d7e65ae 984
AzureIoTClient 15:956c6d205aa7 985 if (InternStrnicmp(substr, Chunked, ChunkedSize) == 0)
AzureIoTClient 15:956c6d205aa7 986 {
AzureIoTClient 15:956c6d205aa7 987 (*chunked) = true;
AzureIoTClient 15:956c6d205aa7 988 }
AzureIoTClient 15:956c6d205aa7 989 }
AzureIoTClient 11:77df6d7e65ae 990
AzureIoTClient 15:956c6d205aa7 991 if (result == HTTPAPI_OK)
AzureIoTClient 15:956c6d205aa7 992 {
AzureIoTClient 15:956c6d205aa7 993 whereIsColon = strchr((char*)buf, ':');
AzureIoTClient 15:956c6d205aa7 994 /*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 995 if (whereIsColon && (responseHeadersHandle != NULL))
AzureIoTClient 15:956c6d205aa7 996 {
AzureIoTClient 15:956c6d205aa7 997 *whereIsColon = '\0';
AzureIoTClient 15:956c6d205aa7 998 HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
AzureIoTClient 15:956c6d205aa7 999 }
AzureIoTClient 11:77df6d7e65ae 1000
AzureIoTClient 15:956c6d205aa7 1001 if (readLine(http_instance, buf, sizeof(buf)) < 0)
AzureIoTClient 15:956c6d205aa7 1002 {
AzureIoTClient 15:956c6d205aa7 1003 /*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 1004 /*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 1005 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 1006 }
AzureIoTClient 15:956c6d205aa7 1007 }
AzureIoTClient 15:956c6d205aa7 1008 }
AzureIoTClient 15:956c6d205aa7 1009 }
AzureIoTClient 11:77df6d7e65ae 1010
AzureIoTClient 15:956c6d205aa7 1011 return result;
AzureIoTClient 11:77df6d7e65ae 1012 }
AzureIoTClient 11:77df6d7e65ae 1013
AzureIoTClient 13:920e00014ee3 1014 static HTTPAPI_RESULT ReadHTTPResponseBodyFromXIO(HTTP_HANDLE_DATA* http_instance, size_t bodyLength, bool chunked, BUFFER_HANDLE responseContent)
AzureIoTClient 11:77df6d7e65ae 1015 {
AzureIoTClient 15:956c6d205aa7 1016 HTTPAPI_RESULT result;
AzureIoTClient 15:956c6d205aa7 1017 char buf[TEMP_BUFFER_SIZE];
AzureIoTClient 15:956c6d205aa7 1018 const unsigned char* receivedContent;
AzureIoTClient 15:956c6d205aa7 1019
AzureIoTClient 15:956c6d205aa7 1020 http_instance->is_io_error = 0;
AzureIoTClient 11:77df6d7e65ae 1021
AzureIoTClient 15:956c6d205aa7 1022 //Read HTTP response body
AzureIoTClient 15:956c6d205aa7 1023 if (!chunked)
AzureIoTClient 15:956c6d205aa7 1024 {
AzureIoTClient 15:956c6d205aa7 1025 if (bodyLength)
AzureIoTClient 15:956c6d205aa7 1026 {
AzureIoTClient 15:956c6d205aa7 1027 if (responseContent != NULL)
AzureIoTClient 15:956c6d205aa7 1028 {
AzureIoTClient 15:956c6d205aa7 1029 if (BUFFER_pre_build(responseContent, bodyLength) != 0)
AzureIoTClient 15:956c6d205aa7 1030 {
AzureIoTClient 15:956c6d205aa7 1031 /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1032 result = HTTPAPI_ALLOC_FAILED;
AzureIoTClient 15:956c6d205aa7 1033 }
AzureIoTClient 15:956c6d205aa7 1034 else if (BUFFER_content(responseContent, &receivedContent) != 0)
AzureIoTClient 15:956c6d205aa7 1035 {
AzureIoTClient 15:956c6d205aa7 1036 (void)BUFFER_unbuild(responseContent);
AzureIoTClient 11:77df6d7e65ae 1037
AzureIoTClient 15:956c6d205aa7 1038 /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1039 result = HTTPAPI_ALLOC_FAILED;
AzureIoTClient 15:956c6d205aa7 1040 }
AzureIoTClient 15:956c6d205aa7 1041 else if (readChunk(http_instance, (char*)receivedContent, bodyLength) < 0)
AzureIoTClient 15:956c6d205aa7 1042 {
AzureIoTClient 15:956c6d205aa7 1043 /*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 1044 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 1045 }
AzureIoTClient 15:956c6d205aa7 1046 else
AzureIoTClient 15:956c6d205aa7 1047 {
AzureIoTClient 15:956c6d205aa7 1048 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 1049 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 1050 }
AzureIoTClient 15:956c6d205aa7 1051 }
AzureIoTClient 13:920e00014ee3 1052 else
AzureIoTClient 13:920e00014ee3 1053 {
AzureIoTClient 13:920e00014ee3 1054 /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
AzureIoTClient 13:920e00014ee3 1055 if (skipN(http_instance, bodyLength) < 0)
AzureIoTClient 13:920e00014ee3 1056 {
AzureIoTClient 15:956c6d205aa7 1057 /*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 1058 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 13:920e00014ee3 1059 }
AzureIoTClient 13:920e00014ee3 1060 else
AzureIoTClient 13:920e00014ee3 1061 {
AzureIoTClient 13:920e00014ee3 1062 result = HTTPAPI_OK;
AzureIoTClient 13:920e00014ee3 1063 }
AzureIoTClient 13:920e00014ee3 1064 }
AzureIoTClient 15:956c6d205aa7 1065 }
AzureIoTClient 15:956c6d205aa7 1066 else
AzureIoTClient 15:956c6d205aa7 1067 {
AzureIoTClient 15:956c6d205aa7 1068 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 1069 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 1070 }
AzureIoTClient 15:956c6d205aa7 1071 }
AzureIoTClient 15:956c6d205aa7 1072 else
AzureIoTClient 15:956c6d205aa7 1073 {
AzureIoTClient 15:956c6d205aa7 1074 size_t size = 0;
AzureIoTClient 15:956c6d205aa7 1075 /*Codes_SRS_HTTPAPI_COMPACT_21_033: [ If the whole process succeed, the HTTPAPI_ExecuteRequest shall retur HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 1076 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 1077 while (result == HTTPAPI_OK)
AzureIoTClient 15:956c6d205aa7 1078 {
AzureIoTClient 15:956c6d205aa7 1079 size_t chunkSize;
AzureIoTClient 15:956c6d205aa7 1080 if (readLine(http_instance, buf, sizeof(buf)) < 0) // read [length in hex]/r/n
AzureIoTClient 15:956c6d205aa7 1081 {
AzureIoTClient 15:956c6d205aa7 1082 /*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 1083 /*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 1084 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 1085 }
AzureIoTClient 15:956c6d205aa7 1086 else if (ParseStringToHexadecimal(buf, &chunkSize) != 1) // chunkSize is length of next line (/r/n is not counted)
AzureIoTClient 15:956c6d205aa7 1087 {
AzureIoTClient 15:956c6d205aa7 1088 //Cannot match string, error
AzureIoTClient 29:e3ed192c35fb 1089 /*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 1090 result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
AzureIoTClient 15:956c6d205aa7 1091 }
AzureIoTClient 15:956c6d205aa7 1092 else if (chunkSize == 0)
AzureIoTClient 15:956c6d205aa7 1093 {
AzureIoTClient 15:956c6d205aa7 1094 // 0 length means next line is just '\r\n' and end of chunks
AzureIoTClient 15:956c6d205aa7 1095 if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
AzureIoTClient 15:956c6d205aa7 1096 || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
AzureIoTClient 15:956c6d205aa7 1097 {
AzureIoTClient 15:956c6d205aa7 1098 (void)BUFFER_unbuild(responseContent);
AzureIoTClient 11:77df6d7e65ae 1099
AzureIoTClient 15:956c6d205aa7 1100 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 1101 }
AzureIoTClient 15:956c6d205aa7 1102 break;
AzureIoTClient 15:956c6d205aa7 1103 }
AzureIoTClient 15:956c6d205aa7 1104 else
AzureIoTClient 15:956c6d205aa7 1105 {
AzureIoTClient 15:956c6d205aa7 1106 if (responseContent != NULL)
AzureIoTClient 15:956c6d205aa7 1107 {
AzureIoTClient 15:956c6d205aa7 1108 if (BUFFER_enlarge(responseContent, chunkSize) != 0)
AzureIoTClient 15:956c6d205aa7 1109 {
AzureIoTClient 15:956c6d205aa7 1110 (void)BUFFER_unbuild(responseContent);
AzureIoTClient 11:77df6d7e65ae 1111
AzureIoTClient 15:956c6d205aa7 1112 /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1113 result = HTTPAPI_ALLOC_FAILED;
AzureIoTClient 15:956c6d205aa7 1114 }
AzureIoTClient 15:956c6d205aa7 1115 else if (BUFFER_content(responseContent, &receivedContent) != 0)
AzureIoTClient 15:956c6d205aa7 1116 {
AzureIoTClient 15:956c6d205aa7 1117 (void)BUFFER_unbuild(responseContent);
AzureIoTClient 11:77df6d7e65ae 1118
AzureIoTClient 15:956c6d205aa7 1119 /*Codes_SRS_HTTPAPI_COMPACT_21_052: [ If any memory allocation get fail, the HTTPAPI_ExecuteRequest shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1120 result = HTTPAPI_ALLOC_FAILED;
AzureIoTClient 15:956c6d205aa7 1121 }
AzureIoTClient 15:956c6d205aa7 1122 else if (readChunk(http_instance, (char*)receivedContent + size, chunkSize) < 0)
AzureIoTClient 15:956c6d205aa7 1123 {
AzureIoTClient 15:956c6d205aa7 1124 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 1125 }
AzureIoTClient 15:956c6d205aa7 1126 }
AzureIoTClient 15:956c6d205aa7 1127 else
AzureIoTClient 15:956c6d205aa7 1128 {
AzureIoTClient 15:956c6d205aa7 1129 /*Codes_SRS_HTTPAPI_COMPACT_21_051: [ If the responseContent is NULL, the HTTPAPI_ExecuteRequest shall ignore any content in the response. ]*/
AzureIoTClient 15:956c6d205aa7 1130 if (skipN(http_instance, chunkSize) < 0)
AzureIoTClient 15:956c6d205aa7 1131 {
AzureIoTClient 15:956c6d205aa7 1132 /*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 1133 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 1134 }
AzureIoTClient 15:956c6d205aa7 1135 }
AzureIoTClient 11:77df6d7e65ae 1136
AzureIoTClient 15:956c6d205aa7 1137 if (result == HTTPAPI_OK)
AzureIoTClient 15:956c6d205aa7 1138 {
AzureIoTClient 15:956c6d205aa7 1139 if (readChunk(http_instance, (char*)buf, (size_t)2) < 0
AzureIoTClient 15:956c6d205aa7 1140 || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
AzureIoTClient 15:956c6d205aa7 1141 {
AzureIoTClient 15:956c6d205aa7 1142 result = HTTPAPI_READ_DATA_FAILED;
AzureIoTClient 15:956c6d205aa7 1143 }
AzureIoTClient 15:956c6d205aa7 1144 size += chunkSize;
AzureIoTClient 15:956c6d205aa7 1145 }
AzureIoTClient 15:956c6d205aa7 1146 }
AzureIoTClient 15:956c6d205aa7 1147 }
AzureIoTClient 11:77df6d7e65ae 1148
AzureIoTClient 15:956c6d205aa7 1149 }
AzureIoTClient 15:956c6d205aa7 1150 return result;
AzureIoTClient 11:77df6d7e65ae 1151 }
AzureIoTClient 11:77df6d7e65ae 1152
AzureIoTClient 11:77df6d7e65ae 1153
AzureIoTClient 11:77df6d7e65ae 1154 /*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 11:77df6d7e65ae 1155 static bool validRequestType(HTTPAPI_REQUEST_TYPE requestType)
AzureIoTClient 11:77df6d7e65ae 1156 {
AzureIoTClient 15:956c6d205aa7 1157 bool result;
AzureIoTClient 11:77df6d7e65ae 1158
AzureIoTClient 15:956c6d205aa7 1159 if ((requestType == HTTPAPI_REQUEST_GET) ||
AzureIoTClient 15:956c6d205aa7 1160 (requestType == HTTPAPI_REQUEST_POST) ||
AzureIoTClient 15:956c6d205aa7 1161 (requestType == HTTPAPI_REQUEST_PUT) ||
AzureIoTClient 15:956c6d205aa7 1162 (requestType == HTTPAPI_REQUEST_DELETE) ||
AzureIoTClient 49:6bb8b9a66642 1163 (requestType == HTTPAPI_REQUEST_PATCH) ||
AzureIoTClient 49:6bb8b9a66642 1164 (requestType == HTTPAPI_REQUEST_HEAD))
AzureIoTClient 15:956c6d205aa7 1165 {
AzureIoTClient 15:956c6d205aa7 1166 result = true;
AzureIoTClient 15:956c6d205aa7 1167 }
AzureIoTClient 15:956c6d205aa7 1168 else
AzureIoTClient 15:956c6d205aa7 1169 {
AzureIoTClient 15:956c6d205aa7 1170 result = false;
AzureIoTClient 15:956c6d205aa7 1171 }
AzureIoTClient 11:77df6d7e65ae 1172
AzureIoTClient 15:956c6d205aa7 1173 return result;
AzureIoTClient 11:77df6d7e65ae 1174 }
AzureIoTClient 11:77df6d7e65ae 1175
AzureIoTClient 11:77df6d7e65ae 1176 /*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 1177 /*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 1178 //Note: This function assumes that "Host:" and "Content-Length:" headers are setup
Azure.IoT Build 6:c55b013dfc2a 1179 // by the caller of HTTPAPI_ExecuteRequest() (which is true for httptransport.c).
Azure.IoT Build 6:c55b013dfc2a 1180 HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
Azure.IoT Build 6:c55b013dfc2a 1181 HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content,
Azure.IoT Build 6:c55b013dfc2a 1182 size_t contentLength, unsigned int* statusCode,
Azure.IoT Build 6:c55b013dfc2a 1183 HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
Azure.IoT Build 6:c55b013dfc2a 1184 {
AzureIoTClient 11:77df6d7e65ae 1185 HTTPAPI_RESULT result = HTTPAPI_ERROR;
Azure.IoT Build 6:c55b013dfc2a 1186 size_t headersCount;
Azure.IoT Build 6:c55b013dfc2a 1187 size_t bodyLength = 0;
Azure.IoT Build 6:c55b013dfc2a 1188 bool chunked = false;
AzureIoTClient 15:956c6d205aa7 1189 HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
Azure.IoT Build 6:c55b013dfc2a 1190
AzureIoTClient 15:956c6d205aa7 1191 /*Codes_SRS_HTTPAPI_COMPACT_21_034: [ If there is no previous connection, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1192 /*Codes_SRS_HTTPAPI_COMPACT_21_037: [ If the request type is unknown, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1193 /*Codes_SRS_HTTPAPI_COMPACT_21_039: [ If the relativePath is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1194 /*Codes_SRS_HTTPAPI_COMPACT_21_041: [ If the httpHeadersHandle is NULL or invalid, the HTTPAPI_ExecuteRequest shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1195 /*Codes_SRS_HTTPAPI_COMPACT_21_053: [ The HTTPAPI_ExecuteRequest shall produce a set of http header to send to the host. ]*/
AzureIoTClient 15:956c6d205aa7 1196 /*Codes_SRS_HTTPAPI_COMPACT_21_040: [ The request shall contain the http header provided in httpHeadersHandle parameter. ]*/
AzureIoTClient 15:956c6d205aa7 1197 /*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 1198 if (http_instance == NULL ||
Azure.IoT Build 6:c55b013dfc2a 1199 relativePath == NULL ||
Azure.IoT Build 6:c55b013dfc2a 1200 httpHeadersHandle == NULL ||
AzureIoTClient 15:956c6d205aa7 1201 !validRequestType(requestType) ||
Azure.IoT Build 6:c55b013dfc2a 1202 HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK)
Azure.IoT Build 6:c55b013dfc2a 1203 {
Azure.IoT Build 6:c55b013dfc2a 1204 result = HTTPAPI_INVALID_ARG;
Azure.IoT Build 6:c55b013dfc2a 1205 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 1206 }
AzureIoTClient 15:956c6d205aa7 1207 /*Codes_SRS_HTTPAPI_COMPACT_21_024: [ The HTTPAPI_ExecuteRequest shall open the transport connection with the host to send the request. ]*/
AzureIoTClient 15:956c6d205aa7 1208 else if ((result = OpenXIOConnection(http_instance)) != HTTPAPI_OK)
AzureIoTClient 15:956c6d205aa7 1209 {
AzureIoTClient 15:956c6d205aa7 1210 LogError("Open HTTP connection failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
AzureIoTClient 15:956c6d205aa7 1211 }
AzureIoTClient 15:956c6d205aa7 1212 /*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 1213 else if ((result = SendHeadsToXIO(http_instance, requestType, relativePath, httpHeadersHandle, headersCount)) != HTTPAPI_OK)
AzureIoTClient 15:956c6d205aa7 1214 {
AzureIoTClient 15:956c6d205aa7 1215 LogError("Send heads to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
AzureIoTClient 15:956c6d205aa7 1216 }
AzureIoTClient 15:956c6d205aa7 1217 /*Codes_SRS_HTTPAPI_COMPACT_21_042: [ The request can contain the a content message, provided in content parameter. ]*/
AzureIoTClient 15:956c6d205aa7 1218 else if ((result = SendContentToXIO(http_instance, content, contentLength)) != HTTPAPI_OK)
AzureIoTClient 15:956c6d205aa7 1219 {
AzureIoTClient 15:956c6d205aa7 1220 LogError("Send content to HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
AzureIoTClient 15:956c6d205aa7 1221 }
AzureIoTClient 15:956c6d205aa7 1222 /*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 1223 /*Codes_SRS_HTTPAPI_COMPACT_21_073: [ The message received by the HTTPAPI_ExecuteRequest shall starts with a valid header. ]*/
AzureIoTClient 29:e3ed192c35fb 1224 else if ((result = ReceiveHeaderFromXIO(http_instance, statusCode)) != HTTPAPI_OK)
AzureIoTClient 15:956c6d205aa7 1225 {
AzureIoTClient 15:956c6d205aa7 1226 LogError("Receive header from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
AzureIoTClient 15:956c6d205aa7 1227 }
AzureIoTClient 29:e3ed192c35fb 1228 /*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 1229 else if ((result = ReceiveContentInfoFromXIO(http_instance, responseHeadersHandle, &bodyLength, &chunked)) != HTTPAPI_OK)
AzureIoTClient 15:956c6d205aa7 1230 {
AzureIoTClient 15:956c6d205aa7 1231 LogError("Receive content information from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
AzureIoTClient 15:956c6d205aa7 1232 }
AzureIoTClient 49:6bb8b9a66642 1233 /*Codes_SRS_HTTPAPI_COMPACT_42_084: [ The message received by the HTTPAPI_ExecuteRequest should not contain http body. ]*/
AzureIoTClient 49:6bb8b9a66642 1234 else if (requestType != HTTPAPI_REQUEST_HEAD)
AzureIoTClient 15:956c6d205aa7 1235 {
AzureIoTClient 49:6bb8b9a66642 1236 /*Codes_SRS_HTTPAPI_COMPACT_21_075: [ The message received by the HTTPAPI_ExecuteRequest can contain a body with the message content. ]*/
AzureIoTClient 49:6bb8b9a66642 1237 if ((result = ReadHTTPResponseBodyFromXIO(http_instance, bodyLength, chunked, responseContent)) != HTTPAPI_OK)
AzureIoTClient 49:6bb8b9a66642 1238 {
AzureIoTClient 49:6bb8b9a66642 1239 LogError("Read HTTP response body from HTTP failed (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
AzureIoTClient 49:6bb8b9a66642 1240 }
AzureIoTClient 15:956c6d205aa7 1241 }
Azure.IoT Build 6:c55b013dfc2a 1242
AzureIoTClient 13:920e00014ee3 1243 conn_receive_discard_buffer(http_instance);
AzureIoTClient 13:920e00014ee3 1244
AzureIoTClient 11:77df6d7e65ae 1245 return result;
AzureIoTClient 11:77df6d7e65ae 1246 }
Azure.IoT Build 6:c55b013dfc2a 1247
AzureIoTClient 11:77df6d7e65ae 1248 /*Codes_SRS_HTTPAPI_COMPACT_21_056: [ The HTTPAPI_SetOption shall change the HTTP options. ]*/
AzureIoTClient 32:3b68703b9316 1249 /*Codes_SRS_HTTPAPI_COMPACT_21_057: [ The HTTPAPI_SetOption shall receive a handle that identiry the HTTP connection. ]*/
AzureIoTClient 32:3b68703b9316 1250 /*Codes_SRS_HTTPAPI_COMPACT_21_058: [ The HTTPAPI_SetOption shall receive the option as a pair optionName/value. ]*/
AzureIoTClient 11:77df6d7e65ae 1251 HTTPAPI_RESULT HTTPAPI_SetOption(HTTP_HANDLE handle, const char* optionName, const void* value)
AzureIoTClient 11:77df6d7e65ae 1252 {
AzureIoTClient 11:77df6d7e65ae 1253 HTTPAPI_RESULT result;
AzureIoTClient 13:920e00014ee3 1254 HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)handle;
Azure.IoT Build 6:c55b013dfc2a 1255
AzureIoTClient 15:956c6d205aa7 1256 if (
AzureIoTClient 13:920e00014ee3 1257 (http_instance == NULL) ||
AzureIoTClient 11:77df6d7e65ae 1258 (optionName == NULL) ||
AzureIoTClient 11:77df6d7e65ae 1259 (value == NULL)
AzureIoTClient 11:77df6d7e65ae 1260 )
Azure.IoT Build 6:c55b013dfc2a 1261 {
AzureIoTClient 15:956c6d205aa7 1262 /*Codes_SRS_HTTPAPI_COMPACT_21_059: [ If the handle is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1263 /*Codes_SRS_HTTPAPI_COMPACT_21_060: [ If the optionName is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1264 /*Codes_SRS_HTTPAPI_COMPACT_21_061: [ If the value is NULL, the HTTPAPI_SetOption shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1265 result = HTTPAPI_INVALID_ARG;
Azure.IoT Build 6:c55b013dfc2a 1266 }
AzureIoTClient 49:6bb8b9a66642 1267 else if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
Azure.IoT Build 6:c55b013dfc2a 1268 {
AzureIoTClient 49:6bb8b9a66642 1269 #ifdef DO_NOT_COPY_TRUSTED_CERTS_STRING
AzureIoTClient 49:6bb8b9a66642 1270 result = HTTPAPI_OK;
AzureIoTClient 49:6bb8b9a66642 1271 http_instance->certificate = (char*)value;
AzureIoTClient 49:6bb8b9a66642 1272 #else
AzureIoTClient 48:81866008bba4 1273 int len;
AzureIoTClient 27:8656a313842b 1274
AzureIoTClient 13:920e00014ee3 1275 if (http_instance->certificate)
Azure.IoT Build 6:c55b013dfc2a 1276 {
AzureIoTClient 13:920e00014ee3 1277 free(http_instance->certificate);
Azure.IoT Build 6:c55b013dfc2a 1278 }
Azure.IoT Build 6:c55b013dfc2a 1279
AzureIoTClient 27:8656a313842b 1280 len = (int)strlen((char*)value);
AzureIoTClient 13:920e00014ee3 1281 http_instance->certificate = (char*)malloc((len + 1) * sizeof(char));
AzureIoTClient 13:920e00014ee3 1282 if (http_instance->certificate == NULL)
Azure.IoT Build 6:c55b013dfc2a 1283 {
AzureIoTClient 15:956c6d205aa7 1284 /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1285 result = HTTPAPI_ALLOC_FAILED;
AzureIoTClient 11:77df6d7e65ae 1286 LogInfo("unable to allocate memory for the certificate in HTTPAPI_SetOption");
Azure.IoT Build 6:c55b013dfc2a 1287 }
Azure.IoT Build 6:c55b013dfc2a 1288 else
Azure.IoT Build 6:c55b013dfc2a 1289 {
AzureIoTClient 15:956c6d205aa7 1290 /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
AzureIoTClient 13:920e00014ee3 1291 (void)strcpy(http_instance->certificate, (const char*)value);
Azure.IoT Build 6:c55b013dfc2a 1292 result = HTTPAPI_OK;
Azure.IoT Build 6:c55b013dfc2a 1293 }
AzureIoTClient 49:6bb8b9a66642 1294 #endif // DO_NOT_COPY_TRUSTED_CERTS_STRING
Azure.IoT Build 6:c55b013dfc2a 1295 }
AzureIoTClient 15:956c6d205aa7 1296 else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
AzureIoTClient 15:956c6d205aa7 1297 {
AzureIoTClient 48:81866008bba4 1298 int len;
AzureIoTClient 15:956c6d205aa7 1299 if (http_instance->x509ClientCertificate)
AzureIoTClient 15:956c6d205aa7 1300 {
AzureIoTClient 15:956c6d205aa7 1301 free(http_instance->x509ClientCertificate);
AzureIoTClient 15:956c6d205aa7 1302 }
AzureIoTClient 15:956c6d205aa7 1303
AzureIoTClient 27:8656a313842b 1304 len = (int)strlen((char*)value);
AzureIoTClient 15:956c6d205aa7 1305 http_instance->x509ClientCertificate = (char*)malloc((len + 1) * sizeof(char));
AzureIoTClient 15:956c6d205aa7 1306 if (http_instance->x509ClientCertificate == NULL)
AzureIoTClient 15:956c6d205aa7 1307 {
AzureIoTClient 15:956c6d205aa7 1308 /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1309 result = HTTPAPI_ALLOC_FAILED;
AzureIoTClient 15:956c6d205aa7 1310 LogInfo("unable to allocate memory for the client certificate in HTTPAPI_SetOption");
AzureIoTClient 15:956c6d205aa7 1311 }
AzureIoTClient 15:956c6d205aa7 1312 else
AzureIoTClient 15:956c6d205aa7 1313 {
AzureIoTClient 15:956c6d205aa7 1314 /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 1315 (void)strcpy(http_instance->x509ClientCertificate, (const char*)value);
AzureIoTClient 15:956c6d205aa7 1316 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 1317 }
AzureIoTClient 15:956c6d205aa7 1318 }
AzureIoTClient 15:956c6d205aa7 1319 else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
AzureIoTClient 15:956c6d205aa7 1320 {
AzureIoTClient 48:81866008bba4 1321 int len;
AzureIoTClient 15:956c6d205aa7 1322 if (http_instance->x509ClientPrivateKey)
AzureIoTClient 15:956c6d205aa7 1323 {
AzureIoTClient 15:956c6d205aa7 1324 free(http_instance->x509ClientPrivateKey);
AzureIoTClient 15:956c6d205aa7 1325 }
AzureIoTClient 15:956c6d205aa7 1326
AzureIoTClient 27:8656a313842b 1327 len = (int)strlen((char*)value);
AzureIoTClient 15:956c6d205aa7 1328 http_instance->x509ClientPrivateKey = (char*)malloc((len + 1) * sizeof(char));
AzureIoTClient 15:956c6d205aa7 1329 if (http_instance->x509ClientPrivateKey == NULL)
AzureIoTClient 15:956c6d205aa7 1330 {
AzureIoTClient 15:956c6d205aa7 1331 /*Codes_SRS_HTTPAPI_COMPACT_21_062: [ If any memory allocation get fail, the HTTPAPI_SetOption shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1332 result = HTTPAPI_ALLOC_FAILED;
AzureIoTClient 15:956c6d205aa7 1333 LogInfo("unable to allocate memory for the client private key in HTTPAPI_SetOption");
AzureIoTClient 15:956c6d205aa7 1334 }
AzureIoTClient 15:956c6d205aa7 1335 else
AzureIoTClient 15:956c6d205aa7 1336 {
AzureIoTClient 15:956c6d205aa7 1337 /*Codes_SRS_HTTPAPI_COMPACT_21_064: [ If the HTTPAPI_SetOption get success setting the option, it shall return HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 1338 (void)strcpy(http_instance->x509ClientPrivateKey, (const char*)value);
AzureIoTClient 15:956c6d205aa7 1339 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 1340 }
AzureIoTClient 15:956c6d205aa7 1341 }
Azure.IoT Build 6:c55b013dfc2a 1342 else
Azure.IoT Build 6:c55b013dfc2a 1343 {
AzureIoTClient 15:956c6d205aa7 1344 /*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 1345 result = HTTPAPI_INVALID_ARG;
AzureIoTClient 11:77df6d7e65ae 1346 LogInfo("unknown option %s", optionName);
Azure.IoT Build 6:c55b013dfc2a 1347 }
Azure.IoT Build 6:c55b013dfc2a 1348 return result;
Azure.IoT Build 6:c55b013dfc2a 1349 }
Azure.IoT Build 6:c55b013dfc2a 1350
AzureIoTClient 11:77df6d7e65ae 1351 /*Codes_SRS_HTTPAPI_COMPACT_21_065: [ The HTTPAPI_CloneOption shall provide the means to clone the HTTP option. ]*/
AzureIoTClient 11:77df6d7e65ae 1352 /*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 1353 HTTPAPI_RESULT HTTPAPI_CloneOption(const char* optionName, const void* value, const void** savedValue)
Azure.IoT Build 6:c55b013dfc2a 1354 {
Azure.IoT Build 6:c55b013dfc2a 1355 HTTPAPI_RESULT result;
AzureIoTClient 11:77df6d7e65ae 1356 size_t certLen;
AzureIoTClient 11:77df6d7e65ae 1357 char* tempCert;
AzureIoTClient 11:77df6d7e65ae 1358
AzureIoTClient 15:956c6d205aa7 1359 if (
Azure.IoT Build 6:c55b013dfc2a 1360 (optionName == NULL) ||
Azure.IoT Build 6:c55b013dfc2a 1361 (value == NULL) ||
Azure.IoT Build 6:c55b013dfc2a 1362 (savedValue == NULL)
Azure.IoT Build 6:c55b013dfc2a 1363 )
Azure.IoT Build 6:c55b013dfc2a 1364 {
AzureIoTClient 15:956c6d205aa7 1365 /*Codes_SRS_HTTPAPI_COMPACT_21_067: [ If the optionName is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1366 /*Codes_SRS_HTTPAPI_COMPACT_21_068: [ If the value is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1367 /*Codes_SRS_HTTPAPI_COMPACT_21_069: [ If the savedValue is NULL, the HTTPAPI_CloneOption shall return HTTPAPI_INVALID_ARG. ]*/
AzureIoTClient 15:956c6d205aa7 1368 result = HTTPAPI_INVALID_ARG;
Azure.IoT Build 6:c55b013dfc2a 1369 }
AzureIoTClient 49:6bb8b9a66642 1370 else if (strcmp(OPTION_TRUSTED_CERT, optionName) == 0)
Azure.IoT Build 6:c55b013dfc2a 1371 {
AzureIoTClient 49:6bb8b9a66642 1372 #ifdef DO_NOT_COPY_TRUSTED_CERTS_STRING
AzureIoTClient 49:6bb8b9a66642 1373 *savedValue = (const void*)value;
AzureIoTClient 49:6bb8b9a66642 1374 result = HTTPAPI_OK;
AzureIoTClient 49:6bb8b9a66642 1375 #else
AzureIoTClient 11:77df6d7e65ae 1376 certLen = strlen((const char*)value);
AzureIoTClient 11:77df6d7e65ae 1377 tempCert = (char*)malloc((certLen + 1) * sizeof(char));
Azure.IoT Build 6:c55b013dfc2a 1378 if (tempCert == NULL)
Azure.IoT Build 6:c55b013dfc2a 1379 {
AzureIoTClient 15:956c6d205aa7 1380 /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1381 result = HTTPAPI_ALLOC_FAILED;
Azure.IoT Build 6:c55b013dfc2a 1382 }
Azure.IoT Build 6:c55b013dfc2a 1383 else
Azure.IoT Build 6:c55b013dfc2a 1384 {
AzureIoTClient 15:956c6d205aa7 1385 /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 1386 (void)strcpy(tempCert, (const char*)value);
AzureIoTClient 15:956c6d205aa7 1387 *savedValue = tempCert;
AzureIoTClient 15:956c6d205aa7 1388 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 1389 }
AzureIoTClient 49:6bb8b9a66642 1390 #endif // DO_NOT_COPY_TRUSTED_CERTS_STRING
AzureIoTClient 15:956c6d205aa7 1391 }
AzureIoTClient 15:956c6d205aa7 1392 else if (strcmp(SU_OPTION_X509_CERT, optionName) == 0)
AzureIoTClient 15:956c6d205aa7 1393 {
AzureIoTClient 15:956c6d205aa7 1394 certLen = strlen((const char*)value);
AzureIoTClient 15:956c6d205aa7 1395 tempCert = (char*)malloc((certLen + 1) * sizeof(char));
AzureIoTClient 15:956c6d205aa7 1396 if (tempCert == NULL)
AzureIoTClient 15:956c6d205aa7 1397 {
AzureIoTClient 15:956c6d205aa7 1398 /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1399 result = HTTPAPI_ALLOC_FAILED;
AzureIoTClient 15:956c6d205aa7 1400 }
AzureIoTClient 15:956c6d205aa7 1401 else
AzureIoTClient 15:956c6d205aa7 1402 {
AzureIoTClient 15:956c6d205aa7 1403 /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 1404 (void)strcpy(tempCert, (const char*)value);
AzureIoTClient 15:956c6d205aa7 1405 *savedValue = tempCert;
AzureIoTClient 15:956c6d205aa7 1406 result = HTTPAPI_OK;
AzureIoTClient 15:956c6d205aa7 1407 }
AzureIoTClient 15:956c6d205aa7 1408 }
AzureIoTClient 15:956c6d205aa7 1409 else if (strcmp(SU_OPTION_X509_PRIVATE_KEY, optionName) == 0)
AzureIoTClient 15:956c6d205aa7 1410 {
AzureIoTClient 15:956c6d205aa7 1411 certLen = strlen((const char*)value);
AzureIoTClient 15:956c6d205aa7 1412 tempCert = (char*)malloc((certLen + 1) * sizeof(char));
AzureIoTClient 15:956c6d205aa7 1413 if (tempCert == NULL)
AzureIoTClient 15:956c6d205aa7 1414 {
AzureIoTClient 15:956c6d205aa7 1415 /*Codes_SRS_HTTPAPI_COMPACT_21_070: [ If any memory allocation get fail, the HTTPAPI_CloneOption shall return HTTPAPI_ALLOC_FAILED. ]*/
AzureIoTClient 15:956c6d205aa7 1416 result = HTTPAPI_ALLOC_FAILED;
AzureIoTClient 15:956c6d205aa7 1417 }
AzureIoTClient 15:956c6d205aa7 1418 else
AzureIoTClient 15:956c6d205aa7 1419 {
AzureIoTClient 15:956c6d205aa7 1420 /*Codes_SRS_HTTPAPI_COMPACT_21_072: [ If the HTTPAPI_CloneOption get success setting the option, it shall return HTTPAPI_OK. ]*/
AzureIoTClient 15:956c6d205aa7 1421 (void)strcpy(tempCert, (const char*)value);
Azure.IoT Build 6:c55b013dfc2a 1422 *savedValue = tempCert;
Azure.IoT Build 6:c55b013dfc2a 1423 result = HTTPAPI_OK;
Azure.IoT Build 6:c55b013dfc2a 1424 }
Azure.IoT Build 6:c55b013dfc2a 1425 }
Azure.IoT Build 6:c55b013dfc2a 1426 else
Azure.IoT Build 6:c55b013dfc2a 1427 {
AzureIoTClient 15:956c6d205aa7 1428 /*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 1429 result = HTTPAPI_INVALID_ARG;
AzureIoTClient 11:77df6d7e65ae 1430 LogInfo("unknown option %s", optionName);
Azure.IoT Build 6:c55b013dfc2a 1431 }
Azure.IoT Build 6:c55b013dfc2a 1432 return result;
Azure.IoT Build 6:c55b013dfc2a 1433 }