Azure IoT common library

Dependents:   STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more

Committer:
AzureIoTClient
Date:
Fri Jan 13 18:41:15 2017 -0800
Revision:
18:6d8a413a4d9a
Parent:
15:956c6d205aa7
Child:
19:2e0811512ceb
1.1.4

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