Azure IoT common library

Fork of azure_c_shared_utility by Azure IoT

Committer:
wiggly
Date:
Thu Aug 24 14:14:15 2017 +0100
Revision:
34:651c23af382c
Parent:
29:e3ed192c35fb
Pass in network stack to platform initialisation
Remove NTP setup from azure platform code

Who changed what in which revision?

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