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
source/https_request.h@29:383e9bfbfbed, 2018-08-10 (annotated)
- Committer:
- Jan Jongboom
- Date:
- Fri Aug 10 11:30:37 2018 +0100
- Revision:
- 29:383e9bfbfbed
- Parent:
- 23:15fa2726f793
- Child:
- 32:fa4d71265625
Force usage of uint32_t instead of size_t - required for compilation on 64-bit systems
Who changed what in which revision?
User | Revision | Line number | New 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 |
29:383e9bfbfbed | 56 | Callback<void(const char *at, uint32_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 |
29:383e9bfbfbed | 82 | Callback<void(const char *at, uint32_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 |
29:383e9bfbfbed | 131 | uint32_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 |
29:383e9bfbfbed | 153 | HttpResponse* send(Callback<const void*(uint32_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 |
29:383e9bfbfbed | 164 | uint32_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 |
29:383e9bfbfbed | 178 | uint32_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 |
29:383e9bfbfbed | 185 | uint32_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 |
29:383e9bfbfbed | 302 | nsapi_size_or_error_t send_buffer(const unsigned char *buffer, uint32_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 |
29:383e9bfbfbed | 333 | uint32_t _bpos = static_cast<uint32_t>(ret); |
Jan Jongboom |
23:15fa2726f793 | 334 | recv_buffer[_bpos] = 0; |
Jan Jongboom |
23:15fa2726f793 | 335 | |
Jan Jongboom |
29:383e9bfbfbed | 336 | uint32_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 |
29:383e9bfbfbed | 376 | Callback<void(const char *at, uint32_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_ |