Azure IoT common library

Dependents:   STM32F746_iothub_client_sample_mqtt f767zi_mqtt iothub_client_sample_amqp iothub_client_sample_http ... more

Committer:
AzureIoTClient
Date:
Sat Jan 28 09:35:22 2017 -0800
Revision:
19:2e0811512ceb
Parent:
18:6d8a413a4d9a
Child:
22:10640b226104
1.1.6

Who changed what in which revision?

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