Azure IoT common library

Fork of azure_c_shared_utility by Azure IoT

Committer:
AzureIoTClient
Date:
Fri Jul 29 16:01:07 2016 -0700
Revision:
7:1af47e3a19b6
Parent:
6:c55b013dfc2a
Child:
11:77df6d7e65ae
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 <stdlib.h>
Azure.IoT Build 6:c55b013dfc2a 11 #include <ctype.h>
Azure.IoT Build 6:c55b013dfc2a 12 #include "azure_c_shared_utility/httpapi.h"
Azure.IoT Build 6:c55b013dfc2a 13 #include "azure_c_shared_utility/httpheaders.h"
Azure.IoT Build 6:c55b013dfc2a 14 #include "azure_c_shared_utility/crt_abstractions.h"
Azure.IoT Build 6:c55b013dfc2a 15 #include "azure_c_shared_utility/xlogging.h"
Azure.IoT Build 6:c55b013dfc2a 16 #include "azure_c_shared_utility/xio.h"
Azure.IoT Build 6:c55b013dfc2a 17 #include "azure_c_shared_utility/platform.h"
Azure.IoT Build 6:c55b013dfc2a 18 #include "azure_c_shared_utility/tlsio.h"
Azure.IoT Build 6:c55b013dfc2a 19 #include "azure_c_shared_utility/threadapi.h"
Azure.IoT Build 6:c55b013dfc2a 20 #include <string.h>
AzureIoTClient 7:1af47e3a19b6 21 #include <limits.h>
Azure.IoT Build 6:c55b013dfc2a 22
Azure.IoT Build 6:c55b013dfc2a 23 #define MAX_HOSTNAME 64
Azure.IoT Build 6:c55b013dfc2a 24 #define TEMP_BUFFER_SIZE 4096
Azure.IoT Build 6:c55b013dfc2a 25
Azure.IoT Build 6:c55b013dfc2a 26 #define CHAR_COUNT(A) (sizeof(A) - 1)
Azure.IoT Build 6:c55b013dfc2a 27
Azure.IoT Build 6:c55b013dfc2a 28 DEFINE_ENUM_STRINGS(HTTPAPI_RESULT, HTTPAPI_RESULT_VALUES)
Azure.IoT Build 6:c55b013dfc2a 29
Azure.IoT Build 6:c55b013dfc2a 30 typedef enum SEND_ALL_RESULT_TAG
Azure.IoT Build 6:c55b013dfc2a 31 {
Azure.IoT Build 6:c55b013dfc2a 32 SEND_ALL_RESULT_NOT_STARTED,
Azure.IoT Build 6:c55b013dfc2a 33 SEND_ALL_RESULT_PENDING,
Azure.IoT Build 6:c55b013dfc2a 34 SEND_ALL_RESULT_OK,
Azure.IoT Build 6:c55b013dfc2a 35 SEND_ALL_RESULT_ERROR
Azure.IoT Build 6:c55b013dfc2a 36 } SEND_ALL_RESULT;
Azure.IoT Build 6:c55b013dfc2a 37
Azure.IoT Build 6:c55b013dfc2a 38 typedef struct HTTP_HANDLE_DATA_TAG
Azure.IoT Build 6:c55b013dfc2a 39 {
Azure.IoT Build 6:c55b013dfc2a 40 char host[MAX_HOSTNAME];
Azure.IoT Build 6:c55b013dfc2a 41 char* certificate;
Azure.IoT Build 6:c55b013dfc2a 42 XIO_HANDLE xio_handle;
Azure.IoT Build 6:c55b013dfc2a 43 size_t received_bytes_count;
Azure.IoT Build 6:c55b013dfc2a 44 unsigned char* received_bytes;
Azure.IoT Build 6:c55b013dfc2a 45 SEND_ALL_RESULT send_all_result;
Azure.IoT Build 6:c55b013dfc2a 46 unsigned int is_io_error : 1;
Azure.IoT Build 6:c55b013dfc2a 47 unsigned int is_connected : 1;
Azure.IoT Build 6:c55b013dfc2a 48 } HTTP_HANDLE_DATA;
Azure.IoT Build 6:c55b013dfc2a 49
AzureIoTClient 7:1af47e3a19b6 50 /*the following function does the same as sscanf(pos2, "%d", &sec)*/
AzureIoTClient 7:1af47e3a19b6 51 /*this function only exists because some of platforms do not have sscanf. */
AzureIoTClient 7:1af47e3a19b6 52 static int ParseStringToDecimal(const char *src, int* dst)
AzureIoTClient 7:1af47e3a19b6 53 {
AzureIoTClient 7:1af47e3a19b6 54 char* next;
AzureIoTClient 7:1af47e3a19b6 55 (*dst) = strtol(src, &next, 0);
AzureIoTClient 7:1af47e3a19b6 56 if ((src == next) || ((((*dst) == LONG_MAX) || ((*dst) == LONG_MIN)) && (errno != 0)))
AzureIoTClient 7:1af47e3a19b6 57 {
AzureIoTClient 7:1af47e3a19b6 58 return EOF;
AzureIoTClient 7:1af47e3a19b6 59 }
AzureIoTClient 7:1af47e3a19b6 60 return 1;
AzureIoTClient 7:1af47e3a19b6 61 }
AzureIoTClient 7:1af47e3a19b6 62
AzureIoTClient 7:1af47e3a19b6 63 /*the following function does the same as sscanf(pos2, "%x", &sec)*/
AzureIoTClient 7:1af47e3a19b6 64 /*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 65 #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 7:1af47e3a19b6 66 static int ParseStringToHexadecimal(const char *src, int* dst)
AzureIoTClient 7:1af47e3a19b6 67 {
AzureIoTClient 7:1af47e3a19b6 68 if (src == NULL)
AzureIoTClient 7:1af47e3a19b6 69 return EOF;
AzureIoTClient 7:1af47e3a19b6 70 if (HEXA_DIGIT_VAL(*src) == -1)
AzureIoTClient 7:1af47e3a19b6 71 return EOF;
AzureIoTClient 7:1af47e3a19b6 72
AzureIoTClient 7:1af47e3a19b6 73 int digitVal;
AzureIoTClient 7:1af47e3a19b6 74 (*dst) = 0;
AzureIoTClient 7:1af47e3a19b6 75 while ((digitVal = HEXA_DIGIT_VAL(*src)) != -1)
AzureIoTClient 7:1af47e3a19b6 76 {
AzureIoTClient 7:1af47e3a19b6 77 (*dst) *= 0x10;
AzureIoTClient 7:1af47e3a19b6 78 (*dst) += digitVal;
AzureIoTClient 7:1af47e3a19b6 79 src++;
AzureIoTClient 7:1af47e3a19b6 80 }
AzureIoTClient 7:1af47e3a19b6 81 return 1;
AzureIoTClient 7:1af47e3a19b6 82 }
AzureIoTClient 7:1af47e3a19b6 83
AzureIoTClient 7:1af47e3a19b6 84 /*the following function does the same as sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) */
AzureIoTClient 7:1af47e3a19b6 85 /*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 7:1af47e3a19b6 86 static int ParseHttpResponse(const char* src, int* dst)
AzureIoTClient 7:1af47e3a19b6 87 {
AzureIoTClient 7:1af47e3a19b6 88 const char* prefix = "HTTP/";
AzureIoTClient 7:1af47e3a19b6 89 while ((*prefix) != '\0')
AzureIoTClient 7:1af47e3a19b6 90 {
AzureIoTClient 7:1af47e3a19b6 91 if ((*prefix) != (*src))
AzureIoTClient 7:1af47e3a19b6 92 return EOF;
AzureIoTClient 7:1af47e3a19b6 93 prefix++;
AzureIoTClient 7:1af47e3a19b6 94 src++;
AzureIoTClient 7:1af47e3a19b6 95 }
AzureIoTClient 7:1af47e3a19b6 96
AzureIoTClient 7:1af47e3a19b6 97 while ((*src) != '.')
AzureIoTClient 7:1af47e3a19b6 98 {
AzureIoTClient 7:1af47e3a19b6 99 if ((*src) == '\0')
AzureIoTClient 7:1af47e3a19b6 100 return EOF;
AzureIoTClient 7:1af47e3a19b6 101 }
AzureIoTClient 7:1af47e3a19b6 102
AzureIoTClient 7:1af47e3a19b6 103 while ((*src) != ' ')
AzureIoTClient 7:1af47e3a19b6 104 {
AzureIoTClient 7:1af47e3a19b6 105 if ((*src) == '\0')
AzureIoTClient 7:1af47e3a19b6 106 return EOF;
AzureIoTClient 7:1af47e3a19b6 107 }
AzureIoTClient 7:1af47e3a19b6 108
AzureIoTClient 7:1af47e3a19b6 109 return ParseStringToDecimal(src, dst);
AzureIoTClient 7:1af47e3a19b6 110 }
AzureIoTClient 7:1af47e3a19b6 111
Azure.IoT Build 6:c55b013dfc2a 112 HTTPAPI_RESULT HTTPAPI_Init(void)
Azure.IoT Build 6:c55b013dfc2a 113 {
Azure.IoT Build 6:c55b013dfc2a 114 return HTTPAPI_OK;
Azure.IoT Build 6:c55b013dfc2a 115 }
Azure.IoT Build 6:c55b013dfc2a 116
Azure.IoT Build 6:c55b013dfc2a 117 void HTTPAPI_Deinit(void)
Azure.IoT Build 6:c55b013dfc2a 118 {
Azure.IoT Build 6:c55b013dfc2a 119 }
Azure.IoT Build 6:c55b013dfc2a 120
Azure.IoT Build 6:c55b013dfc2a 121 HTTP_HANDLE HTTPAPI_CreateConnection(const char* hostName)
Azure.IoT Build 6:c55b013dfc2a 122 {
Azure.IoT Build 6:c55b013dfc2a 123 HTTP_HANDLE_DATA* handle = NULL;
Azure.IoT Build 6:c55b013dfc2a 124
Azure.IoT Build 6:c55b013dfc2a 125 if (hostName)
Azure.IoT Build 6:c55b013dfc2a 126 {
Azure.IoT Build 6:c55b013dfc2a 127 handle = (HTTP_HANDLE_DATA*)malloc(sizeof(HTTP_HANDLE_DATA));
Azure.IoT Build 6:c55b013dfc2a 128 if (handle != NULL)
Azure.IoT Build 6:c55b013dfc2a 129 {
Azure.IoT Build 6:c55b013dfc2a 130 if (strcpy_s(handle->host, MAX_HOSTNAME, hostName) != 0)
Azure.IoT Build 6:c55b013dfc2a 131 {
Azure.IoT Build 6:c55b013dfc2a 132 LogError("HTTPAPI_CreateConnection::Could not strcpy_s");
Azure.IoT Build 6:c55b013dfc2a 133 free(handle);
Azure.IoT Build 6:c55b013dfc2a 134 handle = NULL;
Azure.IoT Build 6:c55b013dfc2a 135 }
Azure.IoT Build 6:c55b013dfc2a 136 else
Azure.IoT Build 6:c55b013dfc2a 137 {
Azure.IoT Build 6:c55b013dfc2a 138 TLSIO_CONFIG tlsio_config = { hostName, 443 };
Azure.IoT Build 6:c55b013dfc2a 139 handle->xio_handle = xio_create(platform_get_default_tlsio(), (void*)&tlsio_config);
Azure.IoT Build 6:c55b013dfc2a 140 if (handle->xio_handle == NULL)
Azure.IoT Build 6:c55b013dfc2a 141 {
Azure.IoT Build 6:c55b013dfc2a 142 LogError("HTTPAPI_CreateConnection::xio_create failed");
Azure.IoT Build 6:c55b013dfc2a 143 free(handle->host);
Azure.IoT Build 6:c55b013dfc2a 144 free(handle);
Azure.IoT Build 6:c55b013dfc2a 145 handle = NULL;
Azure.IoT Build 6:c55b013dfc2a 146 }
Azure.IoT Build 6:c55b013dfc2a 147 else
Azure.IoT Build 6:c55b013dfc2a 148 {
Azure.IoT Build 6:c55b013dfc2a 149 handle->is_connected = 0;
Azure.IoT Build 6:c55b013dfc2a 150 handle->is_io_error = 0;
Azure.IoT Build 6:c55b013dfc2a 151 handle->received_bytes_count = 0;
Azure.IoT Build 6:c55b013dfc2a 152 handle->received_bytes = NULL;
Azure.IoT Build 6:c55b013dfc2a 153 handle->send_all_result = SEND_ALL_RESULT_NOT_STARTED;
Azure.IoT Build 6:c55b013dfc2a 154 handle->certificate = NULL;
Azure.IoT Build 6:c55b013dfc2a 155 }
Azure.IoT Build 6:c55b013dfc2a 156 }
Azure.IoT Build 6:c55b013dfc2a 157 }
Azure.IoT Build 6:c55b013dfc2a 158 }
Azure.IoT Build 6:c55b013dfc2a 159 else
Azure.IoT Build 6:c55b013dfc2a 160 {
Azure.IoT Build 6:c55b013dfc2a 161 LogInfo("HTTPAPI_CreateConnection:: null hostName parameter");
Azure.IoT Build 6:c55b013dfc2a 162 }
Azure.IoT Build 6:c55b013dfc2a 163
Azure.IoT Build 6:c55b013dfc2a 164 return (HTTP_HANDLE)handle;
Azure.IoT Build 6:c55b013dfc2a 165 }
Azure.IoT Build 6:c55b013dfc2a 166
Azure.IoT Build 6:c55b013dfc2a 167 void HTTPAPI_CloseConnection(HTTP_HANDLE handle)
Azure.IoT Build 6:c55b013dfc2a 168 {
Azure.IoT Build 6:c55b013dfc2a 169 HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)handle;
Azure.IoT Build 6:c55b013dfc2a 170
Azure.IoT Build 6:c55b013dfc2a 171 if (h)
Azure.IoT Build 6:c55b013dfc2a 172 {
Azure.IoT Build 6:c55b013dfc2a 173 if (h->xio_handle != NULL)
Azure.IoT Build 6:c55b013dfc2a 174 {
Azure.IoT Build 6:c55b013dfc2a 175 LogInfo("HTTPAPI_CloseConnection xio_destroy(); to %s", h->host);
Azure.IoT Build 6:c55b013dfc2a 176 xio_destroy(h->xio_handle);
Azure.IoT Build 6:c55b013dfc2a 177 }
Azure.IoT Build 6:c55b013dfc2a 178
Azure.IoT Build 6:c55b013dfc2a 179 if (h->certificate)
Azure.IoT Build 6:c55b013dfc2a 180 {
Azure.IoT Build 6:c55b013dfc2a 181 free(h->certificate);
Azure.IoT Build 6:c55b013dfc2a 182 }
Azure.IoT Build 6:c55b013dfc2a 183
Azure.IoT Build 6:c55b013dfc2a 184 free(h);
Azure.IoT Build 6:c55b013dfc2a 185 }
Azure.IoT Build 6:c55b013dfc2a 186 }
Azure.IoT Build 6:c55b013dfc2a 187
Azure.IoT Build 6:c55b013dfc2a 188 static void on_io_open_complete(void* context, IO_OPEN_RESULT open_result)
Azure.IoT Build 6:c55b013dfc2a 189 {
Azure.IoT Build 6:c55b013dfc2a 190 HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)context;
Azure.IoT Build 6:c55b013dfc2a 191 if (open_result == IO_OPEN_OK)
Azure.IoT Build 6:c55b013dfc2a 192 {
Azure.IoT Build 6:c55b013dfc2a 193 h->is_connected = 1;
Azure.IoT Build 6:c55b013dfc2a 194 h->is_io_error = 0;
Azure.IoT Build 6:c55b013dfc2a 195 }
Azure.IoT Build 6:c55b013dfc2a 196 else
Azure.IoT Build 6:c55b013dfc2a 197 {
Azure.IoT Build 6:c55b013dfc2a 198 h->is_io_error = 1;
Azure.IoT Build 6:c55b013dfc2a 199 }
Azure.IoT Build 6:c55b013dfc2a 200 }
Azure.IoT Build 6:c55b013dfc2a 201
Azure.IoT Build 6:c55b013dfc2a 202 static int my_strnicmp(const char* s1, const char* s2, size_t n)
Azure.IoT Build 6:c55b013dfc2a 203 {
Azure.IoT Build 6:c55b013dfc2a 204 size_t i;
Azure.IoT Build 6:c55b013dfc2a 205 int result = 0;
Azure.IoT Build 6:c55b013dfc2a 206
Azure.IoT Build 6:c55b013dfc2a 207 for (i = 0; i < n; i++)
Azure.IoT Build 6:c55b013dfc2a 208 {
Azure.IoT Build 6:c55b013dfc2a 209 /* compute the difference between the chars */
Azure.IoT Build 6:c55b013dfc2a 210 result = tolower(s1[i]) - tolower(s2[i]);
Azure.IoT Build 6:c55b013dfc2a 211
Azure.IoT Build 6:c55b013dfc2a 212 /* break if we have a difference ... */
Azure.IoT Build 6:c55b013dfc2a 213 if ((result != 0) ||
Azure.IoT Build 6:c55b013dfc2a 214 /* ... or if we got to the end of one the strings */
Azure.IoT Build 6:c55b013dfc2a 215 (s1[i] == '\0') || (s2[i] == '\0'))
Azure.IoT Build 6:c55b013dfc2a 216 {
Azure.IoT Build 6:c55b013dfc2a 217 break;
Azure.IoT Build 6:c55b013dfc2a 218 }
Azure.IoT Build 6:c55b013dfc2a 219 }
Azure.IoT Build 6:c55b013dfc2a 220
Azure.IoT Build 6:c55b013dfc2a 221 return result;
Azure.IoT Build 6:c55b013dfc2a 222 }
Azure.IoT Build 6:c55b013dfc2a 223
Azure.IoT Build 6:c55b013dfc2a 224 static int my_stricmp(const char* s1, const char* s2)
Azure.IoT Build 6:c55b013dfc2a 225 {
Azure.IoT Build 6:c55b013dfc2a 226 size_t i = 0;
Azure.IoT Build 6:c55b013dfc2a 227
Azure.IoT Build 6:c55b013dfc2a 228 while ((s1[i] != '\0') && (s2[i] != '\0'))
Azure.IoT Build 6:c55b013dfc2a 229 {
Azure.IoT Build 6:c55b013dfc2a 230 /* break if we have a difference ... */
Azure.IoT Build 6:c55b013dfc2a 231 if (tolower(s1[i]) != tolower(s2[i]))
Azure.IoT Build 6:c55b013dfc2a 232 {
Azure.IoT Build 6:c55b013dfc2a 233 break;
Azure.IoT Build 6:c55b013dfc2a 234 }
Azure.IoT Build 6:c55b013dfc2a 235
Azure.IoT Build 6:c55b013dfc2a 236 i++;
Azure.IoT Build 6:c55b013dfc2a 237 }
Azure.IoT Build 6:c55b013dfc2a 238
Azure.IoT Build 6:c55b013dfc2a 239 /* if we broke because we are at end of string this will yield 0 */
Azure.IoT Build 6:c55b013dfc2a 240 /* if we broke because there was a difference this will yield non-zero */
Azure.IoT Build 6:c55b013dfc2a 241 return tolower(s1[i]) - tolower(s2[i]);
Azure.IoT Build 6:c55b013dfc2a 242 }
Azure.IoT Build 6:c55b013dfc2a 243
Azure.IoT Build 6:c55b013dfc2a 244 static void on_bytes_received(void* context, const unsigned char* buffer, size_t size)
Azure.IoT Build 6:c55b013dfc2a 245 {
Azure.IoT Build 6:c55b013dfc2a 246 HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)context;
Azure.IoT Build 6:c55b013dfc2a 247
Azure.IoT Build 6:c55b013dfc2a 248 /* Here we got some bytes so we'll buffer them so the receive functions can consumer it */
Azure.IoT Build 6:c55b013dfc2a 249 unsigned char* new_received_bytes = (unsigned char*)realloc(h->received_bytes, h->received_bytes_count + size);
Azure.IoT Build 6:c55b013dfc2a 250 if (new_received_bytes == NULL)
Azure.IoT Build 6:c55b013dfc2a 251 {
Azure.IoT Build 6:c55b013dfc2a 252 h->is_io_error = 1;
Azure.IoT Build 6:c55b013dfc2a 253 LogError("on_bytes_received: Error allocating memory for received data");
Azure.IoT Build 6:c55b013dfc2a 254 }
Azure.IoT Build 6:c55b013dfc2a 255 else
Azure.IoT Build 6:c55b013dfc2a 256 {
Azure.IoT Build 6:c55b013dfc2a 257 h->received_bytes = new_received_bytes;
Azure.IoT Build 6:c55b013dfc2a 258 (void)memcpy(h->received_bytes + h->received_bytes_count, buffer, size);
Azure.IoT Build 6:c55b013dfc2a 259 h->received_bytes_count += size;
Azure.IoT Build 6:c55b013dfc2a 260 }
Azure.IoT Build 6:c55b013dfc2a 261 }
Azure.IoT Build 6:c55b013dfc2a 262
Azure.IoT Build 6:c55b013dfc2a 263 static void on_io_error(void* context)
Azure.IoT Build 6:c55b013dfc2a 264 {
Azure.IoT Build 6:c55b013dfc2a 265 HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)context;
Azure.IoT Build 6:c55b013dfc2a 266 h->is_io_error = 1;
Azure.IoT Build 6:c55b013dfc2a 267 LogError("on_io_error: Error signalled by underlying IO");
Azure.IoT Build 6:c55b013dfc2a 268 }
Azure.IoT Build 6:c55b013dfc2a 269
Azure.IoT Build 6:c55b013dfc2a 270 static int conn_receive(HTTP_HANDLE_DATA* http_instance, char* buffer, int count)
Azure.IoT Build 6:c55b013dfc2a 271 {
Azure.IoT Build 6:c55b013dfc2a 272 int result = 0;
Azure.IoT Build 6:c55b013dfc2a 273
Azure.IoT Build 6:c55b013dfc2a 274 if (count < 0)
Azure.IoT Build 6:c55b013dfc2a 275 {
Azure.IoT Build 6:c55b013dfc2a 276 result = -1;
Azure.IoT Build 6:c55b013dfc2a 277 }
Azure.IoT Build 6:c55b013dfc2a 278 else
Azure.IoT Build 6:c55b013dfc2a 279 {
Azure.IoT Build 6:c55b013dfc2a 280 while (result < count)
Azure.IoT Build 6:c55b013dfc2a 281 {
Azure.IoT Build 6:c55b013dfc2a 282 xio_dowork(http_instance->xio_handle);
Azure.IoT Build 6:c55b013dfc2a 283
Azure.IoT Build 6:c55b013dfc2a 284 /* if any error was detected while receiving then simply break and report it */
Azure.IoT Build 6:c55b013dfc2a 285 if (http_instance->is_io_error != 0)
Azure.IoT Build 6:c55b013dfc2a 286 {
Azure.IoT Build 6:c55b013dfc2a 287 result = -1;
Azure.IoT Build 6:c55b013dfc2a 288 break;
Azure.IoT Build 6:c55b013dfc2a 289 }
Azure.IoT Build 6:c55b013dfc2a 290
Azure.IoT Build 6:c55b013dfc2a 291 if (http_instance->received_bytes_count >= (size_t)count)
Azure.IoT Build 6:c55b013dfc2a 292 {
Azure.IoT Build 6:c55b013dfc2a 293 /* Consuming bytes from the receive buffer */
Azure.IoT Build 6:c55b013dfc2a 294 (void)memcpy(buffer, http_instance->received_bytes, count);
Azure.IoT Build 6:c55b013dfc2a 295 (void)memmove(http_instance->received_bytes, http_instance->received_bytes + count, http_instance->received_bytes_count - count);
Azure.IoT Build 6:c55b013dfc2a 296 http_instance->received_bytes_count -= count;
Azure.IoT Build 6:c55b013dfc2a 297
Azure.IoT Build 6:c55b013dfc2a 298 /* we're not reallocating at each consumption so that we don't trash due to byte by byte consumption */
Azure.IoT Build 6:c55b013dfc2a 299 if (http_instance->received_bytes_count == 0)
Azure.IoT Build 6:c55b013dfc2a 300 {
Azure.IoT Build 6:c55b013dfc2a 301 free(http_instance->received_bytes);
Azure.IoT Build 6:c55b013dfc2a 302 http_instance->received_bytes = NULL;
Azure.IoT Build 6:c55b013dfc2a 303 }
Azure.IoT Build 6:c55b013dfc2a 304
Azure.IoT Build 6:c55b013dfc2a 305 result = count;
Azure.IoT Build 6:c55b013dfc2a 306 break;
Azure.IoT Build 6:c55b013dfc2a 307 }
Azure.IoT Build 6:c55b013dfc2a 308
Azure.IoT Build 6:c55b013dfc2a 309 ThreadAPI_Sleep(1);
Azure.IoT Build 6:c55b013dfc2a 310 }
Azure.IoT Build 6:c55b013dfc2a 311 }
Azure.IoT Build 6:c55b013dfc2a 312
Azure.IoT Build 6:c55b013dfc2a 313 return result;
Azure.IoT Build 6:c55b013dfc2a 314 }
Azure.IoT Build 6:c55b013dfc2a 315
Azure.IoT Build 6:c55b013dfc2a 316 static void on_send_complete(void* context, IO_SEND_RESULT send_result)
Azure.IoT Build 6:c55b013dfc2a 317 {
Azure.IoT Build 6:c55b013dfc2a 318 /* If a send is complete we'll simply signal this by changing the send all state */
Azure.IoT Build 6:c55b013dfc2a 319 HTTP_HANDLE_DATA* http_instance = (HTTP_HANDLE_DATA*)context;
Azure.IoT Build 6:c55b013dfc2a 320 if (send_result == IO_SEND_OK)
Azure.IoT Build 6:c55b013dfc2a 321 {
Azure.IoT Build 6:c55b013dfc2a 322 http_instance->send_all_result = SEND_ALL_RESULT_OK;
Azure.IoT Build 6:c55b013dfc2a 323 }
Azure.IoT Build 6:c55b013dfc2a 324 else
Azure.IoT Build 6:c55b013dfc2a 325 {
Azure.IoT Build 6:c55b013dfc2a 326 http_instance->send_all_result = SEND_ALL_RESULT_ERROR;
Azure.IoT Build 6:c55b013dfc2a 327 }
Azure.IoT Build 6:c55b013dfc2a 328 }
Azure.IoT Build 6:c55b013dfc2a 329
Azure.IoT Build 6:c55b013dfc2a 330 static int conn_send_all(HTTP_HANDLE_DATA* http_instance, char* buffer, int count)
Azure.IoT Build 6:c55b013dfc2a 331 {
Azure.IoT Build 6:c55b013dfc2a 332 int result;
Azure.IoT Build 6:c55b013dfc2a 333
Azure.IoT Build 6:c55b013dfc2a 334 if (count < 0)
Azure.IoT Build 6:c55b013dfc2a 335 {
Azure.IoT Build 6:c55b013dfc2a 336 result = -1;
Azure.IoT Build 6:c55b013dfc2a 337 }
Azure.IoT Build 6:c55b013dfc2a 338 else
Azure.IoT Build 6:c55b013dfc2a 339 {
Azure.IoT Build 6:c55b013dfc2a 340 http_instance->send_all_result = SEND_ALL_RESULT_PENDING;
Azure.IoT Build 6:c55b013dfc2a 341 if (xio_send(http_instance->xio_handle, buffer, count, on_send_complete, http_instance) != 0)
Azure.IoT Build 6:c55b013dfc2a 342 {
Azure.IoT Build 6:c55b013dfc2a 343 result = -1;
Azure.IoT Build 6:c55b013dfc2a 344 }
Azure.IoT Build 6:c55b013dfc2a 345 else
Azure.IoT Build 6:c55b013dfc2a 346 {
Azure.IoT Build 6:c55b013dfc2a 347 /* We have to loop in here until all bytes are sent or we encounter an error. */
Azure.IoT Build 6:c55b013dfc2a 348 while (1)
Azure.IoT Build 6:c55b013dfc2a 349 {
Azure.IoT Build 6:c55b013dfc2a 350 xio_dowork(http_instance->xio_handle);
Azure.IoT Build 6:c55b013dfc2a 351
Azure.IoT Build 6:c55b013dfc2a 352 /* If we got an error signalled from the underlying IO we simply report it up */
Azure.IoT Build 6:c55b013dfc2a 353 if (http_instance->is_io_error)
Azure.IoT Build 6:c55b013dfc2a 354 {
Azure.IoT Build 6:c55b013dfc2a 355 http_instance->send_all_result = SEND_ALL_RESULT_ERROR;
Azure.IoT Build 6:c55b013dfc2a 356 break;
Azure.IoT Build 6:c55b013dfc2a 357 }
Azure.IoT Build 6:c55b013dfc2a 358
Azure.IoT Build 6:c55b013dfc2a 359 if (http_instance->send_all_result != SEND_ALL_RESULT_PENDING)
Azure.IoT Build 6:c55b013dfc2a 360 {
Azure.IoT Build 6:c55b013dfc2a 361 break;
Azure.IoT Build 6:c55b013dfc2a 362 }
Azure.IoT Build 6:c55b013dfc2a 363
Azure.IoT Build 6:c55b013dfc2a 364 /* We yield the CPU for a bit so others can do their work */
Azure.IoT Build 6:c55b013dfc2a 365 ThreadAPI_Sleep(1);
Azure.IoT Build 6:c55b013dfc2a 366 }
Azure.IoT Build 6:c55b013dfc2a 367
Azure.IoT Build 6:c55b013dfc2a 368 /* The send_all_result indicates what is the status for the send operation.
Azure.IoT Build 6:c55b013dfc2a 369 Not started - means nothing should happen since no send was started
Azure.IoT Build 6:c55b013dfc2a 370 Pending - a send was started, but it is still being carried out
Azure.IoT Build 6:c55b013dfc2a 371 Ok - Send complete
Azure.IoT Build 6:c55b013dfc2a 372 Error - error */
Azure.IoT Build 6:c55b013dfc2a 373 switch (http_instance->send_all_result)
Azure.IoT Build 6:c55b013dfc2a 374 {
Azure.IoT Build 6:c55b013dfc2a 375 default:
Azure.IoT Build 6:c55b013dfc2a 376 case SEND_ALL_RESULT_NOT_STARTED:
Azure.IoT Build 6:c55b013dfc2a 377 result = -1;
Azure.IoT Build 6:c55b013dfc2a 378 break;
Azure.IoT Build 6:c55b013dfc2a 379
Azure.IoT Build 6:c55b013dfc2a 380 case SEND_ALL_RESULT_OK:
Azure.IoT Build 6:c55b013dfc2a 381 result = count;
Azure.IoT Build 6:c55b013dfc2a 382 break;
Azure.IoT Build 6:c55b013dfc2a 383
Azure.IoT Build 6:c55b013dfc2a 384 case SEND_ALL_RESULT_ERROR:
Azure.IoT Build 6:c55b013dfc2a 385 result = -1;
Azure.IoT Build 6:c55b013dfc2a 386 break;
Azure.IoT Build 6:c55b013dfc2a 387 }
Azure.IoT Build 6:c55b013dfc2a 388 }
Azure.IoT Build 6:c55b013dfc2a 389 }
Azure.IoT Build 6:c55b013dfc2a 390
Azure.IoT Build 6:c55b013dfc2a 391 return result;
Azure.IoT Build 6:c55b013dfc2a 392 }
Azure.IoT Build 6:c55b013dfc2a 393
Azure.IoT Build 6:c55b013dfc2a 394 static int readLine(HTTP_HANDLE_DATA* http_instance, char* buf, const size_t size)
Azure.IoT Build 6:c55b013dfc2a 395 {
Azure.IoT Build 6:c55b013dfc2a 396 // reads until \r\n is encountered. writes in buf all the characters
Azure.IoT Build 6:c55b013dfc2a 397 char* p = buf;
Azure.IoT Build 6:c55b013dfc2a 398 char c;
Azure.IoT Build 6:c55b013dfc2a 399 if (conn_receive(http_instance, &c, 1) < 0)
Azure.IoT Build 6:c55b013dfc2a 400 return -1;
Azure.IoT Build 6:c55b013dfc2a 401 while (c != '\r') {
Azure.IoT Build 6:c55b013dfc2a 402 if ((p - buf + 1) >= (int)size)
Azure.IoT Build 6:c55b013dfc2a 403 return -1;
Azure.IoT Build 6:c55b013dfc2a 404 *p++ = c;
Azure.IoT Build 6:c55b013dfc2a 405 if (conn_receive(http_instance, &c, 1) < 0)
Azure.IoT Build 6:c55b013dfc2a 406 return -1;
Azure.IoT Build 6:c55b013dfc2a 407 }
Azure.IoT Build 6:c55b013dfc2a 408 *p = 0;
Azure.IoT Build 6:c55b013dfc2a 409 if (conn_receive(http_instance, &c, 1) < 0 || c != '\n') // skip \n
Azure.IoT Build 6:c55b013dfc2a 410 return -1;
Azure.IoT Build 6:c55b013dfc2a 411 return p - buf;
Azure.IoT Build 6:c55b013dfc2a 412 }
Azure.IoT Build 6:c55b013dfc2a 413
Azure.IoT Build 6:c55b013dfc2a 414 static int readChunk(HTTP_HANDLE_DATA* http_instance, char* buf, size_t size)
Azure.IoT Build 6:c55b013dfc2a 415 {
Azure.IoT Build 6:c55b013dfc2a 416 size_t cur, offset;
Azure.IoT Build 6:c55b013dfc2a 417
Azure.IoT Build 6:c55b013dfc2a 418 // read content with specified length, even if it is received
Azure.IoT Build 6:c55b013dfc2a 419 // only in chunks due to fragmentation in the networking layer.
Azure.IoT Build 6:c55b013dfc2a 420 // returns -1 in case of error.
Azure.IoT Build 6:c55b013dfc2a 421 offset = 0;
Azure.IoT Build 6:c55b013dfc2a 422 while (size > 0)
Azure.IoT Build 6:c55b013dfc2a 423 {
Azure.IoT Build 6:c55b013dfc2a 424 cur = conn_receive(http_instance, buf + offset, size);
Azure.IoT Build 6:c55b013dfc2a 425
Azure.IoT Build 6:c55b013dfc2a 426 // end of stream reached
Azure.IoT Build 6:c55b013dfc2a 427 if (cur == 0)
Azure.IoT Build 6:c55b013dfc2a 428 return offset;
Azure.IoT Build 6:c55b013dfc2a 429
Azure.IoT Build 6:c55b013dfc2a 430 // read cur bytes (might be less than requested)
Azure.IoT Build 6:c55b013dfc2a 431 size -= cur;
Azure.IoT Build 6:c55b013dfc2a 432 offset += cur;
Azure.IoT Build 6:c55b013dfc2a 433 }
Azure.IoT Build 6:c55b013dfc2a 434
Azure.IoT Build 6:c55b013dfc2a 435 return offset;
Azure.IoT Build 6:c55b013dfc2a 436 }
Azure.IoT Build 6:c55b013dfc2a 437
Azure.IoT Build 6:c55b013dfc2a 438 static int skipN(HTTP_HANDLE_DATA* http_instance, size_t n, char* buf, size_t size)
Azure.IoT Build 6:c55b013dfc2a 439 {
Azure.IoT Build 6:c55b013dfc2a 440 size_t org = n;
Azure.IoT Build 6:c55b013dfc2a 441 // read and abandon response content with specified length
Azure.IoT Build 6:c55b013dfc2a 442 // returns -1 in case of error.
Azure.IoT Build 6:c55b013dfc2a 443 while (n > size)
Azure.IoT Build 6:c55b013dfc2a 444 {
Azure.IoT Build 6:c55b013dfc2a 445 if (readChunk(http_instance, (char*)buf, size) < 0)
Azure.IoT Build 6:c55b013dfc2a 446 return -1;
Azure.IoT Build 6:c55b013dfc2a 447
Azure.IoT Build 6:c55b013dfc2a 448 n -= size;
Azure.IoT Build 6:c55b013dfc2a 449 }
Azure.IoT Build 6:c55b013dfc2a 450
Azure.IoT Build 6:c55b013dfc2a 451 if (readChunk(http_instance, (char*)buf, n) < 0)
Azure.IoT Build 6:c55b013dfc2a 452 return -1;
Azure.IoT Build 6:c55b013dfc2a 453
Azure.IoT Build 6:c55b013dfc2a 454 return org;
Azure.IoT Build 6:c55b013dfc2a 455 }
Azure.IoT Build 6:c55b013dfc2a 456
Azure.IoT Build 6:c55b013dfc2a 457 //Note: This function assumes that "Host:" and "Content-Length:" headers are setup
Azure.IoT Build 6:c55b013dfc2a 458 // by the caller of HTTPAPI_ExecuteRequest() (which is true for httptransport.c).
Azure.IoT Build 6:c55b013dfc2a 459 HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath,
Azure.IoT Build 6:c55b013dfc2a 460 HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content,
Azure.IoT Build 6:c55b013dfc2a 461 size_t contentLength, unsigned int* statusCode,
Azure.IoT Build 6:c55b013dfc2a 462 HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
Azure.IoT Build 6:c55b013dfc2a 463 {
Azure.IoT Build 6:c55b013dfc2a 464
Azure.IoT Build 6:c55b013dfc2a 465 HTTPAPI_RESULT result;
Azure.IoT Build 6:c55b013dfc2a 466 size_t headersCount;
Azure.IoT Build 6:c55b013dfc2a 467 char buf[TEMP_BUFFER_SIZE];
Azure.IoT Build 6:c55b013dfc2a 468 int ret;
Azure.IoT Build 6:c55b013dfc2a 469 size_t bodyLength = 0;
Azure.IoT Build 6:c55b013dfc2a 470 bool chunked = false;
Azure.IoT Build 6:c55b013dfc2a 471 const unsigned char* receivedContent;
Azure.IoT Build 6:c55b013dfc2a 472
Azure.IoT Build 6:c55b013dfc2a 473 const char* method = (requestType == HTTPAPI_REQUEST_GET) ? "GET"
Azure.IoT Build 6:c55b013dfc2a 474 : (requestType == HTTPAPI_REQUEST_POST) ? "POST"
Azure.IoT Build 6:c55b013dfc2a 475 : (requestType == HTTPAPI_REQUEST_PUT) ? "PUT"
Azure.IoT Build 6:c55b013dfc2a 476 : (requestType == HTTPAPI_REQUEST_DELETE) ? "DELETE"
Azure.IoT Build 6:c55b013dfc2a 477 : (requestType == HTTPAPI_REQUEST_PATCH) ? "PATCH"
Azure.IoT Build 6:c55b013dfc2a 478 : NULL;
Azure.IoT Build 6:c55b013dfc2a 479
Azure.IoT Build 6:c55b013dfc2a 480 if (handle == NULL ||
Azure.IoT Build 6:c55b013dfc2a 481 relativePath == NULL ||
Azure.IoT Build 6:c55b013dfc2a 482 httpHeadersHandle == NULL ||
Azure.IoT Build 6:c55b013dfc2a 483 method == NULL ||
Azure.IoT Build 6:c55b013dfc2a 484 HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK)
Azure.IoT Build 6:c55b013dfc2a 485 {
Azure.IoT Build 6:c55b013dfc2a 486 result = HTTPAPI_INVALID_ARG;
Azure.IoT Build 6:c55b013dfc2a 487 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 488 goto exit;
Azure.IoT Build 6:c55b013dfc2a 489 }
Azure.IoT Build 6:c55b013dfc2a 490
Azure.IoT Build 6:c55b013dfc2a 491 HTTP_HANDLE_DATA* httpHandle = (HTTP_HANDLE_DATA*)handle;
Azure.IoT Build 6:c55b013dfc2a 492
Azure.IoT Build 6:c55b013dfc2a 493 if (handle->is_connected == 0)
Azure.IoT Build 6:c55b013dfc2a 494 {
Azure.IoT Build 6:c55b013dfc2a 495 // Load the certificate
Azure.IoT Build 6:c55b013dfc2a 496 if ((httpHandle->certificate != NULL) &&
Azure.IoT Build 6:c55b013dfc2a 497 (xio_setoption(httpHandle->xio_handle, "TrustedCerts", httpHandle->certificate) != 0))
Azure.IoT Build 6:c55b013dfc2a 498 {
Azure.IoT Build 6:c55b013dfc2a 499 result = HTTPAPI_ERROR;
Azure.IoT Build 6:c55b013dfc2a 500 LogError("Could not load certificate (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 501 goto exit;
Azure.IoT Build 6:c55b013dfc2a 502 }
Azure.IoT Build 6:c55b013dfc2a 503
Azure.IoT Build 6:c55b013dfc2a 504 // Make the connection
Azure.IoT Build 6:c55b013dfc2a 505 if (xio_open(httpHandle->xio_handle, on_io_open_complete, httpHandle, on_bytes_received, httpHandle, on_io_error, httpHandle) != 0)
Azure.IoT Build 6:c55b013dfc2a 506 {
Azure.IoT Build 6:c55b013dfc2a 507 result = HTTPAPI_ERROR;
Azure.IoT Build 6:c55b013dfc2a 508 LogError("Could not connect (result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 509 goto exit;
Azure.IoT Build 6:c55b013dfc2a 510 }
Azure.IoT Build 6:c55b013dfc2a 511
Azure.IoT Build 6:c55b013dfc2a 512 while (1)
Azure.IoT Build 6:c55b013dfc2a 513 {
Azure.IoT Build 6:c55b013dfc2a 514 xio_dowork(httpHandle->xio_handle);
Azure.IoT Build 6:c55b013dfc2a 515 if ((handle->is_connected == 1) ||
Azure.IoT Build 6:c55b013dfc2a 516 (handle->is_io_error == 1))
Azure.IoT Build 6:c55b013dfc2a 517 {
Azure.IoT Build 6:c55b013dfc2a 518 break;
Azure.IoT Build 6:c55b013dfc2a 519 }
Azure.IoT Build 6:c55b013dfc2a 520
Azure.IoT Build 6:c55b013dfc2a 521 ThreadAPI_Sleep(1);
Azure.IoT Build 6:c55b013dfc2a 522 }
Azure.IoT Build 6:c55b013dfc2a 523 }
Azure.IoT Build 6:c55b013dfc2a 524
Azure.IoT Build 6:c55b013dfc2a 525 //Send request
Azure.IoT Build 6:c55b013dfc2a 526 if ((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", method, relativePath)) < 0
Azure.IoT Build 6:c55b013dfc2a 527 || ret >= sizeof(buf))
Azure.IoT Build 6:c55b013dfc2a 528 {
Azure.IoT Build 6:c55b013dfc2a 529 result = HTTPAPI_STRING_PROCESSING_ERROR;
Azure.IoT Build 6:c55b013dfc2a 530 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 531 goto exit;
Azure.IoT Build 6:c55b013dfc2a 532 }
Azure.IoT Build 6:c55b013dfc2a 533 if (conn_send_all(httpHandle, buf, strlen(buf)) < 0)
Azure.IoT Build 6:c55b013dfc2a 534 {
Azure.IoT Build 6:c55b013dfc2a 535 result = HTTPAPI_SEND_REQUEST_FAILED;
Azure.IoT Build 6:c55b013dfc2a 536 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 537 goto exit;
Azure.IoT Build 6:c55b013dfc2a 538 }
Azure.IoT Build 6:c55b013dfc2a 539
Azure.IoT Build 6:c55b013dfc2a 540 //Send default headers
Azure.IoT Build 6:c55b013dfc2a 541 for (size_t i = 0; i < headersCount; i++)
Azure.IoT Build 6:c55b013dfc2a 542 {
Azure.IoT Build 6:c55b013dfc2a 543 char* header;
Azure.IoT Build 6:c55b013dfc2a 544 if (HTTPHeaders_GetHeader(httpHeadersHandle, i, &header) != HTTP_HEADERS_OK)
Azure.IoT Build 6:c55b013dfc2a 545 {
Azure.IoT Build 6:c55b013dfc2a 546 result = HTTPAPI_HTTP_HEADERS_FAILED;
Azure.IoT Build 6:c55b013dfc2a 547 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 548 goto exit;
Azure.IoT Build 6:c55b013dfc2a 549 }
Azure.IoT Build 6:c55b013dfc2a 550 if (conn_send_all(httpHandle, header, strlen(header)) < 0)
Azure.IoT Build 6:c55b013dfc2a 551 {
Azure.IoT Build 6:c55b013dfc2a 552 result = HTTPAPI_SEND_REQUEST_FAILED;
Azure.IoT Build 6:c55b013dfc2a 553 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 554 free(header);
Azure.IoT Build 6:c55b013dfc2a 555 goto exit;
Azure.IoT Build 6:c55b013dfc2a 556 }
Azure.IoT Build 6:c55b013dfc2a 557 if (conn_send_all(httpHandle, "\r\n", 2) < 0)
Azure.IoT Build 6:c55b013dfc2a 558 {
Azure.IoT Build 6:c55b013dfc2a 559 result = HTTPAPI_SEND_REQUEST_FAILED;
Azure.IoT Build 6:c55b013dfc2a 560 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 561 free(header);
Azure.IoT Build 6:c55b013dfc2a 562 goto exit;
Azure.IoT Build 6:c55b013dfc2a 563 }
Azure.IoT Build 6:c55b013dfc2a 564 free(header);
Azure.IoT Build 6:c55b013dfc2a 565 }
Azure.IoT Build 6:c55b013dfc2a 566
Azure.IoT Build 6:c55b013dfc2a 567 //Close headers
Azure.IoT Build 6:c55b013dfc2a 568 if (conn_send_all(httpHandle, "\r\n", 2) < 0)
Azure.IoT Build 6:c55b013dfc2a 569 {
Azure.IoT Build 6:c55b013dfc2a 570 result = HTTPAPI_SEND_REQUEST_FAILED;
Azure.IoT Build 6:c55b013dfc2a 571 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 572 goto exit;
Azure.IoT Build 6:c55b013dfc2a 573 }
Azure.IoT Build 6:c55b013dfc2a 574
Azure.IoT Build 6:c55b013dfc2a 575 //Send data (if available)
Azure.IoT Build 6:c55b013dfc2a 576 if (content && contentLength > 0)
Azure.IoT Build 6:c55b013dfc2a 577 {
Azure.IoT Build 6:c55b013dfc2a 578 if (conn_send_all(httpHandle, (char*)content, contentLength) < 0)
Azure.IoT Build 6:c55b013dfc2a 579 {
Azure.IoT Build 6:c55b013dfc2a 580 result = HTTPAPI_SEND_REQUEST_FAILED;
Azure.IoT Build 6:c55b013dfc2a 581 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 582 goto exit;
Azure.IoT Build 6:c55b013dfc2a 583 }
Azure.IoT Build 6:c55b013dfc2a 584 }
Azure.IoT Build 6:c55b013dfc2a 585
Azure.IoT Build 6:c55b013dfc2a 586 //Receive response
Azure.IoT Build 6:c55b013dfc2a 587 if (readLine(httpHandle, buf, sizeof(buf)) < 0)
Azure.IoT Build 6:c55b013dfc2a 588 {
Azure.IoT Build 6:c55b013dfc2a 589 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 590 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 591 goto exit;
Azure.IoT Build 6:c55b013dfc2a 592 }
Azure.IoT Build 6:c55b013dfc2a 593
Azure.IoT Build 6:c55b013dfc2a 594 //Parse HTTP response
AzureIoTClient 7:1af47e3a19b6 595 if (ParseHttpResponse(buf, &ret) != 1)
Azure.IoT Build 6:c55b013dfc2a 596 {
Azure.IoT Build 6:c55b013dfc2a 597 //Cannot match string, error
Azure.IoT Build 6:c55b013dfc2a 598 LogInfo("HTTPAPI_ExecuteRequest::Not a correct HTTP answer=%s", buf);
Azure.IoT Build 6:c55b013dfc2a 599 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 600 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 601 goto exit;
Azure.IoT Build 6:c55b013dfc2a 602 }
Azure.IoT Build 6:c55b013dfc2a 603 if (statusCode)
Azure.IoT Build 6:c55b013dfc2a 604 *statusCode = ret;
Azure.IoT Build 6:c55b013dfc2a 605
Azure.IoT Build 6:c55b013dfc2a 606 //Read HTTP response headers
Azure.IoT Build 6:c55b013dfc2a 607 if (readLine(httpHandle, buf, sizeof(buf)) < 0)
Azure.IoT Build 6:c55b013dfc2a 608 {
Azure.IoT Build 6:c55b013dfc2a 609 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 610 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 611 goto exit;
Azure.IoT Build 6:c55b013dfc2a 612 }
Azure.IoT Build 6:c55b013dfc2a 613
Azure.IoT Build 6:c55b013dfc2a 614 while (buf[0])
Azure.IoT Build 6:c55b013dfc2a 615 {
Azure.IoT Build 6:c55b013dfc2a 616 const char ContentLength[] = "content-length:";
Azure.IoT Build 6:c55b013dfc2a 617 const char TransferEncoding[] = "transfer-encoding:";
Azure.IoT Build 6:c55b013dfc2a 618
Azure.IoT Build 6:c55b013dfc2a 619 if (my_strnicmp(buf, ContentLength, CHAR_COUNT(ContentLength)) == 0)
Azure.IoT Build 6:c55b013dfc2a 620 {
AzureIoTClient 7:1af47e3a19b6 621 if (ParseStringToDecimal(buf + CHAR_COUNT(ContentLength), &bodyLength) != 1)
Azure.IoT Build 6:c55b013dfc2a 622 {
Azure.IoT Build 6:c55b013dfc2a 623 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 624 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 625 goto exit;
Azure.IoT Build 6:c55b013dfc2a 626 }
Azure.IoT Build 6:c55b013dfc2a 627 }
Azure.IoT Build 6:c55b013dfc2a 628 else if (my_strnicmp(buf, TransferEncoding, CHAR_COUNT(TransferEncoding)) == 0)
Azure.IoT Build 6:c55b013dfc2a 629 {
Azure.IoT Build 6:c55b013dfc2a 630 const char* p = buf + CHAR_COUNT(TransferEncoding);
Azure.IoT Build 6:c55b013dfc2a 631 while (isspace(*p)) p++;
Azure.IoT Build 6:c55b013dfc2a 632 if (my_stricmp(p, "chunked") == 0)
Azure.IoT Build 6:c55b013dfc2a 633 chunked = true;
Azure.IoT Build 6:c55b013dfc2a 634 }
Azure.IoT Build 6:c55b013dfc2a 635
Azure.IoT Build 6:c55b013dfc2a 636 char* whereIsColon = strchr((char*)buf, ':');
Azure.IoT Build 6:c55b013dfc2a 637 if (whereIsColon && responseHeadersHandle != NULL)
Azure.IoT Build 6:c55b013dfc2a 638 {
Azure.IoT Build 6:c55b013dfc2a 639 *whereIsColon = '\0';
Azure.IoT Build 6:c55b013dfc2a 640 HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1);
Azure.IoT Build 6:c55b013dfc2a 641 }
Azure.IoT Build 6:c55b013dfc2a 642
Azure.IoT Build 6:c55b013dfc2a 643 if (readLine(httpHandle, buf, sizeof(buf)) < 0)
Azure.IoT Build 6:c55b013dfc2a 644 {
Azure.IoT Build 6:c55b013dfc2a 645 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 646 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 647 goto exit;
Azure.IoT Build 6:c55b013dfc2a 648 }
Azure.IoT Build 6:c55b013dfc2a 649 }
Azure.IoT Build 6:c55b013dfc2a 650
Azure.IoT Build 6:c55b013dfc2a 651 //Read HTTP response body
Azure.IoT Build 6:c55b013dfc2a 652 if (!chunked)
Azure.IoT Build 6:c55b013dfc2a 653 {
Azure.IoT Build 6:c55b013dfc2a 654 if (bodyLength)
Azure.IoT Build 6:c55b013dfc2a 655 {
Azure.IoT Build 6:c55b013dfc2a 656 if (responseContent != NULL)
Azure.IoT Build 6:c55b013dfc2a 657 {
Azure.IoT Build 6:c55b013dfc2a 658 if (BUFFER_pre_build(responseContent, bodyLength) != 0)
Azure.IoT Build 6:c55b013dfc2a 659 {
Azure.IoT Build 6:c55b013dfc2a 660 result = HTTPAPI_ALLOC_FAILED;
Azure.IoT Build 6:c55b013dfc2a 661 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 662 }
Azure.IoT Build 6:c55b013dfc2a 663 else if (BUFFER_content(responseContent, &receivedContent) != 0)
Azure.IoT Build 6:c55b013dfc2a 664 {
Azure.IoT Build 6:c55b013dfc2a 665 (void)BUFFER_unbuild(responseContent);
Azure.IoT Build 6:c55b013dfc2a 666
Azure.IoT Build 6:c55b013dfc2a 667 result = HTTPAPI_ALLOC_FAILED;
Azure.IoT Build 6:c55b013dfc2a 668 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 669 }
Azure.IoT Build 6:c55b013dfc2a 670
Azure.IoT Build 6:c55b013dfc2a 671 if (readChunk(httpHandle, (char*)receivedContent, bodyLength) < 0)
Azure.IoT Build 6:c55b013dfc2a 672 {
Azure.IoT Build 6:c55b013dfc2a 673 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 674 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 675 goto exit;
Azure.IoT Build 6:c55b013dfc2a 676 }
Azure.IoT Build 6:c55b013dfc2a 677 else
Azure.IoT Build 6:c55b013dfc2a 678 {
Azure.IoT Build 6:c55b013dfc2a 679 result = HTTPAPI_OK;
Azure.IoT Build 6:c55b013dfc2a 680 }
Azure.IoT Build 6:c55b013dfc2a 681 }
Azure.IoT Build 6:c55b013dfc2a 682 else
Azure.IoT Build 6:c55b013dfc2a 683 {
Azure.IoT Build 6:c55b013dfc2a 684 (void)skipN(httpHandle, bodyLength, buf, sizeof(buf));
Azure.IoT Build 6:c55b013dfc2a 685 result = HTTPAPI_OK;
Azure.IoT Build 6:c55b013dfc2a 686 }
Azure.IoT Build 6:c55b013dfc2a 687 }
Azure.IoT Build 6:c55b013dfc2a 688 else
Azure.IoT Build 6:c55b013dfc2a 689 {
Azure.IoT Build 6:c55b013dfc2a 690 result = HTTPAPI_OK;
Azure.IoT Build 6:c55b013dfc2a 691 }
Azure.IoT Build 6:c55b013dfc2a 692 }
Azure.IoT Build 6:c55b013dfc2a 693 else
Azure.IoT Build 6:c55b013dfc2a 694 {
Azure.IoT Build 6:c55b013dfc2a 695 size_t size = 0;
Azure.IoT Build 6:c55b013dfc2a 696 result = HTTPAPI_OK;
Azure.IoT Build 6:c55b013dfc2a 697 for (;;)
Azure.IoT Build 6:c55b013dfc2a 698 {
Azure.IoT Build 6:c55b013dfc2a 699 int chunkSize;
Azure.IoT Build 6:c55b013dfc2a 700 if (readLine(httpHandle, buf, sizeof(buf)) < 0) // read [length in hex]/r/n
Azure.IoT Build 6:c55b013dfc2a 701 {
Azure.IoT Build 6:c55b013dfc2a 702 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 703 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 704 goto exit;
Azure.IoT Build 6:c55b013dfc2a 705 }
AzureIoTClient 7:1af47e3a19b6 706 if (ParseStringToHexadecimal(buf, &chunkSize) != 1) // chunkSize is length of next line (/r/n is not counted)
Azure.IoT Build 6:c55b013dfc2a 707 {
Azure.IoT Build 6:c55b013dfc2a 708 //Cannot match string, error
Azure.IoT Build 6:c55b013dfc2a 709 result = HTTPAPI_RECEIVE_RESPONSE_FAILED;
Azure.IoT Build 6:c55b013dfc2a 710 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 711 goto exit;
Azure.IoT Build 6:c55b013dfc2a 712 }
Azure.IoT Build 6:c55b013dfc2a 713
Azure.IoT Build 6:c55b013dfc2a 714 if (chunkSize == 0)
Azure.IoT Build 6:c55b013dfc2a 715 {
Azure.IoT Build 6:c55b013dfc2a 716 // 0 length means next line is just '\r\n' and end of chunks
Azure.IoT Build 6:c55b013dfc2a 717 if (readChunk(httpHandle, (char*)buf, 2) < 0
Azure.IoT Build 6:c55b013dfc2a 718 || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
Azure.IoT Build 6:c55b013dfc2a 719 {
Azure.IoT Build 6:c55b013dfc2a 720 (void)BUFFER_unbuild(responseContent);
Azure.IoT Build 6:c55b013dfc2a 721
Azure.IoT Build 6:c55b013dfc2a 722 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 723 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 724 goto exit;
Azure.IoT Build 6:c55b013dfc2a 725 }
Azure.IoT Build 6:c55b013dfc2a 726 break;
Azure.IoT Build 6:c55b013dfc2a 727 }
Azure.IoT Build 6:c55b013dfc2a 728 else
Azure.IoT Build 6:c55b013dfc2a 729 {
Azure.IoT Build 6:c55b013dfc2a 730 if (responseContent != NULL)
Azure.IoT Build 6:c55b013dfc2a 731 {
Azure.IoT Build 6:c55b013dfc2a 732 if (BUFFER_enlarge(responseContent, chunkSize) != 0)
Azure.IoT Build 6:c55b013dfc2a 733 {
Azure.IoT Build 6:c55b013dfc2a 734 (void)BUFFER_unbuild(responseContent);
Azure.IoT Build 6:c55b013dfc2a 735
Azure.IoT Build 6:c55b013dfc2a 736 result = HTTPAPI_ALLOC_FAILED;
Azure.IoT Build 6:c55b013dfc2a 737 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 738 }
Azure.IoT Build 6:c55b013dfc2a 739 else if (BUFFER_content(responseContent, &receivedContent) != 0)
Azure.IoT Build 6:c55b013dfc2a 740 {
Azure.IoT Build 6:c55b013dfc2a 741 (void)BUFFER_unbuild(responseContent);
Azure.IoT Build 6:c55b013dfc2a 742
Azure.IoT Build 6:c55b013dfc2a 743 result = HTTPAPI_ALLOC_FAILED;
Azure.IoT Build 6:c55b013dfc2a 744 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 745 }
Azure.IoT Build 6:c55b013dfc2a 746
Azure.IoT Build 6:c55b013dfc2a 747 if (readChunk(httpHandle, (char*)receivedContent + size, chunkSize) < 0)
Azure.IoT Build 6:c55b013dfc2a 748 {
Azure.IoT Build 6:c55b013dfc2a 749 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 750 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 751 goto exit;
Azure.IoT Build 6:c55b013dfc2a 752 }
Azure.IoT Build 6:c55b013dfc2a 753 }
Azure.IoT Build 6:c55b013dfc2a 754 else
Azure.IoT Build 6:c55b013dfc2a 755 {
Azure.IoT Build 6:c55b013dfc2a 756 if (skipN(httpHandle, chunkSize, buf, sizeof(buf)) < 0)
Azure.IoT Build 6:c55b013dfc2a 757 {
Azure.IoT Build 6:c55b013dfc2a 758 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 759 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 760 goto exit;
Azure.IoT Build 6:c55b013dfc2a 761 }
Azure.IoT Build 6:c55b013dfc2a 762 }
Azure.IoT Build 6:c55b013dfc2a 763
Azure.IoT Build 6:c55b013dfc2a 764 if (readChunk(httpHandle, (char*)buf, 2) < 0
Azure.IoT Build 6:c55b013dfc2a 765 || buf[0] != '\r' || buf[1] != '\n') // skip /r/n
Azure.IoT Build 6:c55b013dfc2a 766 {
Azure.IoT Build 6:c55b013dfc2a 767 result = HTTPAPI_READ_DATA_FAILED;
Azure.IoT Build 6:c55b013dfc2a 768 LogError("(result = %s)", ENUM_TO_STRING(HTTPAPI_RESULT, result));
Azure.IoT Build 6:c55b013dfc2a 769 goto exit;
Azure.IoT Build 6:c55b013dfc2a 770 }
Azure.IoT Build 6:c55b013dfc2a 771 size += chunkSize;
Azure.IoT Build 6:c55b013dfc2a 772 }
Azure.IoT Build 6:c55b013dfc2a 773 }
Azure.IoT Build 6:c55b013dfc2a 774
Azure.IoT Build 6:c55b013dfc2a 775 }
Azure.IoT Build 6:c55b013dfc2a 776
Azure.IoT Build 6:c55b013dfc2a 777 exit:
Azure.IoT Build 6:c55b013dfc2a 778 if ((handle != NULL) &&
Azure.IoT Build 6:c55b013dfc2a 779 (handle->is_io_error != 0))
Azure.IoT Build 6:c55b013dfc2a 780 {
Azure.IoT Build 6:c55b013dfc2a 781 xio_close(handle->xio_handle, NULL, NULL);
Azure.IoT Build 6:c55b013dfc2a 782 handle->is_connected = 0;
Azure.IoT Build 6:c55b013dfc2a 783 }
Azure.IoT Build 6:c55b013dfc2a 784
Azure.IoT Build 6:c55b013dfc2a 785 return result;
Azure.IoT Build 6:c55b013dfc2a 786 }
Azure.IoT Build 6:c55b013dfc2a 787
Azure.IoT Build 6:c55b013dfc2a 788 HTTPAPI_RESULT HTTPAPI_SetOption(HTTP_HANDLE handle, const char* optionName, const void* value)
Azure.IoT Build 6:c55b013dfc2a 789 {
Azure.IoT Build 6:c55b013dfc2a 790 HTTPAPI_RESULT result;
Azure.IoT Build 6:c55b013dfc2a 791 if (
Azure.IoT Build 6:c55b013dfc2a 792 (handle == NULL) ||
Azure.IoT Build 6:c55b013dfc2a 793 (optionName == NULL) ||
Azure.IoT Build 6:c55b013dfc2a 794 (value == NULL)
Azure.IoT Build 6:c55b013dfc2a 795 )
Azure.IoT Build 6:c55b013dfc2a 796 {
Azure.IoT Build 6:c55b013dfc2a 797 result = HTTPAPI_INVALID_ARG;
Azure.IoT Build 6:c55b013dfc2a 798 LogError("invalid parameter (NULL) passed to HTTPAPI_SetOption");
Azure.IoT Build 6:c55b013dfc2a 799 }
Azure.IoT Build 6:c55b013dfc2a 800 else if (strcmp("TrustedCerts", optionName) == 0)
Azure.IoT Build 6:c55b013dfc2a 801 {
Azure.IoT Build 6:c55b013dfc2a 802 HTTP_HANDLE_DATA* h = (HTTP_HANDLE_DATA*)handle;
Azure.IoT Build 6:c55b013dfc2a 803 if (h->certificate)
Azure.IoT Build 6:c55b013dfc2a 804 {
Azure.IoT Build 6:c55b013dfc2a 805 free(h->certificate);
Azure.IoT Build 6:c55b013dfc2a 806 }
Azure.IoT Build 6:c55b013dfc2a 807
Azure.IoT Build 6:c55b013dfc2a 808 int len = strlen((char*)value);
Azure.IoT Build 6:c55b013dfc2a 809 h->certificate = (char*)malloc(len + 1);
Azure.IoT Build 6:c55b013dfc2a 810 if (h->certificate == NULL)
Azure.IoT Build 6:c55b013dfc2a 811 {
Azure.IoT Build 6:c55b013dfc2a 812 result = HTTPAPI_ERROR;
Azure.IoT Build 6:c55b013dfc2a 813 LogError("unable to allocate certificate memory in HTTPAPI_SetOption");
Azure.IoT Build 6:c55b013dfc2a 814 }
Azure.IoT Build 6:c55b013dfc2a 815 else
Azure.IoT Build 6:c55b013dfc2a 816 {
Azure.IoT Build 6:c55b013dfc2a 817 (void)strcpy(h->certificate, (const char*)value);
Azure.IoT Build 6:c55b013dfc2a 818 result = HTTPAPI_OK;
Azure.IoT Build 6:c55b013dfc2a 819 }
Azure.IoT Build 6:c55b013dfc2a 820 }
Azure.IoT Build 6:c55b013dfc2a 821 else
Azure.IoT Build 6:c55b013dfc2a 822 {
Azure.IoT Build 6:c55b013dfc2a 823 result = HTTPAPI_INVALID_ARG;
Azure.IoT Build 6:c55b013dfc2a 824 LogError("unknown option %s", optionName);
Azure.IoT Build 6:c55b013dfc2a 825 }
Azure.IoT Build 6:c55b013dfc2a 826 return result;
Azure.IoT Build 6:c55b013dfc2a 827 }
Azure.IoT Build 6:c55b013dfc2a 828
Azure.IoT Build 6:c55b013dfc2a 829 HTTPAPI_RESULT HTTPAPI_CloneOption(const char* optionName, const void* value, const void** savedValue)
Azure.IoT Build 6:c55b013dfc2a 830 {
Azure.IoT Build 6:c55b013dfc2a 831 HTTPAPI_RESULT result;
Azure.IoT Build 6:c55b013dfc2a 832 if (
Azure.IoT Build 6:c55b013dfc2a 833 (optionName == NULL) ||
Azure.IoT Build 6:c55b013dfc2a 834 (value == NULL) ||
Azure.IoT Build 6:c55b013dfc2a 835 (savedValue == NULL)
Azure.IoT Build 6:c55b013dfc2a 836 )
Azure.IoT Build 6:c55b013dfc2a 837 {
Azure.IoT Build 6:c55b013dfc2a 838 result = HTTPAPI_INVALID_ARG;
Azure.IoT Build 6:c55b013dfc2a 839 LogError("invalid argument(NULL) passed to HTTPAPI_CloneOption");
Azure.IoT Build 6:c55b013dfc2a 840 }
Azure.IoT Build 6:c55b013dfc2a 841 else if (strcmp("TrustedCerts", optionName) == 0)
Azure.IoT Build 6:c55b013dfc2a 842 {
Azure.IoT Build 6:c55b013dfc2a 843 size_t certLen = strlen((const char*)value);
Azure.IoT Build 6:c55b013dfc2a 844 char* tempCert = (char*)malloc(certLen+1);
Azure.IoT Build 6:c55b013dfc2a 845 if (tempCert == NULL)
Azure.IoT Build 6:c55b013dfc2a 846 {
Azure.IoT Build 6:c55b013dfc2a 847 result = HTTPAPI_INVALID_ARG;
Azure.IoT Build 6:c55b013dfc2a 848 LogError("unable to allocate certificate memory in HTTPAPI_CloneOption");
Azure.IoT Build 6:c55b013dfc2a 849 }
Azure.IoT Build 6:c55b013dfc2a 850 else
Azure.IoT Build 6:c55b013dfc2a 851 {
Azure.IoT Build 6:c55b013dfc2a 852 (void)strcpy(tempCert, (const char*)value);
Azure.IoT Build 6:c55b013dfc2a 853 *savedValue = tempCert;
Azure.IoT Build 6:c55b013dfc2a 854 result = HTTPAPI_OK;
Azure.IoT Build 6:c55b013dfc2a 855 }
Azure.IoT Build 6:c55b013dfc2a 856 }
Azure.IoT Build 6:c55b013dfc2a 857 else
Azure.IoT Build 6:c55b013dfc2a 858 {
Azure.IoT Build 6:c55b013dfc2a 859 result = HTTPAPI_INVALID_ARG;
Azure.IoT Build 6:c55b013dfc2a 860 LogError("unknown option %s", optionName);
Azure.IoT Build 6:c55b013dfc2a 861 }
Azure.IoT Build 6:c55b013dfc2a 862 return result;
Azure.IoT Build 6:c55b013dfc2a 863 }