Xin Zhang / azure-iot-c-sdk-f767zi

Dependents:   samplemqtt

Committer:
XinZhangMS
Date:
Thu Aug 23 06:52:14 2018 +0000
Revision:
0:f7f1f0d76dd6
azure-c-sdk for mbed os supporting NUCLEO_F767ZI

Who changed what in which revision?

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