WIP. send a large constant string twice a second, in order to test out the transport with something indicative of our required load.

Dependencies:   FXOS8700CQ NTPClient azure_umqtt_c iothub_mqtt_transport mbed-rtos mbed wolfSSL Socket lwip-eth lwip-sys lwip

Fork of FXOS8700CQ_To_Azure_IoT by Mark Radbourne

Committer:
julianhigginson
Date:
Thu Jan 05 23:40:24 2017 +0000
Revision:
7:0d1a0fe537dc
Parent:
3:c0556ff7b8e3
modified dummy message for minimal data transport

Who changed what in which revision?

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