Azure IoT common library

Fork of azure_c_shared_utility by Azure IoT

Committer:
AzureIoTClient
Date:
Fri Sep 09 13:38:26 2016 -0700
Revision:
11:77df6d7e65ae
Parent:
7:1af47e3a19b6
Child:
13:920e00014ee3
1.0.10

Who changed what in which revision?

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