Fork of SandBox's original mbed-http (https://os.mbed.com/teams/sandbox/code/mbed-http/) and update for MbedOS6+ Content of TESTS folder was replaced with basic examples form original SandBox's HelloWorld

Committer:
Jan Jongboom
Date:
Thu Jan 11 13:49:06 2018 +0100
Revision:
23:15fa2726f793
Parent:
20:0e63d6a93c02
Child:
29:383e9bfbfbed
Child:
31:b3730a2c4f39
Implement Transfer-Encoding: chunked on HTTP and HTTPS requests, allows streaming large blocks of data over HTTP

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Jan Jongboom 0:910f5949759f 1 /*
Jan Jongboom 0:910f5949759f 2 * PackageLicenseDeclared: Apache-2.0
Jan Jongboom 0:910f5949759f 3 * Copyright (c) 2017 ARM Limited
Jan Jongboom 0:910f5949759f 4 *
Jan Jongboom 0:910f5949759f 5 * Licensed under the Apache License, Version 2.0 (the "License");
Jan Jongboom 0:910f5949759f 6 * you may not use this file except in compliance with the License.
Jan Jongboom 0:910f5949759f 7 * You may obtain a copy of the License at
Jan Jongboom 0:910f5949759f 8 *
Jan Jongboom 0:910f5949759f 9 * http://www.apache.org/licenses/LICENSE-2.0
Jan Jongboom 0:910f5949759f 10 *
Jan Jongboom 0:910f5949759f 11 * Unless required by applicable law or agreed to in writing, software
Jan Jongboom 0:910f5949759f 12 * distributed under the License is distributed on an "AS IS" BASIS,
Jan Jongboom 0:910f5949759f 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Jan Jongboom 0:910f5949759f 14 * See the License for the specific language governing permissions and
Jan Jongboom 0:910f5949759f 15 * limitations under the License.
Jan Jongboom 0:910f5949759f 16 */
Jan Jongboom 0:910f5949759f 17
Jan Jongboom 0:910f5949759f 18 #ifndef _MBED_HTTPS_REQUEST_H_
Jan Jongboom 0:910f5949759f 19 #define _MBED_HTTPS_REQUEST_H_
Jan Jongboom 0:910f5949759f 20
Jan Jongboom 0:910f5949759f 21 #include <string>
Jan Jongboom 0:910f5949759f 22 #include <vector>
Jan Jongboom 0:910f5949759f 23 #include <map>
Jan Jongboom 0:910f5949759f 24 #include "http_parser.h"
Jan Jongboom 0:910f5949759f 25 #include "http_response.h"
Jan Jongboom 0:910f5949759f 26 #include "http_request_builder.h"
Jan Jongboom 15:ffc77f212382 27 #include "http_request_parser.h"
Jan Jongboom 0:910f5949759f 28 #include "http_parsed_url.h"
Jan Jongboom 11:96e4dcb9c0c2 29 #include "tls_socket.h"
Jan Jongboom 0:910f5949759f 30
Jan Jongboom 20:0e63d6a93c02 31 #ifndef HTTP_RECEIVE_BUFFER_SIZE
Jan Jongboom 20:0e63d6a93c02 32 #define HTTP_RECEIVE_BUFFER_SIZE 8 * 1024
Jan Jongboom 20:0e63d6a93c02 33 #endif
Jan Jongboom 20:0e63d6a93c02 34
Jan Jongboom 0:910f5949759f 35 /**
Jan Jongboom 0:910f5949759f 36 * \brief HttpsRequest implements the logic for interacting with HTTPS servers.
Jan Jongboom 0:910f5949759f 37 */
Jan Jongboom 0:910f5949759f 38 class HttpsRequest {
Jan Jongboom 0:910f5949759f 39 public:
Jan Jongboom 0:910f5949759f 40 /**
Jan Jongboom 0:910f5949759f 41 * HttpsRequest Constructor
Jan Jongboom 0:910f5949759f 42 * Initializes the TCP socket, sets up event handlers and flags.
Jan Jongboom 0:910f5949759f 43 *
Jan Jongboom 0:910f5949759f 44 * @param[in] net_iface The network interface
Jan Jongboom 0:910f5949759f 45 * @param[in] ssl_ca_pem String containing the trusted CAs
Jan Jongboom 0:910f5949759f 46 * @param[in] method HTTP method to use
Jan Jongboom 0:910f5949759f 47 * @param[in] url URL to the resource
Jan Jongboom 0:910f5949759f 48 * @param[in] body_callback Callback on which to retrieve chunks of the response body.
Jan Jongboom 0:910f5949759f 49 If not set, the complete body will be allocated on the HttpResponse object,
Jan Jongboom 0:910f5949759f 50 which might use lots of memory.
Jan Jongboom 0:910f5949759f 51 */
Jan Jongboom 0:910f5949759f 52 HttpsRequest(NetworkInterface* net_iface,
Jan Jongboom 0:910f5949759f 53 const char* ssl_ca_pem,
Jan Jongboom 0:910f5949759f 54 http_method method,
Jan Jongboom 0:910f5949759f 55 const char* url,
Jan Jongboom 0:910f5949759f 56 Callback<void(const char *at, size_t length)> body_callback = 0)
Jan Jongboom 0:910f5949759f 57 {
Jan Jongboom 0:910f5949759f 58 _parsed_url = new ParsedUrl(url);
Jan Jongboom 0:910f5949759f 59 _body_callback = body_callback;
Jan Jongboom 0:910f5949759f 60 _request_builder = new HttpRequestBuilder(method, _parsed_url);
Jan Jongboom 0:910f5949759f 61 _response = NULL;
Jan Jongboom 0:910f5949759f 62 _debug = false;
Jan Jongboom 0:910f5949759f 63
Jan Jongboom 11:96e4dcb9c0c2 64 _tlssocket = new TLSSocket(net_iface, _parsed_url->host(), _parsed_url->port(), ssl_ca_pem);
Jan Jongboom 11:96e4dcb9c0c2 65 _we_created_the_socket = true;
Jan Jongboom 11:96e4dcb9c0c2 66 }
Jan Jongboom 0:910f5949759f 67
Jan Jongboom 11:96e4dcb9c0c2 68 /**
Jan Jongboom 11:96e4dcb9c0c2 69 * HttpsRequest Constructor
Jan Jongboom 11:96e4dcb9c0c2 70 * Sets up event handlers and flags.
Jan Jongboom 11:96e4dcb9c0c2 71 *
Jan Jongboom 11:96e4dcb9c0c2 72 * @param[in] socket A connected TLSSocket
Jan Jongboom 11:96e4dcb9c0c2 73 * @param[in] method HTTP method to use
Jan Jongboom 11:96e4dcb9c0c2 74 * @param[in] url URL to the resource
Jan Jongboom 11:96e4dcb9c0c2 75 * @param[in] body_callback Callback on which to retrieve chunks of the response body.
Jan Jongboom 11:96e4dcb9c0c2 76 If not set, the complete body will be allocated on the HttpResponse object,
Jan Jongboom 11:96e4dcb9c0c2 77 which might use lots of memory.
Jan Jongboom 11:96e4dcb9c0c2 78 */
Jan Jongboom 11:96e4dcb9c0c2 79 HttpsRequest(TLSSocket* socket,
Jan Jongboom 11:96e4dcb9c0c2 80 http_method method,
Jan Jongboom 11:96e4dcb9c0c2 81 const char* url,
Jan Jongboom 11:96e4dcb9c0c2 82 Callback<void(const char *at, size_t length)> body_callback = 0)
Jan Jongboom 11:96e4dcb9c0c2 83 {
Jan Jongboom 11:96e4dcb9c0c2 84 _parsed_url = new ParsedUrl(url);
Jan Jongboom 11:96e4dcb9c0c2 85 _body_callback = body_callback;
Jan Jongboom 11:96e4dcb9c0c2 86 _request_builder = new HttpRequestBuilder(method, _parsed_url);
Jan Jongboom 11:96e4dcb9c0c2 87 _response = NULL;
Jan Jongboom 11:96e4dcb9c0c2 88 _debug = false;
Jan Jongboom 11:96e4dcb9c0c2 89
Jan Jongboom 11:96e4dcb9c0c2 90 _tlssocket = socket;
Jan Jongboom 11:96e4dcb9c0c2 91 _we_created_the_socket = false;
Jan Jongboom 0:910f5949759f 92 }
Jan Jongboom 0:910f5949759f 93
Jan Jongboom 0:910f5949759f 94 /**
Jan Jongboom 0:910f5949759f 95 * HttpsRequest Destructor
Jan Jongboom 0:910f5949759f 96 */
Jan Jongboom 0:910f5949759f 97 ~HttpsRequest() {
Jan Jongboom 0:910f5949759f 98 if (_request_builder) {
Jan Jongboom 0:910f5949759f 99 delete _request_builder;
Jan Jongboom 0:910f5949759f 100 }
Jan Jongboom 0:910f5949759f 101
Jan Jongboom 11:96e4dcb9c0c2 102 if (_tlssocket && _we_created_the_socket) {
Jan Jongboom 11:96e4dcb9c0c2 103 delete _tlssocket;
Jan Jongboom 0:910f5949759f 104 }
Jan Jongboom 0:910f5949759f 105
Jan Jongboom 0:910f5949759f 106 if (_parsed_url) {
Jan Jongboom 0:910f5949759f 107 delete _parsed_url;
Jan Jongboom 0:910f5949759f 108 }
Jan Jongboom 0:910f5949759f 109
Jan Jongboom 0:910f5949759f 110 if (_response) {
Jan Jongboom 0:910f5949759f 111 delete _response;
Jan Jongboom 0:910f5949759f 112 }
Jan Jongboom 0:910f5949759f 113 }
Jan Jongboom 0:910f5949759f 114
Jan Jongboom 0:910f5949759f 115 /**
Jan Jongboom 0:910f5949759f 116 * Execute the HTTPS request.
Jan Jongboom 0:910f5949759f 117 *
Jan Jongboom 0:910f5949759f 118 * @param[in] body Pointer to the request body
Jan Jongboom 0:910f5949759f 119 * @param[in] body_size Size of the request body
Jan Jongboom 0:910f5949759f 120 * @return An HttpResponse pointer on success, or NULL on failure.
Jan Jongboom 0:910f5949759f 121 * See get_error() for the error code.
Jan Jongboom 0:910f5949759f 122 */
Jan Jongboom 0:910f5949759f 123 HttpResponse* send(const void* body = NULL, nsapi_size_t body_size = 0) {
Jan Jongboom 23:15fa2726f793 124 nsapi_size_or_error_t ret = open_socket();
Jan Jongboom 23:15fa2726f793 125
Jan Jongboom 23:15fa2726f793 126 if (ret != NSAPI_ERROR_OK) {
Jan Jongboom 23:15fa2726f793 127 _error = ret;
Jan Jongboom 0:910f5949759f 128 return NULL;
Jan Jongboom 0:910f5949759f 129 }
Jan Jongboom 0:910f5949759f 130
Jan Jongboom 10:b017c7d2cf23 131 size_t request_size = 0;
Jan Jongboom 10:b017c7d2cf23 132 char* request = _request_builder->build(body, body_size, request_size);
Jan Jongboom 0:910f5949759f 133
Jan Jongboom 23:15fa2726f793 134 ret = send_buffer((const unsigned char*)request, request_size);
Jan Jongboom 0:910f5949759f 135
Jan Jongboom 0:910f5949759f 136 free(request);
Jan Jongboom 0:910f5949759f 137
Jan Jongboom 0:910f5949759f 138 if (ret < 0) {
Jan Jongboom 23:15fa2726f793 139 _error = ret;
Jan Jongboom 23:15fa2726f793 140 return NULL;
Jan Jongboom 23:15fa2726f793 141 }
Jan Jongboom 23:15fa2726f793 142
Jan Jongboom 23:15fa2726f793 143 return create_http_response();
Jan Jongboom 23:15fa2726f793 144 }
Jan Jongboom 23:15fa2726f793 145
Jan Jongboom 23:15fa2726f793 146 /**
Jan Jongboom 23:15fa2726f793 147 * Execute the HTTPS request.
Jan Jongboom 23:15fa2726f793 148 * This sends the request through chunked-encoding.
Jan Jongboom 23:15fa2726f793 149 * @param body_cb Callback which generates the next chunk of the request
Jan Jongboom 23:15fa2726f793 150 * @return An HttpResponse pointer on success, or NULL on failure.
Jan Jongboom 23:15fa2726f793 151 * See get_error() for the error code.
Jan Jongboom 23:15fa2726f793 152 */
Jan Jongboom 23:15fa2726f793 153 HttpResponse* send(Callback<const void*(size_t*)> body_cb) {
Jan Jongboom 23:15fa2726f793 154
Jan Jongboom 23:15fa2726f793 155 nsapi_error_t ret;
Jan Jongboom 23:15fa2726f793 156
Jan Jongboom 23:15fa2726f793 157 if ((ret = open_socket()) != NSAPI_ERROR_OK) {
Jan Jongboom 23:15fa2726f793 158 _error = ret;
Jan Jongboom 23:15fa2726f793 159 return NULL;
Jan Jongboom 23:15fa2726f793 160 }
Jan Jongboom 23:15fa2726f793 161
Jan Jongboom 23:15fa2726f793 162 set_header("Transfer-Encoding", "chunked");
Jan Jongboom 23:15fa2726f793 163
Jan Jongboom 23:15fa2726f793 164 size_t request_size = 0;
Jan Jongboom 23:15fa2726f793 165 char* request = _request_builder->build(NULL, 0, request_size);
Jan Jongboom 23:15fa2726f793 166
Jan Jongboom 23:15fa2726f793 167 // first... send this request headers without the body
Jan Jongboom 23:15fa2726f793 168 nsapi_size_or_error_t total_send_count = send_buffer((unsigned char*)request, request_size);
Jan Jongboom 23:15fa2726f793 169
Jan Jongboom 23:15fa2726f793 170 if (total_send_count < 0) {
Jan Jongboom 23:15fa2726f793 171 free(request);
Jan Jongboom 23:15fa2726f793 172 _error = total_send_count;
Jan Jongboom 0:910f5949759f 173 return NULL;
Jan Jongboom 0:910f5949759f 174 }
Jan Jongboom 0:910f5949759f 175
Jan Jongboom 23:15fa2726f793 176 // ok... now it's time to start sending chunks...
Jan Jongboom 23:15fa2726f793 177 while (1) {
Jan Jongboom 23:15fa2726f793 178 size_t size;
Jan Jongboom 23:15fa2726f793 179 const void *buffer = body_cb(&size);
Jan Jongboom 0:910f5949759f 180
Jan Jongboom 23:15fa2726f793 181 if (size == 0) break;
Jan Jongboom 0:910f5949759f 182
Jan Jongboom 23:15fa2726f793 183 // so... size in HEX, \r\n, data, \r\n again
Jan Jongboom 23:15fa2726f793 184 char size_buff[10]; // if sending length of more than 8 digits, you have another problem on a microcontroller...
Jan Jongboom 23:15fa2726f793 185 size_t size_buff_size = sprintf(size_buff, "%X\r\n", size);
Jan Jongboom 23:15fa2726f793 186 if ((total_send_count = send_buffer((const unsigned char*)size_buff, size_buff_size)) < 0) {
Jan Jongboom 23:15fa2726f793 187 free(request);
Jan Jongboom 23:15fa2726f793 188 _error = total_send_count;
Jan Jongboom 0:910f5949759f 189 return NULL;
Jan Jongboom 0:910f5949759f 190 }
Jan Jongboom 6:112d72c60e07 191
Jan Jongboom 23:15fa2726f793 192 // now send the normal buffer... and then \r\n at the end
Jan Jongboom 23:15fa2726f793 193 total_send_count = send_buffer((const unsigned char*)buffer, size);
Jan Jongboom 23:15fa2726f793 194 if (total_send_count < 0) {
Jan Jongboom 23:15fa2726f793 195 free(request);
Jan Jongboom 23:15fa2726f793 196 _error = total_send_count;
Jan Jongboom 23:15fa2726f793 197 return NULL;
Jan Jongboom 23:15fa2726f793 198 }
Jan Jongboom 23:15fa2726f793 199
Jan Jongboom 23:15fa2726f793 200 // and... \r\n
Jan Jongboom 23:15fa2726f793 201 const char* rn = "\r\n";
Jan Jongboom 23:15fa2726f793 202 if ((total_send_count = send_buffer((const unsigned char*)rn, 2)) < 0) {
Jan Jongboom 23:15fa2726f793 203 free(request);
Jan Jongboom 23:15fa2726f793 204 _error = total_send_count;
Jan Jongboom 23:15fa2726f793 205 return NULL;
Jan Jongboom 0:910f5949759f 206 }
Jan Jongboom 0:910f5949759f 207 }
Jan Jongboom 23:15fa2726f793 208
Jan Jongboom 23:15fa2726f793 209 // finalize...?
Jan Jongboom 23:15fa2726f793 210 const char* fin = "0\r\n\r\n";
Jan Jongboom 23:15fa2726f793 211 if ((total_send_count = send_buffer((const unsigned char*)fin, strlen(fin))) < 0) {
Jan Jongboom 23:15fa2726f793 212 free(request);
Jan Jongboom 23:15fa2726f793 213 _error = total_send_count;
Jan Jongboom 0:910f5949759f 214 return NULL;
Jan Jongboom 0:910f5949759f 215 }
Jan Jongboom 0:910f5949759f 216
Jan Jongboom 23:15fa2726f793 217 free(request);
Jan Jongboom 0:910f5949759f 218
Jan Jongboom 23:15fa2726f793 219 return create_http_response();
Jan Jongboom 0:910f5949759f 220 }
Jan Jongboom 0:910f5949759f 221
Jan Jongboom 0:910f5949759f 222 /**
Jan Jongboom 11:96e4dcb9c0c2 223 * Closes the underlying TCP socket
Jan Jongboom 0:910f5949759f 224 */
Jan Jongboom 0:910f5949759f 225 void close() {
Jan Jongboom 11:96e4dcb9c0c2 226 _tlssocket->get_tcp_socket()->close();
Jan Jongboom 0:910f5949759f 227 }
Jan Jongboom 0:910f5949759f 228
Jan Jongboom 0:910f5949759f 229 /**
Jan Jongboom 0:910f5949759f 230 * Set a header for the request.
Jan Jongboom 0:910f5949759f 231 *
Jan Jongboom 0:910f5949759f 232 * The 'Host' and 'Content-Length' headers are set automatically.
Jan Jongboom 0:910f5949759f 233 * Setting the same header twice will overwrite the previous entry.
Jan Jongboom 0:910f5949759f 234 *
Jan Jongboom 0:910f5949759f 235 * @param[in] key Header key
Jan Jongboom 0:910f5949759f 236 * @param[in] value Header value
Jan Jongboom 0:910f5949759f 237 */
Jan Jongboom 0:910f5949759f 238 void set_header(string key, string value) {
Jan Jongboom 0:910f5949759f 239 _request_builder->set_header(key, value);
Jan Jongboom 0:910f5949759f 240 }
Jan Jongboom 0:910f5949759f 241
Jan Jongboom 0:910f5949759f 242 /**
Jan Jongboom 0:910f5949759f 243 * Get the error code.
Jan Jongboom 0:910f5949759f 244 *
Jan Jongboom 0:910f5949759f 245 * When send() fails, this error is set.
Jan Jongboom 0:910f5949759f 246 */
Jan Jongboom 0:910f5949759f 247 nsapi_error_t get_error() {
Jan Jongboom 0:910f5949759f 248 return _error;
Jan Jongboom 0:910f5949759f 249 }
Jan Jongboom 0:910f5949759f 250
Jan Jongboom 0:910f5949759f 251 /**
Jan Jongboom 0:910f5949759f 252 * Set the debug flag.
Jan Jongboom 0:910f5949759f 253 *
Jan Jongboom 0:910f5949759f 254 * If this flag is set, debug information from mbed TLS will be logged to stdout.
Jan Jongboom 0:910f5949759f 255 */
Jan Jongboom 0:910f5949759f 256 void set_debug(bool debug) {
Jan Jongboom 0:910f5949759f 257 _debug = debug;
Jan Jongboom 11:96e4dcb9c0c2 258
Jan Jongboom 11:96e4dcb9c0c2 259 _tlssocket->set_debug(debug);
Jan Jongboom 0:910f5949759f 260 }
Jan Jongboom 0:910f5949759f 261
Jan Jongboom 11:96e4dcb9c0c2 262
Jan Jongboom 0:910f5949759f 263 protected:
Jan Jongboom 0:910f5949759f 264 /**
Jan Jongboom 0:910f5949759f 265 * Helper for pretty-printing mbed TLS error codes
Jan Jongboom 0:910f5949759f 266 */
Jan Jongboom 0:910f5949759f 267 static void print_mbedtls_error(const char *name, int err) {
Jan Jongboom 0:910f5949759f 268 char buf[128];
Jan Jongboom 0:910f5949759f 269 mbedtls_strerror(err, buf, sizeof (buf));
Jan Jongboom 0:910f5949759f 270 mbedtls_printf("%s() failed: -0x%04x (%d): %s\r\n", name, -err, err, buf);
Jan Jongboom 0:910f5949759f 271 }
Jan Jongboom 0:910f5949759f 272
Jan Jongboom 0:910f5949759f 273 void onError(TCPSocket *s, int error) {
Jan Jongboom 0:910f5949759f 274 s->close();
Jan Jongboom 0:910f5949759f 275 _error = error;
Jan Jongboom 0:910f5949759f 276 }
Jan Jongboom 0:910f5949759f 277
Jan Jongboom 23:15fa2726f793 278 nsapi_error_t onErrorAndReturn(TCPSocket *s, int error) {
Jan Jongboom 23:15fa2726f793 279 s->close();
Jan Jongboom 23:15fa2726f793 280 return error;
Jan Jongboom 23:15fa2726f793 281 }
Jan Jongboom 23:15fa2726f793 282
Jan Jongboom 23:15fa2726f793 283 private:
Jan Jongboom 23:15fa2726f793 284 nsapi_error_t open_socket() {
Jan Jongboom 23:15fa2726f793 285 // not tried to connect before?
Jan Jongboom 23:15fa2726f793 286 if (_tlssocket->error() != 0) {
Jan Jongboom 23:15fa2726f793 287 return _tlssocket->error();
Jan Jongboom 23:15fa2726f793 288 }
Jan Jongboom 23:15fa2726f793 289
Jan Jongboom 23:15fa2726f793 290 _socket_was_open = _tlssocket->connected();
Jan Jongboom 23:15fa2726f793 291
Jan Jongboom 23:15fa2726f793 292 if (!_socket_was_open) {
Jan Jongboom 23:15fa2726f793 293 nsapi_error_t r = _tlssocket->connect();
Jan Jongboom 23:15fa2726f793 294 if (r != NSAPI_ERROR_OK) {
Jan Jongboom 23:15fa2726f793 295 return r;
Jan Jongboom 23:15fa2726f793 296 }
Jan Jongboom 23:15fa2726f793 297 }
Jan Jongboom 23:15fa2726f793 298
Jan Jongboom 23:15fa2726f793 299 return NSAPI_ERROR_OK;
Jan Jongboom 23:15fa2726f793 300 }
Jan Jongboom 23:15fa2726f793 301
Jan Jongboom 23:15fa2726f793 302 nsapi_size_or_error_t send_buffer(const unsigned char *buffer, size_t buffer_size) {
Jan Jongboom 23:15fa2726f793 303 nsapi_size_or_error_t ret = mbedtls_ssl_write(_tlssocket->get_ssl_context(), (const unsigned char *) buffer, buffer_size);
Jan Jongboom 23:15fa2726f793 304
Jan Jongboom 23:15fa2726f793 305 if (ret < 0) {
Jan Jongboom 23:15fa2726f793 306 if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
Jan Jongboom 23:15fa2726f793 307 ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
Jan Jongboom 23:15fa2726f793 308 print_mbedtls_error("mbedtls_ssl_write", ret);
Jan Jongboom 23:15fa2726f793 309 return onErrorAndReturn(_tlssocket->get_tcp_socket(), -1 );
Jan Jongboom 23:15fa2726f793 310 }
Jan Jongboom 23:15fa2726f793 311 else {
Jan Jongboom 23:15fa2726f793 312 return ret;
Jan Jongboom 23:15fa2726f793 313 }
Jan Jongboom 23:15fa2726f793 314 }
Jan Jongboom 23:15fa2726f793 315
Jan Jongboom 23:15fa2726f793 316 return NSAPI_ERROR_OK;
Jan Jongboom 23:15fa2726f793 317 }
Jan Jongboom 23:15fa2726f793 318
Jan Jongboom 23:15fa2726f793 319 HttpResponse* create_http_response() {
Jan Jongboom 23:15fa2726f793 320 nsapi_size_or_error_t ret;
Jan Jongboom 23:15fa2726f793 321
Jan Jongboom 23:15fa2726f793 322 // Create a response object
Jan Jongboom 23:15fa2726f793 323 _response = new HttpResponse();
Jan Jongboom 23:15fa2726f793 324 // And a response parser
Jan Jongboom 23:15fa2726f793 325 HttpParser parser(_response, HTTP_RESPONSE, _body_callback);
Jan Jongboom 23:15fa2726f793 326
Jan Jongboom 23:15fa2726f793 327 // Set up a receive buffer (on the heap)
Jan Jongboom 23:15fa2726f793 328 uint8_t* recv_buffer = (uint8_t*)malloc(HTTP_RECEIVE_BUFFER_SIZE);
Jan Jongboom 23:15fa2726f793 329
Jan Jongboom 23:15fa2726f793 330 /* Read data out of the socket */
Jan Jongboom 23:15fa2726f793 331 while ((ret = mbedtls_ssl_read(_tlssocket->get_ssl_context(), (unsigned char *) recv_buffer, HTTP_RECEIVE_BUFFER_SIZE)) > 0) {
Jan Jongboom 23:15fa2726f793 332 // Don't know if this is actually needed, but OK
Jan Jongboom 23:15fa2726f793 333 size_t _bpos = static_cast<size_t>(ret);
Jan Jongboom 23:15fa2726f793 334 recv_buffer[_bpos] = 0;
Jan Jongboom 23:15fa2726f793 335
Jan Jongboom 23:15fa2726f793 336 size_t nparsed = parser.execute((const char*)recv_buffer, _bpos);
Jan Jongboom 23:15fa2726f793 337 if (nparsed != _bpos) {
Jan Jongboom 23:15fa2726f793 338 print_mbedtls_error("parser_error", nparsed);
Jan Jongboom 23:15fa2726f793 339 // parser error...
Jan Jongboom 23:15fa2726f793 340 _error = -2101;
Jan Jongboom 23:15fa2726f793 341 free(recv_buffer);
Jan Jongboom 23:15fa2726f793 342 return NULL;
Jan Jongboom 23:15fa2726f793 343 }
Jan Jongboom 23:15fa2726f793 344
Jan Jongboom 23:15fa2726f793 345 if (_response->is_message_complete()) {
Jan Jongboom 23:15fa2726f793 346 break;
Jan Jongboom 23:15fa2726f793 347 }
Jan Jongboom 23:15fa2726f793 348 }
Jan Jongboom 23:15fa2726f793 349 if (ret < 0) {
Jan Jongboom 23:15fa2726f793 350 if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
Jan Jongboom 23:15fa2726f793 351 print_mbedtls_error("mbedtls_ssl_read", ret);
Jan Jongboom 23:15fa2726f793 352 onError(_tlssocket->get_tcp_socket(), -1 );
Jan Jongboom 23:15fa2726f793 353 }
Jan Jongboom 23:15fa2726f793 354 else {
Jan Jongboom 23:15fa2726f793 355 _error = ret;
Jan Jongboom 23:15fa2726f793 356 }
Jan Jongboom 23:15fa2726f793 357 free(recv_buffer);
Jan Jongboom 23:15fa2726f793 358 return NULL;
Jan Jongboom 23:15fa2726f793 359 }
Jan Jongboom 23:15fa2726f793 360
Jan Jongboom 23:15fa2726f793 361 parser.finish();
Jan Jongboom 23:15fa2726f793 362
Jan Jongboom 23:15fa2726f793 363 if (!_socket_was_open) {
Jan Jongboom 23:15fa2726f793 364 _tlssocket->get_tcp_socket()->close();
Jan Jongboom 23:15fa2726f793 365 }
Jan Jongboom 23:15fa2726f793 366
Jan Jongboom 23:15fa2726f793 367 free(recv_buffer);
Jan Jongboom 23:15fa2726f793 368
Jan Jongboom 23:15fa2726f793 369 return _response;
Jan Jongboom 23:15fa2726f793 370 }
Jan Jongboom 23:15fa2726f793 371
Jan Jongboom 0:910f5949759f 372 protected:
Jan Jongboom 11:96e4dcb9c0c2 373 TLSSocket* _tlssocket;
Jan Jongboom 11:96e4dcb9c0c2 374 bool _we_created_the_socket;
Jan Jongboom 0:910f5949759f 375
Jan Jongboom 0:910f5949759f 376 Callback<void(const char *at, size_t length)> _body_callback;
Jan Jongboom 0:910f5949759f 377 ParsedUrl* _parsed_url;
Jan Jongboom 0:910f5949759f 378 HttpRequestBuilder* _request_builder;
Jan Jongboom 0:910f5949759f 379 HttpResponse* _response;
Jan Jongboom 0:910f5949759f 380
Jan Jongboom 23:15fa2726f793 381 bool _socket_was_open;
Jan Jongboom 23:15fa2726f793 382
Jan Jongboom 0:910f5949759f 383 nsapi_error_t _error;
Jan Jongboom 0:910f5949759f 384 bool _debug;
Jan Jongboom 0:910f5949759f 385
Jan Jongboom 0:910f5949759f 386 };
Jan Jongboom 0:910f5949759f 387
Jan Jongboom 0:910f5949759f 388 #endif // _MBED_HTTPS_REQUEST_H_