Azure IoT common library

Dependents:   STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more

Committer:
AzureIoTClient
Date:
Wed Nov 16 21:38:39 2016 -0800
Revision:
15:956c6d205aa7
Parent:
14:b7e6599cacf5
Child:
18:6d8a413a4d9a
1.0.10

Who changed what in which revision?

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