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 <stdbool.h>
XinZhangMS 0:f7f1f0d76dd6 7 #include <stdint.h>
XinZhangMS 0:f7f1f0d76dd6 8 #include <limits.h>
XinZhangMS 0:f7f1f0d76dd6 9 #include <stddef.h>
XinZhangMS 0:f7f1f0d76dd6 10 #include "azure_c_shared_utility/gballoc.h"
XinZhangMS 0:f7f1f0d76dd6 11 #include "azure_c_shared_utility/xio.h"
XinZhangMS 0:f7f1f0d76dd6 12 #include "azure_c_shared_utility/socketio.h"
XinZhangMS 0:f7f1f0d76dd6 13 #include "azure_c_shared_utility/crt_abstractions.h"
XinZhangMS 0:f7f1f0d76dd6 14 #include "azure_c_shared_utility/http_proxy_io.h"
XinZhangMS 0:f7f1f0d76dd6 15 #include "azure_c_shared_utility/base64.h"
XinZhangMS 0:f7f1f0d76dd6 16
XinZhangMS 0:f7f1f0d76dd6 17 typedef enum HTTP_PROXY_IO_STATE_TAG
XinZhangMS 0:f7f1f0d76dd6 18 {
XinZhangMS 0:f7f1f0d76dd6 19 HTTP_PROXY_IO_STATE_CLOSED,
XinZhangMS 0:f7f1f0d76dd6 20 HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO,
XinZhangMS 0:f7f1f0d76dd6 21 HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE,
XinZhangMS 0:f7f1f0d76dd6 22 HTTP_PROXY_IO_STATE_OPEN,
XinZhangMS 0:f7f1f0d76dd6 23 HTTP_PROXY_IO_STATE_CLOSING,
XinZhangMS 0:f7f1f0d76dd6 24 HTTP_PROXY_IO_STATE_ERROR
XinZhangMS 0:f7f1f0d76dd6 25 } HTTP_PROXY_IO_STATE;
XinZhangMS 0:f7f1f0d76dd6 26
XinZhangMS 0:f7f1f0d76dd6 27 typedef struct HTTP_PROXY_IO_INSTANCE_TAG
XinZhangMS 0:f7f1f0d76dd6 28 {
XinZhangMS 0:f7f1f0d76dd6 29 HTTP_PROXY_IO_STATE http_proxy_io_state;
XinZhangMS 0:f7f1f0d76dd6 30 ON_BYTES_RECEIVED on_bytes_received;
XinZhangMS 0:f7f1f0d76dd6 31 void* on_bytes_received_context;
XinZhangMS 0:f7f1f0d76dd6 32 ON_IO_ERROR on_io_error;
XinZhangMS 0:f7f1f0d76dd6 33 void* on_io_error_context;
XinZhangMS 0:f7f1f0d76dd6 34 ON_IO_OPEN_COMPLETE on_io_open_complete;
XinZhangMS 0:f7f1f0d76dd6 35 void* on_io_open_complete_context;
XinZhangMS 0:f7f1f0d76dd6 36 ON_IO_CLOSE_COMPLETE on_io_close_complete;
XinZhangMS 0:f7f1f0d76dd6 37 void* on_io_close_complete_context;
XinZhangMS 0:f7f1f0d76dd6 38 char* hostname;
XinZhangMS 0:f7f1f0d76dd6 39 int port;
XinZhangMS 0:f7f1f0d76dd6 40 char* proxy_hostname;
XinZhangMS 0:f7f1f0d76dd6 41 int proxy_port;
XinZhangMS 0:f7f1f0d76dd6 42 char* username;
XinZhangMS 0:f7f1f0d76dd6 43 char* password;
XinZhangMS 0:f7f1f0d76dd6 44 XIO_HANDLE underlying_io;
XinZhangMS 0:f7f1f0d76dd6 45 unsigned char* receive_buffer;
XinZhangMS 0:f7f1f0d76dd6 46 size_t receive_buffer_size;
XinZhangMS 0:f7f1f0d76dd6 47 } HTTP_PROXY_IO_INSTANCE;
XinZhangMS 0:f7f1f0d76dd6 48
XinZhangMS 0:f7f1f0d76dd6 49 static CONCRETE_IO_HANDLE http_proxy_io_create(void* io_create_parameters)
XinZhangMS 0:f7f1f0d76dd6 50 {
XinZhangMS 0:f7f1f0d76dd6 51 HTTP_PROXY_IO_INSTANCE* result;
XinZhangMS 0:f7f1f0d76dd6 52
XinZhangMS 0:f7f1f0d76dd6 53 if (io_create_parameters == NULL)
XinZhangMS 0:f7f1f0d76dd6 54 {
XinZhangMS 0:f7f1f0d76dd6 55 /* Codes_SRS_HTTP_PROXY_IO_01_002: [ If `io_create_parameters` is NULL, `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 56 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 57 LogError("NULL io_create_parameters.");
XinZhangMS 0:f7f1f0d76dd6 58 }
XinZhangMS 0:f7f1f0d76dd6 59 else
XinZhangMS 0:f7f1f0d76dd6 60 {
XinZhangMS 0:f7f1f0d76dd6 61 /* Codes_SRS_HTTP_PROXY_IO_01_003: [ `io_create_parameters` shall be used as an `HTTP_PROXY_IO_CONFIG*`. ]*/
XinZhangMS 0:f7f1f0d76dd6 62 HTTP_PROXY_IO_CONFIG* http_proxy_io_config = (HTTP_PROXY_IO_CONFIG*)io_create_parameters;
XinZhangMS 0:f7f1f0d76dd6 63 if ((http_proxy_io_config->hostname == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 64 (http_proxy_io_config->proxy_hostname == NULL))
XinZhangMS 0:f7f1f0d76dd6 65 {
XinZhangMS 0:f7f1f0d76dd6 66 /* Codes_SRS_HTTP_PROXY_IO_01_004: [ If the `hostname` or `proxy_hostname` member is NULL, then `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 67 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 68 LogError("Bad arguments: hostname = %p, proxy_hostname = %p",
XinZhangMS 0:f7f1f0d76dd6 69 http_proxy_io_config->hostname, http_proxy_io_config->proxy_hostname);
XinZhangMS 0:f7f1f0d76dd6 70 }
XinZhangMS 0:f7f1f0d76dd6 71 /* Codes_SRS_HTTP_PROXY_IO_01_095: [ If one of the fields `username` and `password` is non-NULL, then the other has to be also non-NULL, otherwise `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 72 else if (((http_proxy_io_config->username == NULL) && (http_proxy_io_config->password != NULL)) ||
XinZhangMS 0:f7f1f0d76dd6 73 ((http_proxy_io_config->username != NULL) && (http_proxy_io_config->password == NULL)))
XinZhangMS 0:f7f1f0d76dd6 74 {
XinZhangMS 0:f7f1f0d76dd6 75 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 76 LogError("Bad arguments: username = %p, password = %p",
XinZhangMS 0:f7f1f0d76dd6 77 http_proxy_io_config->username, http_proxy_io_config->password);
XinZhangMS 0:f7f1f0d76dd6 78 }
XinZhangMS 0:f7f1f0d76dd6 79 else
XinZhangMS 0:f7f1f0d76dd6 80 {
XinZhangMS 0:f7f1f0d76dd6 81 /* Codes_SRS_HTTP_PROXY_IO_01_001: [ `http_proxy_io_create` shall create a new instance of the HTTP proxy IO. ]*/
XinZhangMS 0:f7f1f0d76dd6 82 result = (HTTP_PROXY_IO_INSTANCE*)malloc(sizeof(HTTP_PROXY_IO_INSTANCE));
XinZhangMS 0:f7f1f0d76dd6 83 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 84 {
XinZhangMS 0:f7f1f0d76dd6 85 /* Codes_SRS_HTTP_PROXY_IO_01_051: [ If allocating memory for the new instance fails, `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 86 LogError("Failed allocating HTTP proxy IO instance.");
XinZhangMS 0:f7f1f0d76dd6 87 }
XinZhangMS 0:f7f1f0d76dd6 88 else
XinZhangMS 0:f7f1f0d76dd6 89 {
XinZhangMS 0:f7f1f0d76dd6 90 /* Codes_SRS_HTTP_PROXY_IO_01_005: [ `http_proxy_io_create` shall copy the `hostname`, `port`, `username` and `password` values for later use when the actual CONNECT is performed. ]*/
XinZhangMS 0:f7f1f0d76dd6 91 /* Codes_SRS_HTTP_PROXY_IO_01_006: [ `hostname` and `proxy_hostname`, `username` and `password` shall be copied by calling `mallocAndStrcpy_s`. ]*/
XinZhangMS 0:f7f1f0d76dd6 92 if (mallocAndStrcpy_s(&result->hostname, http_proxy_io_config->hostname) != 0)
XinZhangMS 0:f7f1f0d76dd6 93 {
XinZhangMS 0:f7f1f0d76dd6 94 /* Codes_SRS_HTTP_PROXY_IO_01_007: [ If `mallocAndStrcpy_s` fails then `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 95 LogError("Failed to copy the hostname.");
XinZhangMS 0:f7f1f0d76dd6 96 /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When `http_proxy_io_create` fails, all allocated resources up to that point shall be freed. ]*/
XinZhangMS 0:f7f1f0d76dd6 97 free(result);
XinZhangMS 0:f7f1f0d76dd6 98 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 99 }
XinZhangMS 0:f7f1f0d76dd6 100 else
XinZhangMS 0:f7f1f0d76dd6 101 {
XinZhangMS 0:f7f1f0d76dd6 102 /* Codes_SRS_HTTP_PROXY_IO_01_006: [ `hostname` and `proxy_hostname`, `username` and `password` shall be copied by calling `mallocAndStrcpy_s`. ]*/
XinZhangMS 0:f7f1f0d76dd6 103 if (mallocAndStrcpy_s(&result->proxy_hostname, http_proxy_io_config->proxy_hostname) != 0)
XinZhangMS 0:f7f1f0d76dd6 104 {
XinZhangMS 0:f7f1f0d76dd6 105 /* Codes_SRS_HTTP_PROXY_IO_01_007: [ If `mallocAndStrcpy_s` fails then `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 106 LogError("Failed to copy the proxy_hostname.");
XinZhangMS 0:f7f1f0d76dd6 107 /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When `http_proxy_io_create` fails, all allocated resources up to that point shall be freed. ]*/
XinZhangMS 0:f7f1f0d76dd6 108 free(result->hostname);
XinZhangMS 0:f7f1f0d76dd6 109 free(result);
XinZhangMS 0:f7f1f0d76dd6 110 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 111 }
XinZhangMS 0:f7f1f0d76dd6 112 else
XinZhangMS 0:f7f1f0d76dd6 113 {
XinZhangMS 0:f7f1f0d76dd6 114 result->username = NULL;
XinZhangMS 0:f7f1f0d76dd6 115 result->password = NULL;
XinZhangMS 0:f7f1f0d76dd6 116
XinZhangMS 0:f7f1f0d76dd6 117 /* Codes_SRS_HTTP_PROXY_IO_01_006: [ `hostname` and `proxy_hostname`, `username` and `password` shall be copied by calling `mallocAndStrcpy_s`. ]*/
XinZhangMS 0:f7f1f0d76dd6 118 /* Codes_SRS_HTTP_PROXY_IO_01_094: [ `username` and `password` shall be optional. ]*/
XinZhangMS 0:f7f1f0d76dd6 119 if ((http_proxy_io_config->username != NULL) && (mallocAndStrcpy_s(&result->username, http_proxy_io_config->username) != 0))
XinZhangMS 0:f7f1f0d76dd6 120 {
XinZhangMS 0:f7f1f0d76dd6 121 /* Codes_SRS_HTTP_PROXY_IO_01_007: [ If `mallocAndStrcpy_s` fails then `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 122 LogError("Failed to copy the username.");
XinZhangMS 0:f7f1f0d76dd6 123 /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When `http_proxy_io_create` fails, all allocated resources up to that point shall be freed. ]*/
XinZhangMS 0:f7f1f0d76dd6 124 free(result->proxy_hostname);
XinZhangMS 0:f7f1f0d76dd6 125 free(result->hostname);
XinZhangMS 0:f7f1f0d76dd6 126 free(result);
XinZhangMS 0:f7f1f0d76dd6 127 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 128 }
XinZhangMS 0:f7f1f0d76dd6 129 else
XinZhangMS 0:f7f1f0d76dd6 130 {
XinZhangMS 0:f7f1f0d76dd6 131 /* Codes_SRS_HTTP_PROXY_IO_01_006: [ `hostname` and `proxy_hostname`, `username` and `password` shall be copied by calling `mallocAndStrcpy_s`. ]*/
XinZhangMS 0:f7f1f0d76dd6 132 /* Codes_SRS_HTTP_PROXY_IO_01_094: [ `username` and `password` shall be optional. ]*/
XinZhangMS 0:f7f1f0d76dd6 133 if ((http_proxy_io_config->password != NULL) && (mallocAndStrcpy_s(&result->password, http_proxy_io_config->password) != 0))
XinZhangMS 0:f7f1f0d76dd6 134 {
XinZhangMS 0:f7f1f0d76dd6 135 /* Codes_SRS_HTTP_PROXY_IO_01_007: [ If `mallocAndStrcpy_s` fails then `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 136 LogError("Failed to copy the passowrd.");
XinZhangMS 0:f7f1f0d76dd6 137 /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When `http_proxy_io_create` fails, all allocated resources up to that point shall be freed. ]*/
XinZhangMS 0:f7f1f0d76dd6 138 free(result->username);
XinZhangMS 0:f7f1f0d76dd6 139 free(result->proxy_hostname);
XinZhangMS 0:f7f1f0d76dd6 140 free(result->hostname);
XinZhangMS 0:f7f1f0d76dd6 141 free(result);
XinZhangMS 0:f7f1f0d76dd6 142 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 143 }
XinZhangMS 0:f7f1f0d76dd6 144 else
XinZhangMS 0:f7f1f0d76dd6 145 {
XinZhangMS 0:f7f1f0d76dd6 146 /* Codes_SRS_HTTP_PROXY_IO_01_010: [ - `io_interface_description` shall be set to the result of `socketio_get_interface_description`. ]*/
XinZhangMS 0:f7f1f0d76dd6 147 const IO_INTERFACE_DESCRIPTION* underlying_io_interface = socketio_get_interface_description();
XinZhangMS 0:f7f1f0d76dd6 148 if (underlying_io_interface == NULL)
XinZhangMS 0:f7f1f0d76dd6 149 {
XinZhangMS 0:f7f1f0d76dd6 150 /* Codes_SRS_HTTP_PROXY_IO_01_050: [ If `socketio_get_interface_description` fails, `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 151 LogError("Unable to get the socket IO interface description.");
XinZhangMS 0:f7f1f0d76dd6 152 /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When `http_proxy_io_create` fails, all allocated resources up to that point shall be freed. ]*/
XinZhangMS 0:f7f1f0d76dd6 153 free(result->password);
XinZhangMS 0:f7f1f0d76dd6 154 free(result->username);
XinZhangMS 0:f7f1f0d76dd6 155 free(result->proxy_hostname);
XinZhangMS 0:f7f1f0d76dd6 156 free(result->hostname);
XinZhangMS 0:f7f1f0d76dd6 157 free(result);
XinZhangMS 0:f7f1f0d76dd6 158 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 159 }
XinZhangMS 0:f7f1f0d76dd6 160 else
XinZhangMS 0:f7f1f0d76dd6 161 {
XinZhangMS 0:f7f1f0d76dd6 162 SOCKETIO_CONFIG socket_io_config;
XinZhangMS 0:f7f1f0d76dd6 163
XinZhangMS 0:f7f1f0d76dd6 164 /* Codes_SRS_HTTP_PROXY_IO_01_011: [ - `xio_create_parameters` shall be set to a `SOCKETIO_CONFIG*` where `hostname` is set to the `proxy_hostname` member of `io_create_parameters` and `port` is set to the `proxy_port` member of `io_create_parameters`. ]*/
XinZhangMS 0:f7f1f0d76dd6 165 socket_io_config.hostname = http_proxy_io_config->proxy_hostname;
XinZhangMS 0:f7f1f0d76dd6 166 socket_io_config.port = http_proxy_io_config->proxy_port;
XinZhangMS 0:f7f1f0d76dd6 167 socket_io_config.accepted_socket = NULL;
XinZhangMS 0:f7f1f0d76dd6 168
XinZhangMS 0:f7f1f0d76dd6 169 /* Codes_SRS_HTTP_PROXY_IO_01_009: [ `http_proxy_io_create` shall create a new socket IO by calling `xio_create` with the arguments: ]*/
XinZhangMS 0:f7f1f0d76dd6 170 result->underlying_io = xio_create(underlying_io_interface, &socket_io_config);
XinZhangMS 0:f7f1f0d76dd6 171 if (result->underlying_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 172 {
XinZhangMS 0:f7f1f0d76dd6 173 /* Codes_SRS_HTTP_PROXY_IO_01_012: [ If `xio_create` fails, `http_proxy_io_create` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 174 LogError("Unable to create the underlying IO.");
XinZhangMS 0:f7f1f0d76dd6 175 /* Codes_SRS_HTTP_PROXY_IO_01_008: [ When `http_proxy_io_create` fails, all allocated resources up to that point shall be freed. ]*/
XinZhangMS 0:f7f1f0d76dd6 176 free(result->password);
XinZhangMS 0:f7f1f0d76dd6 177 free(result->username);
XinZhangMS 0:f7f1f0d76dd6 178 free(result->proxy_hostname);
XinZhangMS 0:f7f1f0d76dd6 179 free(result->hostname);
XinZhangMS 0:f7f1f0d76dd6 180 free(result);
XinZhangMS 0:f7f1f0d76dd6 181 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 182 }
XinZhangMS 0:f7f1f0d76dd6 183 else
XinZhangMS 0:f7f1f0d76dd6 184 {
XinZhangMS 0:f7f1f0d76dd6 185 result->port = http_proxy_io_config->port;
XinZhangMS 0:f7f1f0d76dd6 186 result->proxy_port = http_proxy_io_config->proxy_port;
XinZhangMS 0:f7f1f0d76dd6 187 result->receive_buffer = NULL;
XinZhangMS 0:f7f1f0d76dd6 188 result->receive_buffer_size = 0;
XinZhangMS 0:f7f1f0d76dd6 189 result->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
XinZhangMS 0:f7f1f0d76dd6 190 }
XinZhangMS 0:f7f1f0d76dd6 191 }
XinZhangMS 0:f7f1f0d76dd6 192 }
XinZhangMS 0:f7f1f0d76dd6 193 }
XinZhangMS 0:f7f1f0d76dd6 194 }
XinZhangMS 0:f7f1f0d76dd6 195 }
XinZhangMS 0:f7f1f0d76dd6 196 }
XinZhangMS 0:f7f1f0d76dd6 197 }
XinZhangMS 0:f7f1f0d76dd6 198 }
XinZhangMS 0:f7f1f0d76dd6 199
XinZhangMS 0:f7f1f0d76dd6 200 return result;
XinZhangMS 0:f7f1f0d76dd6 201 }
XinZhangMS 0:f7f1f0d76dd6 202
XinZhangMS 0:f7f1f0d76dd6 203 static void http_proxy_io_destroy(CONCRETE_IO_HANDLE http_proxy_io)
XinZhangMS 0:f7f1f0d76dd6 204 {
XinZhangMS 0:f7f1f0d76dd6 205 if (http_proxy_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 206 {
XinZhangMS 0:f7f1f0d76dd6 207 /* Codes_SRS_HTTP_PROXY_IO_01_014: [ If `http_proxy_io` is NULL, `http_proxy_io_destroy` shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 208 LogError("NULL http_proxy_io.");
XinZhangMS 0:f7f1f0d76dd6 209 }
XinZhangMS 0:f7f1f0d76dd6 210 else
XinZhangMS 0:f7f1f0d76dd6 211 {
XinZhangMS 0:f7f1f0d76dd6 212 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
XinZhangMS 0:f7f1f0d76dd6 213
XinZhangMS 0:f7f1f0d76dd6 214 /* Codes_SRS_HTTP_PROXY_IO_01_013: [ `http_proxy_io_destroy` shall free the HTTP proxy IO instance indicated by `http_proxy_io`. ]*/
XinZhangMS 0:f7f1f0d76dd6 215 if (http_proxy_io_instance->receive_buffer != NULL)
XinZhangMS 0:f7f1f0d76dd6 216 {
XinZhangMS 0:f7f1f0d76dd6 217 free(http_proxy_io_instance->receive_buffer);
XinZhangMS 0:f7f1f0d76dd6 218 }
XinZhangMS 0:f7f1f0d76dd6 219
XinZhangMS 0:f7f1f0d76dd6 220 /* Codes_SRS_HTTP_PROXY_IO_01_016: [ `http_proxy_io_destroy` shall destroy the underlying IO created in `http_proxy_io_create` by calling `xio_destroy`. ]*/
XinZhangMS 0:f7f1f0d76dd6 221 xio_destroy(http_proxy_io_instance->underlying_io);
XinZhangMS 0:f7f1f0d76dd6 222 free(http_proxy_io_instance->hostname);
XinZhangMS 0:f7f1f0d76dd6 223 free(http_proxy_io_instance->proxy_hostname);
XinZhangMS 0:f7f1f0d76dd6 224 free(http_proxy_io_instance->username);
XinZhangMS 0:f7f1f0d76dd6 225 free(http_proxy_io_instance->password);
XinZhangMS 0:f7f1f0d76dd6 226 free(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 227 }
XinZhangMS 0:f7f1f0d76dd6 228 }
XinZhangMS 0:f7f1f0d76dd6 229
XinZhangMS 0:f7f1f0d76dd6 230 static void indicate_open_complete_error_and_close(HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance)
XinZhangMS 0:f7f1f0d76dd6 231 {
XinZhangMS 0:f7f1f0d76dd6 232 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
XinZhangMS 0:f7f1f0d76dd6 233 (void)xio_close(http_proxy_io_instance->underlying_io, NULL, NULL);
XinZhangMS 0:f7f1f0d76dd6 234 http_proxy_io_instance->on_io_open_complete(http_proxy_io_instance->on_io_open_complete_context, IO_OPEN_ERROR);
XinZhangMS 0:f7f1f0d76dd6 235 }
XinZhangMS 0:f7f1f0d76dd6 236
XinZhangMS 0:f7f1f0d76dd6 237 // This callback usage needs to be either verified and commented or integrated into
XinZhangMS 0:f7f1f0d76dd6 238 // the state machine.
XinZhangMS 0:f7f1f0d76dd6 239 static void unchecked_on_send_complete(void* context, IO_SEND_RESULT send_result)
XinZhangMS 0:f7f1f0d76dd6 240 {
XinZhangMS 0:f7f1f0d76dd6 241 (void)context;
XinZhangMS 0:f7f1f0d76dd6 242 (void)send_result;
XinZhangMS 0:f7f1f0d76dd6 243 }
XinZhangMS 0:f7f1f0d76dd6 244
XinZhangMS 0:f7f1f0d76dd6 245 static void on_underlying_io_open_complete(void* context, IO_OPEN_RESULT open_result)
XinZhangMS 0:f7f1f0d76dd6 246 {
XinZhangMS 0:f7f1f0d76dd6 247 if (context == NULL)
XinZhangMS 0:f7f1f0d76dd6 248 {
XinZhangMS 0:f7f1f0d76dd6 249 /* Codes_SRS_HTTP_PROXY_IO_01_081: [ `on_underlying_io_open_complete` called with NULL context shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 250 LogError("NULL context in on_underlying_io_open_complete");
XinZhangMS 0:f7f1f0d76dd6 251 }
XinZhangMS 0:f7f1f0d76dd6 252 else
XinZhangMS 0:f7f1f0d76dd6 253 {
XinZhangMS 0:f7f1f0d76dd6 254 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 255 switch (http_proxy_io_instance->http_proxy_io_state)
XinZhangMS 0:f7f1f0d76dd6 256 {
XinZhangMS 0:f7f1f0d76dd6 257 default:
XinZhangMS 0:f7f1f0d76dd6 258 LogError("on_underlying_io_open_complete called in an unexpected state.");
XinZhangMS 0:f7f1f0d76dd6 259 break;
XinZhangMS 0:f7f1f0d76dd6 260
XinZhangMS 0:f7f1f0d76dd6 261 case HTTP_PROXY_IO_STATE_CLOSING:
XinZhangMS 0:f7f1f0d76dd6 262 case HTTP_PROXY_IO_STATE_OPEN:
XinZhangMS 0:f7f1f0d76dd6 263 /* Codes_SRS_HTTP_PROXY_IO_01_077: [ When `on_underlying_io_open_complete` is called in after OPEN has completed, the `on_io_error` callback shall be triggered passing the `on_io_error_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 264 http_proxy_io_instance->on_io_error(http_proxy_io_instance->on_io_error_context);
XinZhangMS 0:f7f1f0d76dd6 265 break;
XinZhangMS 0:f7f1f0d76dd6 266
XinZhangMS 0:f7f1f0d76dd6 267 case HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE:
XinZhangMS 0:f7f1f0d76dd6 268 /* Codes_SRS_HTTP_PROXY_IO_01_076: [ When `on_underlying_io_open_complete` is called while waiting for the CONNECT reply, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 269 LogError("Open complete called again by underlying IO.");
XinZhangMS 0:f7f1f0d76dd6 270 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 271 break;
XinZhangMS 0:f7f1f0d76dd6 272
XinZhangMS 0:f7f1f0d76dd6 273 case HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO:
XinZhangMS 0:f7f1f0d76dd6 274 switch (open_result)
XinZhangMS 0:f7f1f0d76dd6 275 {
XinZhangMS 0:f7f1f0d76dd6 276 default:
XinZhangMS 0:f7f1f0d76dd6 277 case IO_OPEN_ERROR:
XinZhangMS 0:f7f1f0d76dd6 278 /* Codes_SRS_HTTP_PROXY_IO_01_078: [ When `on_underlying_io_open_complete` is called with `IO_OPEN_ERROR`, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 279 LogError("Underlying IO open failed");
XinZhangMS 0:f7f1f0d76dd6 280 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 281 break;
XinZhangMS 0:f7f1f0d76dd6 282
XinZhangMS 0:f7f1f0d76dd6 283 case IO_OPEN_CANCELLED:
XinZhangMS 0:f7f1f0d76dd6 284 /* Codes_SRS_HTTP_PROXY_IO_01_079: [ When `on_underlying_io_open_complete` is called with `IO_OPEN_CANCELLED`, the `on_open_complete` callback shall be triggered with `IO_OPEN_CANCELLED`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 285 LogError("Underlying IO open failed");
XinZhangMS 0:f7f1f0d76dd6 286 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
XinZhangMS 0:f7f1f0d76dd6 287 (void)xio_close(http_proxy_io_instance->underlying_io, NULL, NULL);
XinZhangMS 0:f7f1f0d76dd6 288 http_proxy_io_instance->on_io_open_complete(http_proxy_io_instance->on_io_open_complete_context, IO_OPEN_CANCELLED);
XinZhangMS 0:f7f1f0d76dd6 289 break;
XinZhangMS 0:f7f1f0d76dd6 290
XinZhangMS 0:f7f1f0d76dd6 291 case IO_OPEN_OK:
XinZhangMS 0:f7f1f0d76dd6 292 {
XinZhangMS 0:f7f1f0d76dd6 293 STRING_HANDLE encoded_auth_string;
XinZhangMS 0:f7f1f0d76dd6 294
XinZhangMS 0:f7f1f0d76dd6 295 /* Codes_SRS_HTTP_PROXY_IO_01_057: [ When `on_underlying_io_open_complete` is called, the `http_proxy_io` shall send the CONNECT request constructed per RFC 2817: ]*/
XinZhangMS 0:f7f1f0d76dd6 296 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE;
XinZhangMS 0:f7f1f0d76dd6 297
XinZhangMS 0:f7f1f0d76dd6 298 if (http_proxy_io_instance->username != NULL)
XinZhangMS 0:f7f1f0d76dd6 299 {
XinZhangMS 0:f7f1f0d76dd6 300 char* plain_auth_string_bytes;
XinZhangMS 0:f7f1f0d76dd6 301
XinZhangMS 0:f7f1f0d76dd6 302 /* Codes_SRS_HTTP_PROXY_IO_01_060: [ - The value of `Proxy-Authorization` shall be the constructed according to RFC 2617. ]*/
XinZhangMS 0:f7f1f0d76dd6 303 int plain_auth_string_length = (int)(strlen(http_proxy_io_instance->username)+1);
XinZhangMS 0:f7f1f0d76dd6 304 if (http_proxy_io_instance->password != NULL)
XinZhangMS 0:f7f1f0d76dd6 305 {
XinZhangMS 0:f7f1f0d76dd6 306 plain_auth_string_length += (int)strlen(http_proxy_io_instance->password);
XinZhangMS 0:f7f1f0d76dd6 307 }
XinZhangMS 0:f7f1f0d76dd6 308
XinZhangMS 0:f7f1f0d76dd6 309 if (plain_auth_string_length < 0)
XinZhangMS 0:f7f1f0d76dd6 310 {
XinZhangMS 0:f7f1f0d76dd6 311 /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 312 encoded_auth_string = NULL;
XinZhangMS 0:f7f1f0d76dd6 313 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 314 }
XinZhangMS 0:f7f1f0d76dd6 315 else
XinZhangMS 0:f7f1f0d76dd6 316 {
XinZhangMS 0:f7f1f0d76dd6 317 plain_auth_string_bytes = (char*)malloc(plain_auth_string_length + 1);
XinZhangMS 0:f7f1f0d76dd6 318 if (plain_auth_string_bytes == NULL)
XinZhangMS 0:f7f1f0d76dd6 319 {
XinZhangMS 0:f7f1f0d76dd6 320 /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 321 encoded_auth_string = NULL;
XinZhangMS 0:f7f1f0d76dd6 322 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 323 }
XinZhangMS 0:f7f1f0d76dd6 324 else
XinZhangMS 0:f7f1f0d76dd6 325 {
XinZhangMS 0:f7f1f0d76dd6 326 /* Codes_SRS_HTTP_PROXY_IO_01_091: [ To receive authorization, the client sends the userid and password, separated by a single colon (":") character, within a base64 [7] encoded string in the credentials. ]*/
XinZhangMS 0:f7f1f0d76dd6 327 /* Codes_SRS_HTTP_PROXY_IO_01_092: [ A client MAY preemptively send the corresponding Authorization header with requests for resources in that space without receipt of another challenge from the server. ]*/
XinZhangMS 0:f7f1f0d76dd6 328 /* Codes_SRS_HTTP_PROXY_IO_01_093: [ Userids might be case sensitive. ]*/
XinZhangMS 0:f7f1f0d76dd6 329 if (sprintf(plain_auth_string_bytes, "%s:%s", http_proxy_io_instance->username, (http_proxy_io_instance->password == NULL) ? "" : http_proxy_io_instance->password) < 0)
XinZhangMS 0:f7f1f0d76dd6 330 {
XinZhangMS 0:f7f1f0d76dd6 331 /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 332 encoded_auth_string = NULL;
XinZhangMS 0:f7f1f0d76dd6 333 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 334 }
XinZhangMS 0:f7f1f0d76dd6 335 else
XinZhangMS 0:f7f1f0d76dd6 336 {
XinZhangMS 0:f7f1f0d76dd6 337 /* Codes_SRS_HTTP_PROXY_IO_01_061: [ Encoding to Base64 shall be done by calling `Base64_Encode_Bytes`. ]*/
XinZhangMS 0:f7f1f0d76dd6 338 encoded_auth_string = Base64_Encode_Bytes((const unsigned char*)plain_auth_string_bytes, plain_auth_string_length);
XinZhangMS 0:f7f1f0d76dd6 339 if (encoded_auth_string == NULL)
XinZhangMS 0:f7f1f0d76dd6 340 {
XinZhangMS 0:f7f1f0d76dd6 341 /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 342 LogError("Cannot Base64 encode auth string");
XinZhangMS 0:f7f1f0d76dd6 343 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 344 }
XinZhangMS 0:f7f1f0d76dd6 345 }
XinZhangMS 0:f7f1f0d76dd6 346
XinZhangMS 0:f7f1f0d76dd6 347 free(plain_auth_string_bytes);
XinZhangMS 0:f7f1f0d76dd6 348 }
XinZhangMS 0:f7f1f0d76dd6 349 }
XinZhangMS 0:f7f1f0d76dd6 350 }
XinZhangMS 0:f7f1f0d76dd6 351 else
XinZhangMS 0:f7f1f0d76dd6 352 {
XinZhangMS 0:f7f1f0d76dd6 353 encoded_auth_string = NULL;
XinZhangMS 0:f7f1f0d76dd6 354 }
XinZhangMS 0:f7f1f0d76dd6 355
XinZhangMS 0:f7f1f0d76dd6 356 if ((http_proxy_io_instance->username != NULL) &&
XinZhangMS 0:f7f1f0d76dd6 357 (encoded_auth_string == NULL))
XinZhangMS 0:f7f1f0d76dd6 358 {
XinZhangMS 0:f7f1f0d76dd6 359 LogError("Cannot create authorization header");
XinZhangMS 0:f7f1f0d76dd6 360 }
XinZhangMS 0:f7f1f0d76dd6 361 else
XinZhangMS 0:f7f1f0d76dd6 362 {
XinZhangMS 0:f7f1f0d76dd6 363 int connect_request_length;
XinZhangMS 0:f7f1f0d76dd6 364 const char* auth_string_payload;
XinZhangMS 0:f7f1f0d76dd6 365 /* Codes_SRS_HTTP_PROXY_IO_01_075: [ The Request-URI portion of the Request-Line is always an 'authority' as defined by URI Generic Syntax [2], which is to say the host name and port number destination of the requested connection separated by a colon: ]*/
XinZhangMS 0:f7f1f0d76dd6 366 const char request_format[] = "CONNECT %s:%d HTTP/1.1\r\nHost:%s:%d%s%s\r\n\r\n";
XinZhangMS 0:f7f1f0d76dd6 367 const char proxy_basic[] = "\r\nProxy-authorization: Basic ";
XinZhangMS 0:f7f1f0d76dd6 368 if (http_proxy_io_instance->username != NULL)
XinZhangMS 0:f7f1f0d76dd6 369 {
XinZhangMS 0:f7f1f0d76dd6 370 auth_string_payload = STRING_c_str(encoded_auth_string);
XinZhangMS 0:f7f1f0d76dd6 371 }
XinZhangMS 0:f7f1f0d76dd6 372 else
XinZhangMS 0:f7f1f0d76dd6 373 {
XinZhangMS 0:f7f1f0d76dd6 374 auth_string_payload = "";
XinZhangMS 0:f7f1f0d76dd6 375 }
XinZhangMS 0:f7f1f0d76dd6 376
XinZhangMS 0:f7f1f0d76dd6 377 /* Codes_SRS_HTTP_PROXY_IO_01_059: [ - If `username` and `password` have been specified in the arguments passed to `http_proxy_io_create`, then the header `Proxy-Authorization` shall be added to the request. ]*/
XinZhangMS 0:f7f1f0d76dd6 378
XinZhangMS 0:f7f1f0d76dd6 379 connect_request_length = (int)(strlen(request_format)+(strlen(http_proxy_io_instance->hostname)*2)+strlen(auth_string_payload)+10);
XinZhangMS 0:f7f1f0d76dd6 380 if (http_proxy_io_instance->username != NULL)
XinZhangMS 0:f7f1f0d76dd6 381 {
XinZhangMS 0:f7f1f0d76dd6 382 connect_request_length += (int)strlen(proxy_basic);
XinZhangMS 0:f7f1f0d76dd6 383 }
XinZhangMS 0:f7f1f0d76dd6 384
XinZhangMS 0:f7f1f0d76dd6 385 if (connect_request_length < 0)
XinZhangMS 0:f7f1f0d76dd6 386 {
XinZhangMS 0:f7f1f0d76dd6 387 /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 388 LogError("Cannot encode the CONNECT request");
XinZhangMS 0:f7f1f0d76dd6 389 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 390 }
XinZhangMS 0:f7f1f0d76dd6 391 else
XinZhangMS 0:f7f1f0d76dd6 392 {
XinZhangMS 0:f7f1f0d76dd6 393 char* connect_request = (char*)malloc(connect_request_length + 1);
XinZhangMS 0:f7f1f0d76dd6 394 if (connect_request == NULL)
XinZhangMS 0:f7f1f0d76dd6 395 {
XinZhangMS 0:f7f1f0d76dd6 396 /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 397 LogError("Cannot allocate memory for CONNECT request");
XinZhangMS 0:f7f1f0d76dd6 398 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 399 }
XinZhangMS 0:f7f1f0d76dd6 400 else
XinZhangMS 0:f7f1f0d76dd6 401 {
XinZhangMS 0:f7f1f0d76dd6 402 /* Codes_SRS_HTTP_PROXY_IO_01_059: [ - If `username` and `password` have been specified in the arguments passed to `http_proxy_io_create`, then the header `Proxy-Authorization` shall be added to the request. ]*/
XinZhangMS 0:f7f1f0d76dd6 403 connect_request_length = sprintf(connect_request, request_format,
XinZhangMS 0:f7f1f0d76dd6 404 http_proxy_io_instance->hostname,
XinZhangMS 0:f7f1f0d76dd6 405 http_proxy_io_instance->port,
XinZhangMS 0:f7f1f0d76dd6 406 http_proxy_io_instance->hostname,
XinZhangMS 0:f7f1f0d76dd6 407 http_proxy_io_instance->port,
XinZhangMS 0:f7f1f0d76dd6 408 (http_proxy_io_instance->username != NULL) ? proxy_basic : "",
XinZhangMS 0:f7f1f0d76dd6 409 auth_string_payload);
XinZhangMS 0:f7f1f0d76dd6 410
XinZhangMS 0:f7f1f0d76dd6 411 if (connect_request_length < 0)
XinZhangMS 0:f7f1f0d76dd6 412 {
XinZhangMS 0:f7f1f0d76dd6 413 /* Codes_SRS_HTTP_PROXY_IO_01_062: [ If any failure is encountered while constructing the request, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 414 LogError("Cannot encode the CONNECT request");
XinZhangMS 0:f7f1f0d76dd6 415 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 416 }
XinZhangMS 0:f7f1f0d76dd6 417 else
XinZhangMS 0:f7f1f0d76dd6 418 {
XinZhangMS 0:f7f1f0d76dd6 419 /* Codes_SRS_HTTP_PROXY_IO_01_063: [ The request shall be sent by calling `xio_send` and passing NULL as `on_send_complete` callback. ]*/
XinZhangMS 0:f7f1f0d76dd6 420 if (xio_send(http_proxy_io_instance->underlying_io, connect_request, connect_request_length, unchecked_on_send_complete, NULL) != 0)
XinZhangMS 0:f7f1f0d76dd6 421 {
XinZhangMS 0:f7f1f0d76dd6 422 /* Codes_SRS_HTTP_PROXY_IO_01_064: [ If `xio_send` fails, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 423 LogError("Could not send CONNECT request");
XinZhangMS 0:f7f1f0d76dd6 424 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 425 }
XinZhangMS 0:f7f1f0d76dd6 426 }
XinZhangMS 0:f7f1f0d76dd6 427
XinZhangMS 0:f7f1f0d76dd6 428 free(connect_request);
XinZhangMS 0:f7f1f0d76dd6 429 }
XinZhangMS 0:f7f1f0d76dd6 430 }
XinZhangMS 0:f7f1f0d76dd6 431 }
XinZhangMS 0:f7f1f0d76dd6 432
XinZhangMS 0:f7f1f0d76dd6 433 if (encoded_auth_string != NULL)
XinZhangMS 0:f7f1f0d76dd6 434 {
XinZhangMS 0:f7f1f0d76dd6 435 STRING_delete(encoded_auth_string);
XinZhangMS 0:f7f1f0d76dd6 436 }
XinZhangMS 0:f7f1f0d76dd6 437
XinZhangMS 0:f7f1f0d76dd6 438 break;
XinZhangMS 0:f7f1f0d76dd6 439 }
XinZhangMS 0:f7f1f0d76dd6 440 }
XinZhangMS 0:f7f1f0d76dd6 441
XinZhangMS 0:f7f1f0d76dd6 442 break;
XinZhangMS 0:f7f1f0d76dd6 443 }
XinZhangMS 0:f7f1f0d76dd6 444 }
XinZhangMS 0:f7f1f0d76dd6 445 }
XinZhangMS 0:f7f1f0d76dd6 446
XinZhangMS 0:f7f1f0d76dd6 447 static void on_underlying_io_error(void* context)
XinZhangMS 0:f7f1f0d76dd6 448 {
XinZhangMS 0:f7f1f0d76dd6 449 if (context == NULL)
XinZhangMS 0:f7f1f0d76dd6 450 {
XinZhangMS 0:f7f1f0d76dd6 451 /* Codes_SRS_HTTP_PROXY_IO_01_088: [ `on_underlying_io_error` called with NULL context shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 452 LogError("NULL context in on_underlying_io_error");
XinZhangMS 0:f7f1f0d76dd6 453 }
XinZhangMS 0:f7f1f0d76dd6 454 else
XinZhangMS 0:f7f1f0d76dd6 455 {
XinZhangMS 0:f7f1f0d76dd6 456 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 457
XinZhangMS 0:f7f1f0d76dd6 458 switch (http_proxy_io_instance->http_proxy_io_state)
XinZhangMS 0:f7f1f0d76dd6 459 {
XinZhangMS 0:f7f1f0d76dd6 460 default:
XinZhangMS 0:f7f1f0d76dd6 461 LogError("on_underlying_io_error in invalid state");
XinZhangMS 0:f7f1f0d76dd6 462 break;
XinZhangMS 0:f7f1f0d76dd6 463
XinZhangMS 0:f7f1f0d76dd6 464 case HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO:
XinZhangMS 0:f7f1f0d76dd6 465 case HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE:
XinZhangMS 0:f7f1f0d76dd6 466 /* Codes_SRS_HTTP_PROXY_IO_01_087: [ If the `on_underlying_io_error` callback is called while OPENING, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 467 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 468 break;
XinZhangMS 0:f7f1f0d76dd6 469
XinZhangMS 0:f7f1f0d76dd6 470 case HTTP_PROXY_IO_STATE_OPEN:
XinZhangMS 0:f7f1f0d76dd6 471 /* Codes_SRS_HTTP_PROXY_IO_01_089: [ If the `on_underlying_io_error` callback is called while the IO is OPEN, the `on_io_error` callback shall be called with the `on_io_error_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 472 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_ERROR;
XinZhangMS 0:f7f1f0d76dd6 473 http_proxy_io_instance->on_io_error(http_proxy_io_instance->on_io_error_context);
XinZhangMS 0:f7f1f0d76dd6 474 break;
XinZhangMS 0:f7f1f0d76dd6 475 }
XinZhangMS 0:f7f1f0d76dd6 476 }
XinZhangMS 0:f7f1f0d76dd6 477 }
XinZhangMS 0:f7f1f0d76dd6 478
XinZhangMS 0:f7f1f0d76dd6 479 static void on_underlying_io_close_complete(void* context)
XinZhangMS 0:f7f1f0d76dd6 480 {
XinZhangMS 0:f7f1f0d76dd6 481 if (context == NULL)
XinZhangMS 0:f7f1f0d76dd6 482 {
XinZhangMS 0:f7f1f0d76dd6 483 /* Cdoes_SRS_HTTP_PROXY_IO_01_084: [ `on_underlying_io_close_complete` called with NULL context shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 484 LogError("NULL context in on_underlying_io_open_complete");
XinZhangMS 0:f7f1f0d76dd6 485 }
XinZhangMS 0:f7f1f0d76dd6 486 else
XinZhangMS 0:f7f1f0d76dd6 487 {
XinZhangMS 0:f7f1f0d76dd6 488 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 489
XinZhangMS 0:f7f1f0d76dd6 490 switch (http_proxy_io_instance->http_proxy_io_state)
XinZhangMS 0:f7f1f0d76dd6 491 {
XinZhangMS 0:f7f1f0d76dd6 492 default:
XinZhangMS 0:f7f1f0d76dd6 493 LogError("on_underlying_io_close_complete called in an invalid state");
XinZhangMS 0:f7f1f0d76dd6 494 break;
XinZhangMS 0:f7f1f0d76dd6 495
XinZhangMS 0:f7f1f0d76dd6 496 case HTTP_PROXY_IO_STATE_CLOSING:
XinZhangMS 0:f7f1f0d76dd6 497 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
XinZhangMS 0:f7f1f0d76dd6 498
XinZhangMS 0:f7f1f0d76dd6 499 /* Codes_SRS_HTTP_PROXY_IO_01_086: [ If the `on_io_close_complete` callback passed to `http_proxy_io_close` was NULL, no callback shall be triggered. ]*/
XinZhangMS 0:f7f1f0d76dd6 500 if (http_proxy_io_instance->on_io_close_complete != NULL)
XinZhangMS 0:f7f1f0d76dd6 501 {
XinZhangMS 0:f7f1f0d76dd6 502 /* Codes_SRS_HTTP_PROXY_IO_01_083: [ `on_underlying_io_close_complete` while CLOSING shall call the `on_io_close_complete` callback, passing to it the `on_io_close_complete_context` as `context` argument. ]*/
XinZhangMS 0:f7f1f0d76dd6 503 http_proxy_io_instance->on_io_close_complete(http_proxy_io_instance->on_io_close_complete_context);
XinZhangMS 0:f7f1f0d76dd6 504 }
XinZhangMS 0:f7f1f0d76dd6 505
XinZhangMS 0:f7f1f0d76dd6 506 break;
XinZhangMS 0:f7f1f0d76dd6 507 }
XinZhangMS 0:f7f1f0d76dd6 508 }
XinZhangMS 0:f7f1f0d76dd6 509 }
XinZhangMS 0:f7f1f0d76dd6 510
XinZhangMS 0:f7f1f0d76dd6 511 /*the following function does the same as sscanf(pos2, "%d", &sec)*/
XinZhangMS 0:f7f1f0d76dd6 512 /*this function only exists because some of platforms do not have sscanf. */
XinZhangMS 0:f7f1f0d76dd6 513 static int ParseStringToDecimal(const char *src, int* dst)
XinZhangMS 0:f7f1f0d76dd6 514 {
XinZhangMS 0:f7f1f0d76dd6 515 int result;
XinZhangMS 0:f7f1f0d76dd6 516 char* next;
XinZhangMS 0:f7f1f0d76dd6 517
XinZhangMS 0:f7f1f0d76dd6 518 (*dst) = (int)strtol(src, &next, 0);
XinZhangMS 0:f7f1f0d76dd6 519 if ((src == next) || ((((*dst) == INT_MAX) || ((*dst) == INT_MIN)) && (errno != 0)))
XinZhangMS 0:f7f1f0d76dd6 520 {
XinZhangMS 0:f7f1f0d76dd6 521 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 522 }
XinZhangMS 0:f7f1f0d76dd6 523 else
XinZhangMS 0:f7f1f0d76dd6 524 {
XinZhangMS 0:f7f1f0d76dd6 525 result = 0;
XinZhangMS 0:f7f1f0d76dd6 526 }
XinZhangMS 0:f7f1f0d76dd6 527
XinZhangMS 0:f7f1f0d76dd6 528 return result;
XinZhangMS 0:f7f1f0d76dd6 529 }
XinZhangMS 0:f7f1f0d76dd6 530
XinZhangMS 0:f7f1f0d76dd6 531 /*the following function does the same as sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) */
XinZhangMS 0:f7f1f0d76dd6 532 /*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 533 static int ParseHttpResponse(const char* src, int* dst)
XinZhangMS 0:f7f1f0d76dd6 534 {
XinZhangMS 0:f7f1f0d76dd6 535 int result;
XinZhangMS 0:f7f1f0d76dd6 536 static const char HTTPPrefix[] = "HTTP/";
XinZhangMS 0:f7f1f0d76dd6 537 bool fail;
XinZhangMS 0:f7f1f0d76dd6 538 const char* runPrefix;
XinZhangMS 0:f7f1f0d76dd6 539
XinZhangMS 0:f7f1f0d76dd6 540 if ((src == NULL) || (dst == NULL))
XinZhangMS 0:f7f1f0d76dd6 541 {
XinZhangMS 0:f7f1f0d76dd6 542 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 543 }
XinZhangMS 0:f7f1f0d76dd6 544 else
XinZhangMS 0:f7f1f0d76dd6 545 {
XinZhangMS 0:f7f1f0d76dd6 546 fail = false;
XinZhangMS 0:f7f1f0d76dd6 547 runPrefix = HTTPPrefix;
XinZhangMS 0:f7f1f0d76dd6 548
XinZhangMS 0:f7f1f0d76dd6 549 while ((*runPrefix) != '\0')
XinZhangMS 0:f7f1f0d76dd6 550 {
XinZhangMS 0:f7f1f0d76dd6 551 if ((*runPrefix) != (*src))
XinZhangMS 0:f7f1f0d76dd6 552 {
XinZhangMS 0:f7f1f0d76dd6 553 fail = true;
XinZhangMS 0:f7f1f0d76dd6 554 break;
XinZhangMS 0:f7f1f0d76dd6 555 }
XinZhangMS 0:f7f1f0d76dd6 556 src++;
XinZhangMS 0:f7f1f0d76dd6 557 runPrefix++;
XinZhangMS 0:f7f1f0d76dd6 558 }
XinZhangMS 0:f7f1f0d76dd6 559
XinZhangMS 0:f7f1f0d76dd6 560 if (!fail)
XinZhangMS 0:f7f1f0d76dd6 561 {
XinZhangMS 0:f7f1f0d76dd6 562 while ((*src) != '.')
XinZhangMS 0:f7f1f0d76dd6 563 {
XinZhangMS 0:f7f1f0d76dd6 564 if ((*src) == '\0')
XinZhangMS 0:f7f1f0d76dd6 565 {
XinZhangMS 0:f7f1f0d76dd6 566 fail = true;
XinZhangMS 0:f7f1f0d76dd6 567 break;
XinZhangMS 0:f7f1f0d76dd6 568 }
XinZhangMS 0:f7f1f0d76dd6 569 src++;
XinZhangMS 0:f7f1f0d76dd6 570 }
XinZhangMS 0:f7f1f0d76dd6 571 }
XinZhangMS 0:f7f1f0d76dd6 572
XinZhangMS 0:f7f1f0d76dd6 573 if (!fail)
XinZhangMS 0:f7f1f0d76dd6 574 {
XinZhangMS 0:f7f1f0d76dd6 575 while ((*src) != ' ')
XinZhangMS 0:f7f1f0d76dd6 576 {
XinZhangMS 0:f7f1f0d76dd6 577 if ((*src) == '\0')
XinZhangMS 0:f7f1f0d76dd6 578 {
XinZhangMS 0:f7f1f0d76dd6 579 fail = true;
XinZhangMS 0:f7f1f0d76dd6 580 break;
XinZhangMS 0:f7f1f0d76dd6 581 }
XinZhangMS 0:f7f1f0d76dd6 582 src++;
XinZhangMS 0:f7f1f0d76dd6 583 }
XinZhangMS 0:f7f1f0d76dd6 584 }
XinZhangMS 0:f7f1f0d76dd6 585
XinZhangMS 0:f7f1f0d76dd6 586 if (fail)
XinZhangMS 0:f7f1f0d76dd6 587 {
XinZhangMS 0:f7f1f0d76dd6 588 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 589 }
XinZhangMS 0:f7f1f0d76dd6 590 else
XinZhangMS 0:f7f1f0d76dd6 591 {
XinZhangMS 0:f7f1f0d76dd6 592 if (ParseStringToDecimal(src, dst) != 0)
XinZhangMS 0:f7f1f0d76dd6 593 {
XinZhangMS 0:f7f1f0d76dd6 594 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 595 }
XinZhangMS 0:f7f1f0d76dd6 596 else
XinZhangMS 0:f7f1f0d76dd6 597 {
XinZhangMS 0:f7f1f0d76dd6 598 result = 0;
XinZhangMS 0:f7f1f0d76dd6 599 }
XinZhangMS 0:f7f1f0d76dd6 600 }
XinZhangMS 0:f7f1f0d76dd6 601 }
XinZhangMS 0:f7f1f0d76dd6 602
XinZhangMS 0:f7f1f0d76dd6 603 return result;
XinZhangMS 0:f7f1f0d76dd6 604 }
XinZhangMS 0:f7f1f0d76dd6 605
XinZhangMS 0:f7f1f0d76dd6 606 static void on_underlying_io_bytes_received(void* context, const unsigned char* buffer, size_t size)
XinZhangMS 0:f7f1f0d76dd6 607 {
XinZhangMS 0:f7f1f0d76dd6 608 if (context == NULL)
XinZhangMS 0:f7f1f0d76dd6 609 {
XinZhangMS 0:f7f1f0d76dd6 610 /* Codes_SRS_HTTP_PROXY_IO_01_082: [ `on_underlying_io_bytes_received` called with NULL context shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 611 LogError("NULL context in on_underlying_io_bytes_received");
XinZhangMS 0:f7f1f0d76dd6 612 }
XinZhangMS 0:f7f1f0d76dd6 613 else
XinZhangMS 0:f7f1f0d76dd6 614 {
XinZhangMS 0:f7f1f0d76dd6 615 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)context;
XinZhangMS 0:f7f1f0d76dd6 616
XinZhangMS 0:f7f1f0d76dd6 617 switch (http_proxy_io_instance->http_proxy_io_state)
XinZhangMS 0:f7f1f0d76dd6 618 {
XinZhangMS 0:f7f1f0d76dd6 619 default:
XinZhangMS 0:f7f1f0d76dd6 620 case HTTP_PROXY_IO_STATE_CLOSING:
XinZhangMS 0:f7f1f0d76dd6 621 LogError("Bytes received in invalid state");
XinZhangMS 0:f7f1f0d76dd6 622 break;
XinZhangMS 0:f7f1f0d76dd6 623
XinZhangMS 0:f7f1f0d76dd6 624 case HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO:
XinZhangMS 0:f7f1f0d76dd6 625 /* Codes_SRS_HTTP_PROXY_IO_01_080: [ If `on_underlying_io_bytes_received` is called while the underlying IO is being opened, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 626 LogError("Bytes received while opening underlying IO");
XinZhangMS 0:f7f1f0d76dd6 627 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 628 break;
XinZhangMS 0:f7f1f0d76dd6 629
XinZhangMS 0:f7f1f0d76dd6 630 case HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE:
XinZhangMS 0:f7f1f0d76dd6 631 {
XinZhangMS 0:f7f1f0d76dd6 632 /* Codes_SRS_HTTP_PROXY_IO_01_065: [ When bytes are received and the response to the CONNECT request was not yet received, the bytes shall be accumulated until a double new-line is detected. ]*/
XinZhangMS 0:f7f1f0d76dd6 633 unsigned char* new_receive_buffer = (unsigned char*)realloc(http_proxy_io_instance->receive_buffer, http_proxy_io_instance->receive_buffer_size + size + 1);
XinZhangMS 0:f7f1f0d76dd6 634 if (new_receive_buffer == NULL)
XinZhangMS 0:f7f1f0d76dd6 635 {
XinZhangMS 0:f7f1f0d76dd6 636 /* Codes_SRS_HTTP_PROXY_IO_01_067: [ If allocating memory for the buffered bytes fails, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 637 LogError("Cannot allocate memory for received data");
XinZhangMS 0:f7f1f0d76dd6 638 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 639 }
XinZhangMS 0:f7f1f0d76dd6 640 else
XinZhangMS 0:f7f1f0d76dd6 641 {
XinZhangMS 0:f7f1f0d76dd6 642 http_proxy_io_instance->receive_buffer = new_receive_buffer;
XinZhangMS 0:f7f1f0d76dd6 643 memcpy(http_proxy_io_instance->receive_buffer + http_proxy_io_instance->receive_buffer_size, buffer, size);
XinZhangMS 0:f7f1f0d76dd6 644 http_proxy_io_instance->receive_buffer_size += size;
XinZhangMS 0:f7f1f0d76dd6 645 }
XinZhangMS 0:f7f1f0d76dd6 646
XinZhangMS 0:f7f1f0d76dd6 647 if (http_proxy_io_instance->receive_buffer_size >= 4)
XinZhangMS 0:f7f1f0d76dd6 648 {
XinZhangMS 0:f7f1f0d76dd6 649 const char* request_end_ptr;
XinZhangMS 0:f7f1f0d76dd6 650
XinZhangMS 0:f7f1f0d76dd6 651 http_proxy_io_instance->receive_buffer[http_proxy_io_instance->receive_buffer_size] = 0;
XinZhangMS 0:f7f1f0d76dd6 652
XinZhangMS 0:f7f1f0d76dd6 653 /* Codes_SRS_HTTP_PROXY_IO_01_066: [ When a double new-line is detected the response shall be parsed in order to extract the status code. ]*/
XinZhangMS 0:f7f1f0d76dd6 654 if ((http_proxy_io_instance->receive_buffer_size >= 4) &&
XinZhangMS 0:f7f1f0d76dd6 655 ((request_end_ptr = strstr((const char*)http_proxy_io_instance->receive_buffer, "\r\n\r\n")) != NULL))
XinZhangMS 0:f7f1f0d76dd6 656 {
XinZhangMS 0:f7f1f0d76dd6 657 int status_code;
XinZhangMS 0:f7f1f0d76dd6 658
XinZhangMS 0:f7f1f0d76dd6 659 /* This part should really be done with the HTTPAPI, but that has to be done as a separate step
XinZhangMS 0:f7f1f0d76dd6 660 as the HTTPAPI has to expose somehow the underlying IO and currently this would be a too big of a change. */
XinZhangMS 0:f7f1f0d76dd6 661
XinZhangMS 0:f7f1f0d76dd6 662 if (ParseHttpResponse((const char*)http_proxy_io_instance->receive_buffer, &status_code) != 0)
XinZhangMS 0:f7f1f0d76dd6 663 {
XinZhangMS 0:f7f1f0d76dd6 664 /* Codes_SRS_HTTP_PROXY_IO_01_068: [ If parsing the CONNECT response fails, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 665 LogError("Cannot decode HTTP response");
XinZhangMS 0:f7f1f0d76dd6 666 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 667 }
XinZhangMS 0:f7f1f0d76dd6 668 /* Codes_SRS_HTTP_PROXY_IO_01_069: [ Any successful (2xx) response to a CONNECT request indicates that the proxy has established a connection to the requested host and port, and has switched to tunneling the current connection to that server connection. ]*/
XinZhangMS 0:f7f1f0d76dd6 669 /* Codes_SRS_HTTP_PROXY_IO_01_090: [ Any successful (2xx) response to a CONNECT request indicates that the proxy has established a connection to the requested host and port, and has switched to tunneling the current connection to that server connection. ]*/
XinZhangMS 0:f7f1f0d76dd6 670 else if ((status_code < 200) || (status_code > 299))
XinZhangMS 0:f7f1f0d76dd6 671 {
XinZhangMS 0:f7f1f0d76dd6 672 /* Codes_SRS_HTTP_PROXY_IO_01_071: [ If the status code is not successful, the `on_open_complete` callback shall be triggered with `IO_OPEN_ERROR`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 673 LogError("Bad status (%d) received in CONNECT response", status_code);
XinZhangMS 0:f7f1f0d76dd6 674 indicate_open_complete_error_and_close(http_proxy_io_instance);
XinZhangMS 0:f7f1f0d76dd6 675 }
XinZhangMS 0:f7f1f0d76dd6 676 else
XinZhangMS 0:f7f1f0d76dd6 677 {
XinZhangMS 0:f7f1f0d76dd6 678 size_t length_remaining = http_proxy_io_instance->receive_buffer + http_proxy_io_instance->receive_buffer_size - ((const unsigned char *)request_end_ptr + 4);
XinZhangMS 0:f7f1f0d76dd6 679
XinZhangMS 0:f7f1f0d76dd6 680 /* Codes_SRS_HTTP_PROXY_IO_01_073: [ Once a success status code was parsed, the IO shall be OPEN. ]*/
XinZhangMS 0:f7f1f0d76dd6 681 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_OPEN;
XinZhangMS 0:f7f1f0d76dd6 682 /* Codes_SRS_HTTP_PROXY_IO_01_070: [ When a success status code is parsed, the `on_open_complete` callback shall be triggered with `IO_OPEN_OK`, passing also the `on_open_complete_context` argument as `context`. ]*/
XinZhangMS 0:f7f1f0d76dd6 683 http_proxy_io_instance->on_io_open_complete(http_proxy_io_instance->on_io_open_complete_context, IO_OPEN_OK);
XinZhangMS 0:f7f1f0d76dd6 684
XinZhangMS 0:f7f1f0d76dd6 685 if (length_remaining > 0)
XinZhangMS 0:f7f1f0d76dd6 686 {
XinZhangMS 0:f7f1f0d76dd6 687 /* Codes_SRS_HTTP_PROXY_IO_01_072: [ Any bytes that are extra (not consumed by the CONNECT response), shall be indicated as received by calling the `on_bytes_received` callback and passing the `on_bytes_received_context` as context argument. ]*/
XinZhangMS 0:f7f1f0d76dd6 688 http_proxy_io_instance->on_bytes_received(http_proxy_io_instance->on_bytes_received_context, (const unsigned char*)request_end_ptr + 4, length_remaining);
XinZhangMS 0:f7f1f0d76dd6 689 }
XinZhangMS 0:f7f1f0d76dd6 690 }
XinZhangMS 0:f7f1f0d76dd6 691 }
XinZhangMS 0:f7f1f0d76dd6 692 }
XinZhangMS 0:f7f1f0d76dd6 693 break;
XinZhangMS 0:f7f1f0d76dd6 694 }
XinZhangMS 0:f7f1f0d76dd6 695 case HTTP_PROXY_IO_STATE_OPEN:
XinZhangMS 0:f7f1f0d76dd6 696 /* Codes_SRS_HTTP_PROXY_IO_01_074: [ If `on_underlying_io_bytes_received` is called while OPEN, all bytes shall be indicated as received by calling the `on_bytes_received` callback and passing the `on_bytes_received_context` as context argument. ]*/
XinZhangMS 0:f7f1f0d76dd6 697 http_proxy_io_instance->on_bytes_received(http_proxy_io_instance->on_bytes_received_context, buffer, size);
XinZhangMS 0:f7f1f0d76dd6 698 break;
XinZhangMS 0:f7f1f0d76dd6 699 }
XinZhangMS 0:f7f1f0d76dd6 700 }
XinZhangMS 0:f7f1f0d76dd6 701 }
XinZhangMS 0:f7f1f0d76dd6 702
XinZhangMS 0:f7f1f0d76dd6 703 static int http_proxy_io_open(CONCRETE_IO_HANDLE http_proxy_io, ON_IO_OPEN_COMPLETE on_io_open_complete, void* on_io_open_complete_context, ON_BYTES_RECEIVED on_bytes_received, void* on_bytes_received_context, ON_IO_ERROR on_io_error, void* on_io_error_context)
XinZhangMS 0:f7f1f0d76dd6 704 {
XinZhangMS 0:f7f1f0d76dd6 705 int result;
XinZhangMS 0:f7f1f0d76dd6 706
XinZhangMS 0:f7f1f0d76dd6 707 /* Codes_SRS_HTTP_PROXY_IO_01_051: [ The arguments `on_io_open_complete_context`, `on_bytes_received_context` and `on_io_error_context` shall be allowed to be NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 708 /* Codes_SRS_HTTP_PROXY_IO_01_018: [ If any of the arguments `http_proxy_io`, `on_io_open_complete`, `on_bytes_received` or `on_io_error` are NULL then `http_proxy_io_open` shall return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 709 if ((http_proxy_io == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 710 (on_io_open_complete == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 711 (on_bytes_received == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 712 (on_io_error == NULL))
XinZhangMS 0:f7f1f0d76dd6 713 {
XinZhangMS 0:f7f1f0d76dd6 714 LogError("Bad arguments: http_proxy_io = %p, on_io_open_complete = %p, on_bytes_received = %p, on_io_error_context = %p.",
XinZhangMS 0:f7f1f0d76dd6 715 http_proxy_io,
XinZhangMS 0:f7f1f0d76dd6 716 on_io_open_complete,
XinZhangMS 0:f7f1f0d76dd6 717 on_bytes_received,
XinZhangMS 0:f7f1f0d76dd6 718 on_io_error);
XinZhangMS 0:f7f1f0d76dd6 719 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 720 }
XinZhangMS 0:f7f1f0d76dd6 721 else
XinZhangMS 0:f7f1f0d76dd6 722 {
XinZhangMS 0:f7f1f0d76dd6 723 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
XinZhangMS 0:f7f1f0d76dd6 724
XinZhangMS 0:f7f1f0d76dd6 725 if (http_proxy_io_instance->http_proxy_io_state != HTTP_PROXY_IO_STATE_CLOSED)
XinZhangMS 0:f7f1f0d76dd6 726 {
XinZhangMS 0:f7f1f0d76dd6 727 LogError("Invalid tlsio_state. Expected state is HTTP_PROXY_IO_STATE_CLOSED.");
XinZhangMS 0:f7f1f0d76dd6 728 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 729 }
XinZhangMS 0:f7f1f0d76dd6 730 else
XinZhangMS 0:f7f1f0d76dd6 731 {
XinZhangMS 0:f7f1f0d76dd6 732 http_proxy_io_instance->on_bytes_received = on_bytes_received;
XinZhangMS 0:f7f1f0d76dd6 733 http_proxy_io_instance->on_bytes_received_context = on_bytes_received_context;
XinZhangMS 0:f7f1f0d76dd6 734
XinZhangMS 0:f7f1f0d76dd6 735 http_proxy_io_instance->on_io_error = on_io_error;
XinZhangMS 0:f7f1f0d76dd6 736 http_proxy_io_instance->on_io_error_context = on_io_error_context;
XinZhangMS 0:f7f1f0d76dd6 737
XinZhangMS 0:f7f1f0d76dd6 738 http_proxy_io_instance->on_io_open_complete = on_io_open_complete;
XinZhangMS 0:f7f1f0d76dd6 739 http_proxy_io_instance->on_io_open_complete_context = on_io_open_complete_context;
XinZhangMS 0:f7f1f0d76dd6 740
XinZhangMS 0:f7f1f0d76dd6 741 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO;
XinZhangMS 0:f7f1f0d76dd6 742
XinZhangMS 0:f7f1f0d76dd6 743 /* Codes_SRS_HTTP_PROXY_IO_01_019: [ `http_proxy_io_open` shall open the underlying IO by calling `xio_open` on the underlying IO handle created in `http_proxy_io_create`, while passing to it the callbacks `on_underlying_io_open_complete`, `on_underlying_io_bytes_received` and `on_underlying_io_error`. ]*/
XinZhangMS 0:f7f1f0d76dd6 744 if (xio_open(http_proxy_io_instance->underlying_io, on_underlying_io_open_complete, http_proxy_io_instance, on_underlying_io_bytes_received, http_proxy_io_instance, on_underlying_io_error, http_proxy_io_instance) != 0)
XinZhangMS 0:f7f1f0d76dd6 745 {
XinZhangMS 0:f7f1f0d76dd6 746 /* Codes_SRS_HTTP_PROXY_IO_01_020: [ If `xio_open` fails, then `http_proxy_io_open` shall return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 747 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
XinZhangMS 0:f7f1f0d76dd6 748 LogError("Cannot open the underlying IO.");
XinZhangMS 0:f7f1f0d76dd6 749 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 750 }
XinZhangMS 0:f7f1f0d76dd6 751 else
XinZhangMS 0:f7f1f0d76dd6 752 {
XinZhangMS 0:f7f1f0d76dd6 753 /* Codes_SRS_HTTP_PROXY_IO_01_017: [ `http_proxy_io_open` shall open the HTTP proxy IO and on success it shall return 0. ]*/
XinZhangMS 0:f7f1f0d76dd6 754 result = 0;
XinZhangMS 0:f7f1f0d76dd6 755 }
XinZhangMS 0:f7f1f0d76dd6 756 }
XinZhangMS 0:f7f1f0d76dd6 757 }
XinZhangMS 0:f7f1f0d76dd6 758
XinZhangMS 0:f7f1f0d76dd6 759 return result;
XinZhangMS 0:f7f1f0d76dd6 760 }
XinZhangMS 0:f7f1f0d76dd6 761
XinZhangMS 0:f7f1f0d76dd6 762 static int http_proxy_io_close(CONCRETE_IO_HANDLE http_proxy_io, ON_IO_CLOSE_COMPLETE on_io_close_complete, void* on_io_close_complete_context)
XinZhangMS 0:f7f1f0d76dd6 763 {
XinZhangMS 0:f7f1f0d76dd6 764 int result = 0;
XinZhangMS 0:f7f1f0d76dd6 765
XinZhangMS 0:f7f1f0d76dd6 766 /* Codes_SRS_HTTP_PROXY_IO_01_052: [ `on_io_close_complete_context` shall be allowed to be NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 767 /* Codes_SRS_HTTP_PROXY_IO_01_028: [ `on_io_close_complete` shall be allowed to be NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 768 if (http_proxy_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 769 {
XinZhangMS 0:f7f1f0d76dd6 770 /* Codes_SRS_HTTP_PROXY_IO_01_023: [ If the argument `http_proxy_io` is NULL, `http_proxy_io_close` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 771 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 772 LogError("NULL http_proxy_io.");
XinZhangMS 0:f7f1f0d76dd6 773 }
XinZhangMS 0:f7f1f0d76dd6 774 else
XinZhangMS 0:f7f1f0d76dd6 775 {
XinZhangMS 0:f7f1f0d76dd6 776 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
XinZhangMS 0:f7f1f0d76dd6 777
XinZhangMS 0:f7f1f0d76dd6 778 /* Codes_SRS_HTTP_PROXY_IO_01_027: [ If `http_proxy_io_close` is called when not open, `http_proxy_io_close` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 779 if ((http_proxy_io_instance->http_proxy_io_state == HTTP_PROXY_IO_STATE_CLOSED) ||
XinZhangMS 0:f7f1f0d76dd6 780 /* Codes_SRS_HTTP_PROXY_IO_01_054: [ `http_proxy_io_close` while OPENING shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 781 (http_proxy_io_instance->http_proxy_io_state == HTTP_PROXY_IO_STATE_CLOSING))
XinZhangMS 0:f7f1f0d76dd6 782 {
XinZhangMS 0:f7f1f0d76dd6 783 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 784 LogError("Invalid tlsio_state. Expected state is HTTP_PROXY_IO_STATE_OPEN.");
XinZhangMS 0:f7f1f0d76dd6 785 }
XinZhangMS 0:f7f1f0d76dd6 786 else if ((http_proxy_io_instance->http_proxy_io_state == HTTP_PROXY_IO_STATE_OPENING_UNDERLYING_IO) ||
XinZhangMS 0:f7f1f0d76dd6 787 (http_proxy_io_instance->http_proxy_io_state == HTTP_PROXY_IO_STATE_WAITING_FOR_CONNECT_RESPONSE))
XinZhangMS 0:f7f1f0d76dd6 788 {
XinZhangMS 0:f7f1f0d76dd6 789 /* Codes_SRS_HTTP_PROXY_IO_01_053: [ `http_proxy_io_close` while OPENING shall trigger the `on_io_open_complete` callback with `IO_OPEN_CANCELLED`. ]*/
XinZhangMS 0:f7f1f0d76dd6 790 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSED;
XinZhangMS 0:f7f1f0d76dd6 791 (void)xio_close(http_proxy_io_instance->underlying_io, NULL, NULL);
XinZhangMS 0:f7f1f0d76dd6 792 http_proxy_io_instance->on_io_open_complete(http_proxy_io_instance->on_io_open_complete_context, IO_OPEN_CANCELLED);
XinZhangMS 0:f7f1f0d76dd6 793
XinZhangMS 0:f7f1f0d76dd6 794 /* Codes_SRS_HTTP_PROXY_IO_01_022: [ `http_proxy_io_close` shall close the HTTP proxy IO and on success it shall return 0. ]*/
XinZhangMS 0:f7f1f0d76dd6 795 result = 0;
XinZhangMS 0:f7f1f0d76dd6 796 }
XinZhangMS 0:f7f1f0d76dd6 797 else
XinZhangMS 0:f7f1f0d76dd6 798 {
XinZhangMS 0:f7f1f0d76dd6 799 HTTP_PROXY_IO_STATE previous_state = http_proxy_io_instance->http_proxy_io_state;
XinZhangMS 0:f7f1f0d76dd6 800
XinZhangMS 0:f7f1f0d76dd6 801 http_proxy_io_instance->http_proxy_io_state = HTTP_PROXY_IO_STATE_CLOSING;
XinZhangMS 0:f7f1f0d76dd6 802
XinZhangMS 0:f7f1f0d76dd6 803 /* Codes_SRS_HTTP_PROXY_IO_01_026: [ The `on_io_close_complete` and `on_io_close_complete_context` arguments shall be saved for later use. ]*/
XinZhangMS 0:f7f1f0d76dd6 804 http_proxy_io_instance->on_io_close_complete = on_io_close_complete;
XinZhangMS 0:f7f1f0d76dd6 805 http_proxy_io_instance->on_io_close_complete_context = on_io_close_complete_context;
XinZhangMS 0:f7f1f0d76dd6 806
XinZhangMS 0:f7f1f0d76dd6 807 /* Codes_SRS_HTTP_PROXY_IO_01_024: [ `http_proxy_io_close` shall close the underlying IO by calling `xio_close` on the IO handle create in `http_proxy_io_create`, while passing to it the `on_underlying_io_close_complete` callback. ]*/
XinZhangMS 0:f7f1f0d76dd6 808 if (xio_close(http_proxy_io_instance->underlying_io, on_underlying_io_close_complete, http_proxy_io_instance) != 0)
XinZhangMS 0:f7f1f0d76dd6 809 {
XinZhangMS 0:f7f1f0d76dd6 810 /* Codes_SRS_HTTP_PROXY_IO_01_025: [ If `xio_close` fails, `http_proxy_io_close` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 811 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 812 http_proxy_io_instance->http_proxy_io_state = previous_state;
XinZhangMS 0:f7f1f0d76dd6 813 LogError("Cannot close underlying IO.");
XinZhangMS 0:f7f1f0d76dd6 814 }
XinZhangMS 0:f7f1f0d76dd6 815 else
XinZhangMS 0:f7f1f0d76dd6 816 {
XinZhangMS 0:f7f1f0d76dd6 817 /* Codes_SRS_HTTP_PROXY_IO_01_022: [ `http_proxy_io_close` shall close the HTTP proxy IO and on success it shall return 0. ]*/
XinZhangMS 0:f7f1f0d76dd6 818 result = 0;
XinZhangMS 0:f7f1f0d76dd6 819 }
XinZhangMS 0:f7f1f0d76dd6 820 }
XinZhangMS 0:f7f1f0d76dd6 821 }
XinZhangMS 0:f7f1f0d76dd6 822
XinZhangMS 0:f7f1f0d76dd6 823 return result;
XinZhangMS 0:f7f1f0d76dd6 824 }
XinZhangMS 0:f7f1f0d76dd6 825
XinZhangMS 0:f7f1f0d76dd6 826 static int http_proxy_io_send(CONCRETE_IO_HANDLE http_proxy_io, const void* buffer, size_t size, ON_SEND_COMPLETE on_send_complete, void* on_send_complete_context)
XinZhangMS 0:f7f1f0d76dd6 827 {
XinZhangMS 0:f7f1f0d76dd6 828 int result;
XinZhangMS 0:f7f1f0d76dd6 829
XinZhangMS 0:f7f1f0d76dd6 830 /* Codes_SRS_HTTP_PROXY_IO_01_032: [ `on_send_complete` shall be allowed to be NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 831 /* Codes_SRS_HTTP_PROXY_IO_01_030: [ If any of the arguments `http_proxy_io` or `buffer` is NULL, `http_proxy_io_send` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 832 if ((http_proxy_io == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 833 (buffer == NULL) ||
XinZhangMS 0:f7f1f0d76dd6 834 /* Codes_SRS_HTTP_PROXY_IO_01_031: [ If `size` is 0, `http_proxy_io_send` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 835 (size == 0))
XinZhangMS 0:f7f1f0d76dd6 836 {
XinZhangMS 0:f7f1f0d76dd6 837 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 838 LogError("Bad arguments: http_proxy_io = %p, buffer = %p.",
XinZhangMS 0:f7f1f0d76dd6 839 http_proxy_io, buffer);
XinZhangMS 0:f7f1f0d76dd6 840 }
XinZhangMS 0:f7f1f0d76dd6 841 else
XinZhangMS 0:f7f1f0d76dd6 842 {
XinZhangMS 0:f7f1f0d76dd6 843 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
XinZhangMS 0:f7f1f0d76dd6 844
XinZhangMS 0:f7f1f0d76dd6 845 /* Codes_SRS_HTTP_PROXY_IO_01_034: [ If `http_proxy_io_send` is called when the IO is not open, `http_proxy_io_send` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 846 /* Codes_SRS_HTTP_PROXY_IO_01_035: [ If the IO is in an error state (an error was reported through the `on_io_error` callback), `http_proxy_io_send` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 847 if (http_proxy_io_instance->http_proxy_io_state != HTTP_PROXY_IO_STATE_OPEN)
XinZhangMS 0:f7f1f0d76dd6 848 {
XinZhangMS 0:f7f1f0d76dd6 849 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 850 LogError("Invalid HTTP proxy IO state. Expected state is HTTP_PROXY_IO_STATE_OPEN.");
XinZhangMS 0:f7f1f0d76dd6 851 }
XinZhangMS 0:f7f1f0d76dd6 852 else
XinZhangMS 0:f7f1f0d76dd6 853 {
XinZhangMS 0:f7f1f0d76dd6 854 /* Codes_SRS_HTTP_PROXY_IO_01_033: [ `http_proxy_io_send` shall send the bytes by calling `xio_send` on the underlying IO created in `http_proxy_io_create` and passing `buffer` and `size` as arguments. ]*/
XinZhangMS 0:f7f1f0d76dd6 855 if (xio_send(http_proxy_io_instance->underlying_io, buffer, size, on_send_complete, on_send_complete_context) != 0)
XinZhangMS 0:f7f1f0d76dd6 856 {
XinZhangMS 0:f7f1f0d76dd6 857 /* Codes_SRS_HTTP_PROXY_IO_01_055: [ If `xio_send` fails, `http_proxy_io_send` shall fail and return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 858 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 859 LogError("Underlying xio_send failed.");
XinZhangMS 0:f7f1f0d76dd6 860 }
XinZhangMS 0:f7f1f0d76dd6 861 else
XinZhangMS 0:f7f1f0d76dd6 862 {
XinZhangMS 0:f7f1f0d76dd6 863 /* Codes_SRS_HTTP_PROXY_IO_01_029: [ `http_proxy_io_send` shall send the `size` bytes pointed to by `buffer` and on success it shall return 0. ]*/
XinZhangMS 0:f7f1f0d76dd6 864 result = 0;
XinZhangMS 0:f7f1f0d76dd6 865 }
XinZhangMS 0:f7f1f0d76dd6 866 }
XinZhangMS 0:f7f1f0d76dd6 867 }
XinZhangMS 0:f7f1f0d76dd6 868
XinZhangMS 0:f7f1f0d76dd6 869 return result;
XinZhangMS 0:f7f1f0d76dd6 870 }
XinZhangMS 0:f7f1f0d76dd6 871
XinZhangMS 0:f7f1f0d76dd6 872 static void http_proxy_io_dowork(CONCRETE_IO_HANDLE http_proxy_io)
XinZhangMS 0:f7f1f0d76dd6 873 {
XinZhangMS 0:f7f1f0d76dd6 874 if (http_proxy_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 875 {
XinZhangMS 0:f7f1f0d76dd6 876 /* Codes_SRS_HTTP_PROXY_IO_01_038: [ If the `http_proxy_io` argument is NULL, `http_proxy_io_dowork` shall do nothing. ]*/
XinZhangMS 0:f7f1f0d76dd6 877 LogError("NULL http_proxy_io.");
XinZhangMS 0:f7f1f0d76dd6 878 }
XinZhangMS 0:f7f1f0d76dd6 879 else
XinZhangMS 0:f7f1f0d76dd6 880 {
XinZhangMS 0:f7f1f0d76dd6 881 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
XinZhangMS 0:f7f1f0d76dd6 882
XinZhangMS 0:f7f1f0d76dd6 883 if (http_proxy_io_instance->http_proxy_io_state != HTTP_PROXY_IO_STATE_CLOSED)
XinZhangMS 0:f7f1f0d76dd6 884 {
XinZhangMS 0:f7f1f0d76dd6 885 /* Codes_SRS_HTTP_PROXY_IO_01_037: [ `http_proxy_io_dowork` shall call `xio_dowork` on the underlying IO created in `http_proxy_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 886 xio_dowork(http_proxy_io_instance->underlying_io);
XinZhangMS 0:f7f1f0d76dd6 887 }
XinZhangMS 0:f7f1f0d76dd6 888 }
XinZhangMS 0:f7f1f0d76dd6 889 }
XinZhangMS 0:f7f1f0d76dd6 890
XinZhangMS 0:f7f1f0d76dd6 891 static int http_proxy_io_set_option(CONCRETE_IO_HANDLE http_proxy_io, const char* option_name, const void* value)
XinZhangMS 0:f7f1f0d76dd6 892 {
XinZhangMS 0:f7f1f0d76dd6 893 int result;
XinZhangMS 0:f7f1f0d76dd6 894
XinZhangMS 0:f7f1f0d76dd6 895 if ((http_proxy_io == NULL) || (option_name == NULL))
XinZhangMS 0:f7f1f0d76dd6 896 {
XinZhangMS 0:f7f1f0d76dd6 897 /* Codes_SRS_HTTP_PROXY_IO_01_040: [ If any of the arguments `http_proxy_io` or `option_name` is NULL, `http_proxy_io_set_option` shall return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 898 LogError("Bad arguments: http_proxy_io = %p, option_name = %p",
XinZhangMS 0:f7f1f0d76dd6 899 http_proxy_io, option_name);
XinZhangMS 0:f7f1f0d76dd6 900 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 901 }
XinZhangMS 0:f7f1f0d76dd6 902 else
XinZhangMS 0:f7f1f0d76dd6 903 {
XinZhangMS 0:f7f1f0d76dd6 904 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
XinZhangMS 0:f7f1f0d76dd6 905
XinZhangMS 0:f7f1f0d76dd6 906 /* Codes_SRS_HTTP_PROXY_IO_01_045: [ None. ]*/
XinZhangMS 0:f7f1f0d76dd6 907
XinZhangMS 0:f7f1f0d76dd6 908 /* Codes_SRS_HTTP_PROXY_IO_01_043: [ If the `option_name` argument indicates an option that is not handled by `http_proxy_io_set_option`, then `xio_setoption` shall be called on the underlying IO created in `http_proxy_io_create`, passing the option name and value to it. ]*/
XinZhangMS 0:f7f1f0d76dd6 909 /* Codes_SRS_HTTP_PROXY_IO_01_056: [ The `value` argument shall be allowed to be NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 910 if (xio_setoption(http_proxy_io_instance->underlying_io, option_name, value) != 0)
XinZhangMS 0:f7f1f0d76dd6 911 {
XinZhangMS 0:f7f1f0d76dd6 912 /* Codes_SRS_HTTP_PROXY_IO_01_044: [ if `xio_setoption` fails, `http_proxy_io_set_option` shall return a non-zero value. ]*/
XinZhangMS 0:f7f1f0d76dd6 913 LogError("Unrecognized option");
XinZhangMS 0:f7f1f0d76dd6 914 result = __LINE__;
XinZhangMS 0:f7f1f0d76dd6 915 }
XinZhangMS 0:f7f1f0d76dd6 916 else
XinZhangMS 0:f7f1f0d76dd6 917 {
XinZhangMS 0:f7f1f0d76dd6 918 /* Codes_SRS_HTTP_PROXY_IO_01_042: [ If the option was handled by `http_proxy_io_set_option` or the underlying IO, then `http_proxy_io_set_option` shall return 0. ]*/
XinZhangMS 0:f7f1f0d76dd6 919 result = 0;
XinZhangMS 0:f7f1f0d76dd6 920 }
XinZhangMS 0:f7f1f0d76dd6 921 }
XinZhangMS 0:f7f1f0d76dd6 922
XinZhangMS 0:f7f1f0d76dd6 923 return result;
XinZhangMS 0:f7f1f0d76dd6 924 }
XinZhangMS 0:f7f1f0d76dd6 925
XinZhangMS 0:f7f1f0d76dd6 926 static OPTIONHANDLER_HANDLE http_proxy_io_retrieve_options(CONCRETE_IO_HANDLE http_proxy_io)
XinZhangMS 0:f7f1f0d76dd6 927 {
XinZhangMS 0:f7f1f0d76dd6 928 OPTIONHANDLER_HANDLE result;
XinZhangMS 0:f7f1f0d76dd6 929
XinZhangMS 0:f7f1f0d76dd6 930 if (http_proxy_io == NULL)
XinZhangMS 0:f7f1f0d76dd6 931 {
XinZhangMS 0:f7f1f0d76dd6 932 /* Codes_SRS_HTTP_PROXY_IO_01_047: [ If the parameter `http_proxy_io` is NULL then `http_proxy_io_retrieve_options` shall fail and return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 933 LogError("invalid parameter detected: CONCRETE_IO_HANDLE handle=%p", http_proxy_io);
XinZhangMS 0:f7f1f0d76dd6 934 result = NULL;
XinZhangMS 0:f7f1f0d76dd6 935 }
XinZhangMS 0:f7f1f0d76dd6 936 else
XinZhangMS 0:f7f1f0d76dd6 937 {
XinZhangMS 0:f7f1f0d76dd6 938 HTTP_PROXY_IO_INSTANCE* http_proxy_io_instance = (HTTP_PROXY_IO_INSTANCE*)http_proxy_io;
XinZhangMS 0:f7f1f0d76dd6 939
XinZhangMS 0:f7f1f0d76dd6 940 /* Codes_SRS_HTTP_PROXY_IO_01_046: [ `http_proxy_io_retrieve_options` shall return an `OPTIONHANDLER_HANDLE` obtained by calling `xio_retrieveoptions` on the underlying IO created in `http_proxy_io_create`. ]*/
XinZhangMS 0:f7f1f0d76dd6 941 result = xio_retrieveoptions(http_proxy_io_instance->underlying_io);
XinZhangMS 0:f7f1f0d76dd6 942 if (result == NULL)
XinZhangMS 0:f7f1f0d76dd6 943 {
XinZhangMS 0:f7f1f0d76dd6 944 /* Codes_SRS_HTTP_PROXY_IO_01_048: [ If `xio_retrieveoptions` fails, `http_proxy_io_retrieve_options` shall return NULL. ]*/
XinZhangMS 0:f7f1f0d76dd6 945 LogError("unable to create option handler");
XinZhangMS 0:f7f1f0d76dd6 946 }
XinZhangMS 0:f7f1f0d76dd6 947 }
XinZhangMS 0:f7f1f0d76dd6 948 return result;
XinZhangMS 0:f7f1f0d76dd6 949 }
XinZhangMS 0:f7f1f0d76dd6 950
XinZhangMS 0:f7f1f0d76dd6 951 static const IO_INTERFACE_DESCRIPTION http_proxy_io_interface_description =
XinZhangMS 0:f7f1f0d76dd6 952 {
XinZhangMS 0:f7f1f0d76dd6 953 http_proxy_io_retrieve_options,
XinZhangMS 0:f7f1f0d76dd6 954 http_proxy_io_create,
XinZhangMS 0:f7f1f0d76dd6 955 http_proxy_io_destroy,
XinZhangMS 0:f7f1f0d76dd6 956 http_proxy_io_open,
XinZhangMS 0:f7f1f0d76dd6 957 http_proxy_io_close,
XinZhangMS 0:f7f1f0d76dd6 958 http_proxy_io_send,
XinZhangMS 0:f7f1f0d76dd6 959 http_proxy_io_dowork,
XinZhangMS 0:f7f1f0d76dd6 960 http_proxy_io_set_option
XinZhangMS 0:f7f1f0d76dd6 961 };
XinZhangMS 0:f7f1f0d76dd6 962
XinZhangMS 0:f7f1f0d76dd6 963 const IO_INTERFACE_DESCRIPTION* http_proxy_io_get_interface_description(void)
XinZhangMS 0:f7f1f0d76dd6 964 {
XinZhangMS 0:f7f1f0d76dd6 965 /* Codes_SRS_HTTP_PROXY_IO_01_049: [ `http_proxy_io_get_interface_description` shall return a pointer to an `IO_INTERFACE_DESCRIPTION` structure that contains pointers to the functions: `http_proxy_io_retrieve_options`, `http_proxy_io_retrieve_create`, `http_proxy_io_destroy`, `http_proxy_io_open`, `http_proxy_io_close`, `http_proxy_io_send` and `http_proxy_io_dowork`. ]*/
XinZhangMS 0:f7f1f0d76dd6 966 return &http_proxy_io_interface_description;
XinZhangMS 0:f7f1f0d76dd6 967 }