Fork of mbed-http
Fork of mbed-http by
source/https_request.h@10:b017c7d2cf23, 2017-03-28 (annotated)
- Committer:
- Jan Jongboom
- Date:
- Tue Mar 28 13:33:14 2017 +0200
- Revision:
- 10:b017c7d2cf23
- Parent:
- 7:2e3eedb9ca5c
- Child:
- 11:96e4dcb9c0c2
Don't rely on strlen for request length, as it prevents sending \0 over the line. Patch via https://developer.mbed.org/users/ihere1/code/mbed-http/rev/ec9b75c349aa
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 | /* Change to a number between 1 and 4 to debug the TLS connection */ |
Jan Jongboom |
0:910f5949759f | 22 | #define DEBUG_LEVEL 0 |
Jan Jongboom |
0:910f5949759f | 23 | |
Jan Jongboom |
0:910f5949759f | 24 | #include <string> |
Jan Jongboom |
0:910f5949759f | 25 | #include <vector> |
Jan Jongboom |
0:910f5949759f | 26 | #include <map> |
Jan Jongboom |
0:910f5949759f | 27 | #include "http_parser.h" |
Jan Jongboom |
0:910f5949759f | 28 | #include "http_response.h" |
Jan Jongboom |
0:910f5949759f | 29 | #include "http_request_builder.h" |
Jan Jongboom |
0:910f5949759f | 30 | #include "http_response_parser.h" |
Jan Jongboom |
0:910f5949759f | 31 | #include "http_parsed_url.h" |
Jan Jongboom |
0:910f5949759f | 32 | |
Jan Jongboom |
0:910f5949759f | 33 | #include "mbedtls/platform.h" |
Jan Jongboom |
0:910f5949759f | 34 | #include "mbedtls/ssl.h" |
Jan Jongboom |
0:910f5949759f | 35 | #include "mbedtls/entropy.h" |
Jan Jongboom |
0:910f5949759f | 36 | #include "mbedtls/ctr_drbg.h" |
Jan Jongboom |
0:910f5949759f | 37 | #include "mbedtls/error.h" |
Jan Jongboom |
0:910f5949759f | 38 | |
Jan Jongboom |
0:910f5949759f | 39 | #if DEBUG_LEVEL > 0 |
Jan Jongboom |
0:910f5949759f | 40 | #include "mbedtls/debug.h" |
Jan Jongboom |
0:910f5949759f | 41 | #endif |
Jan Jongboom |
0:910f5949759f | 42 | |
Jan Jongboom |
0:910f5949759f | 43 | /** |
Jan Jongboom |
0:910f5949759f | 44 | * \brief HttpsRequest implements the logic for interacting with HTTPS servers. |
Jan Jongboom |
0:910f5949759f | 45 | */ |
Jan Jongboom |
0:910f5949759f | 46 | class HttpsRequest { |
Jan Jongboom |
0:910f5949759f | 47 | public: |
Jan Jongboom |
0:910f5949759f | 48 | /** |
Jan Jongboom |
0:910f5949759f | 49 | * HttpsRequest Constructor |
Jan Jongboom |
0:910f5949759f | 50 | * Initializes the TCP socket, sets up event handlers and flags. |
Jan Jongboom |
0:910f5949759f | 51 | * |
Jan Jongboom |
0:910f5949759f | 52 | * @param[in] net_iface The network interface |
Jan Jongboom |
0:910f5949759f | 53 | * @param[in] ssl_ca_pem String containing the trusted CAs |
Jan Jongboom |
0:910f5949759f | 54 | * @param[in] method HTTP method to use |
Jan Jongboom |
0:910f5949759f | 55 | * @param[in] url URL to the resource |
Jan Jongboom |
0:910f5949759f | 56 | * @param[in] body_callback Callback on which to retrieve chunks of the response body. |
Jan Jongboom |
0:910f5949759f | 57 | If not set, the complete body will be allocated on the HttpResponse object, |
Jan Jongboom |
0:910f5949759f | 58 | which might use lots of memory. |
Jan Jongboom |
0:910f5949759f | 59 | */ |
Jan Jongboom |
0:910f5949759f | 60 | HttpsRequest(NetworkInterface* net_iface, |
Jan Jongboom |
0:910f5949759f | 61 | const char* ssl_ca_pem, |
Jan Jongboom |
0:910f5949759f | 62 | http_method method, |
Jan Jongboom |
0:910f5949759f | 63 | const char* url, |
Jan Jongboom |
0:910f5949759f | 64 | Callback<void(const char *at, size_t length)> body_callback = 0) |
Jan Jongboom |
0:910f5949759f | 65 | { |
Jan Jongboom |
0:910f5949759f | 66 | _parsed_url = new ParsedUrl(url); |
Jan Jongboom |
0:910f5949759f | 67 | _body_callback = body_callback; |
Jan Jongboom |
0:910f5949759f | 68 | _tcpsocket = new TCPSocket(net_iface); |
Jan Jongboom |
0:910f5949759f | 69 | _request_builder = new HttpRequestBuilder(method, _parsed_url); |
Jan Jongboom |
0:910f5949759f | 70 | _response = NULL; |
Jan Jongboom |
0:910f5949759f | 71 | _debug = false; |
Jan Jongboom |
0:910f5949759f | 72 | _ssl_ca_pem = ssl_ca_pem; |
Jan Jongboom |
0:910f5949759f | 73 | |
Jan Jongboom |
0:910f5949759f | 74 | DRBG_PERS = "mbed TLS helloword client"; |
Jan Jongboom |
0:910f5949759f | 75 | |
Jan Jongboom |
0:910f5949759f | 76 | mbedtls_entropy_init(&_entropy); |
Jan Jongboom |
0:910f5949759f | 77 | mbedtls_ctr_drbg_init(&_ctr_drbg); |
Jan Jongboom |
0:910f5949759f | 78 | mbedtls_x509_crt_init(&_cacert); |
Jan Jongboom |
0:910f5949759f | 79 | mbedtls_ssl_init(&_ssl); |
Jan Jongboom |
0:910f5949759f | 80 | mbedtls_ssl_config_init(&_ssl_conf); |
Jan Jongboom |
0:910f5949759f | 81 | } |
Jan Jongboom |
0:910f5949759f | 82 | |
Jan Jongboom |
0:910f5949759f | 83 | /** |
Jan Jongboom |
0:910f5949759f | 84 | * HttpsRequest Destructor |
Jan Jongboom |
0:910f5949759f | 85 | */ |
Jan Jongboom |
0:910f5949759f | 86 | ~HttpsRequest() { |
Jan Jongboom |
0:910f5949759f | 87 | mbedtls_entropy_free(&_entropy); |
Jan Jongboom |
0:910f5949759f | 88 | mbedtls_ctr_drbg_free(&_ctr_drbg); |
Jan Jongboom |
0:910f5949759f | 89 | mbedtls_x509_crt_free(&_cacert); |
Jan Jongboom |
0:910f5949759f | 90 | mbedtls_ssl_free(&_ssl); |
Jan Jongboom |
0:910f5949759f | 91 | mbedtls_ssl_config_free(&_ssl_conf); |
Jan Jongboom |
0:910f5949759f | 92 | |
Jan Jongboom |
0:910f5949759f | 93 | if (_request_builder) { |
Jan Jongboom |
0:910f5949759f | 94 | delete _request_builder; |
Jan Jongboom |
0:910f5949759f | 95 | } |
Jan Jongboom |
0:910f5949759f | 96 | |
Jan Jongboom |
0:910f5949759f | 97 | if (_tcpsocket) { |
Jan Jongboom |
0:910f5949759f | 98 | delete _tcpsocket; |
Jan Jongboom |
0:910f5949759f | 99 | } |
Jan Jongboom |
0:910f5949759f | 100 | |
Jan Jongboom |
0:910f5949759f | 101 | if (_parsed_url) { |
Jan Jongboom |
0:910f5949759f | 102 | delete _parsed_url; |
Jan Jongboom |
0:910f5949759f | 103 | } |
Jan Jongboom |
0:910f5949759f | 104 | |
Jan Jongboom |
0:910f5949759f | 105 | if (_response) { |
Jan Jongboom |
0:910f5949759f | 106 | delete _response; |
Jan Jongboom |
0:910f5949759f | 107 | } |
Jan Jongboom |
0:910f5949759f | 108 | |
Jan Jongboom |
0:910f5949759f | 109 | // @todo: free DRBG_PERS ? |
Jan Jongboom |
0:910f5949759f | 110 | } |
Jan Jongboom |
0:910f5949759f | 111 | |
Jan Jongboom |
0:910f5949759f | 112 | /** |
Jan Jongboom |
0:910f5949759f | 113 | * Execute the HTTPS request. |
Jan Jongboom |
0:910f5949759f | 114 | * |
Jan Jongboom |
0:910f5949759f | 115 | * @param[in] body Pointer to the request body |
Jan Jongboom |
0:910f5949759f | 116 | * @param[in] body_size Size of the request body |
Jan Jongboom |
0:910f5949759f | 117 | * @return An HttpResponse pointer on success, or NULL on failure. |
Jan Jongboom |
0:910f5949759f | 118 | * See get_error() for the error code. |
Jan Jongboom |
0:910f5949759f | 119 | */ |
Jan Jongboom |
0:910f5949759f | 120 | HttpResponse* send(const void* body = NULL, nsapi_size_t body_size = 0) { |
Jan Jongboom |
0:910f5949759f | 121 | /* Initialize the flags */ |
Jan Jongboom |
0:910f5949759f | 122 | /* |
Jan Jongboom |
0:910f5949759f | 123 | * Initialize TLS-related stuf. |
Jan Jongboom |
0:910f5949759f | 124 | */ |
Jan Jongboom |
0:910f5949759f | 125 | int ret; |
Jan Jongboom |
0:910f5949759f | 126 | if ((ret = mbedtls_ctr_drbg_seed(&_ctr_drbg, mbedtls_entropy_func, &_entropy, |
Jan Jongboom |
0:910f5949759f | 127 | (const unsigned char *) DRBG_PERS, |
Jan Jongboom |
0:910f5949759f | 128 | sizeof (DRBG_PERS))) != 0) { |
Jan Jongboom |
0:910f5949759f | 129 | print_mbedtls_error("mbedtls_crt_drbg_init", ret); |
Jan Jongboom |
0:910f5949759f | 130 | _error = ret; |
Jan Jongboom |
0:910f5949759f | 131 | return NULL; |
Jan Jongboom |
0:910f5949759f | 132 | } |
Jan Jongboom |
0:910f5949759f | 133 | |
Jan Jongboom |
0:910f5949759f | 134 | if ((ret = mbedtls_x509_crt_parse(&_cacert, (const unsigned char *)_ssl_ca_pem, |
Jan Jongboom |
0:910f5949759f | 135 | strlen(_ssl_ca_pem) + 1)) != 0) { |
Jan Jongboom |
0:910f5949759f | 136 | print_mbedtls_error("mbedtls_x509_crt_parse", ret); |
Jan Jongboom |
0:910f5949759f | 137 | _error = ret; |
Jan Jongboom |
0:910f5949759f | 138 | return NULL; |
Jan Jongboom |
0:910f5949759f | 139 | } |
Jan Jongboom |
0:910f5949759f | 140 | |
Jan Jongboom |
0:910f5949759f | 141 | if ((ret = mbedtls_ssl_config_defaults(&_ssl_conf, |
Jan Jongboom |
0:910f5949759f | 142 | MBEDTLS_SSL_IS_CLIENT, |
Jan Jongboom |
0:910f5949759f | 143 | MBEDTLS_SSL_TRANSPORT_STREAM, |
Jan Jongboom |
0:910f5949759f | 144 | MBEDTLS_SSL_PRESET_DEFAULT)) != 0) { |
Jan Jongboom |
0:910f5949759f | 145 | print_mbedtls_error("mbedtls_ssl_config_defaults", ret); |
Jan Jongboom |
0:910f5949759f | 146 | _error = ret; |
Jan Jongboom |
0:910f5949759f | 147 | return NULL; |
Jan Jongboom |
0:910f5949759f | 148 | } |
Jan Jongboom |
0:910f5949759f | 149 | |
Jan Jongboom |
0:910f5949759f | 150 | mbedtls_ssl_conf_ca_chain(&_ssl_conf, &_cacert, NULL); |
Jan Jongboom |
0:910f5949759f | 151 | mbedtls_ssl_conf_rng(&_ssl_conf, mbedtls_ctr_drbg_random, &_ctr_drbg); |
Jan Jongboom |
0:910f5949759f | 152 | |
Jan Jongboom |
0:910f5949759f | 153 | /* It is possible to disable authentication by passing |
Jan Jongboom |
0:910f5949759f | 154 | * MBEDTLS_SSL_VERIFY_NONE in the call to mbedtls_ssl_conf_authmode() |
Jan Jongboom |
0:910f5949759f | 155 | */ |
Jan Jongboom |
0:910f5949759f | 156 | mbedtls_ssl_conf_authmode(&_ssl_conf, MBEDTLS_SSL_VERIFY_REQUIRED); |
Jan Jongboom |
0:910f5949759f | 157 | |
Jan Jongboom |
0:910f5949759f | 158 | #if DEBUG_LEVEL > 0 |
Jan Jongboom |
0:910f5949759f | 159 | mbedtls_ssl_conf_verify(&_ssl_conf, my_verify, NULL); |
Jan Jongboom |
0:910f5949759f | 160 | mbedtls_ssl_conf_dbg(&_ssl_conf, my_debug, NULL); |
Jan Jongboom |
0:910f5949759f | 161 | mbedtls_debug_set_threshold(DEBUG_LEVEL); |
Jan Jongboom |
0:910f5949759f | 162 | #endif |
Jan Jongboom |
0:910f5949759f | 163 | |
Jan Jongboom |
0:910f5949759f | 164 | if ((ret = mbedtls_ssl_setup(&_ssl, &_ssl_conf)) != 0) { |
Jan Jongboom |
0:910f5949759f | 165 | print_mbedtls_error("mbedtls_ssl_setup", ret); |
Jan Jongboom |
0:910f5949759f | 166 | _error = ret; |
Jan Jongboom |
0:910f5949759f | 167 | return NULL; |
Jan Jongboom |
0:910f5949759f | 168 | } |
Jan Jongboom |
0:910f5949759f | 169 | |
Jan Jongboom |
0:910f5949759f | 170 | mbedtls_ssl_set_hostname(&_ssl, _parsed_url->host()); |
Jan Jongboom |
0:910f5949759f | 171 | |
Jan Jongboom |
0:910f5949759f | 172 | mbedtls_ssl_set_bio(&_ssl, static_cast<void *>(_tcpsocket), |
Jan Jongboom |
0:910f5949759f | 173 | ssl_send, ssl_recv, NULL ); |
Jan Jongboom |
0:910f5949759f | 174 | |
Jan Jongboom |
0:910f5949759f | 175 | /* Connect to the server */ |
Jan Jongboom |
0:910f5949759f | 176 | if (_debug) mbedtls_printf("Connecting to %s:%d\r\n", _parsed_url->host(), _parsed_url->port()); |
Jan Jongboom |
0:910f5949759f | 177 | ret = _tcpsocket->connect(_parsed_url->host(), _parsed_url->port()); |
Jan Jongboom |
0:910f5949759f | 178 | if (ret != NSAPI_ERROR_OK) { |
Jan Jongboom |
0:910f5949759f | 179 | if (_debug) mbedtls_printf("Failed to connect\r\n"); |
Jan Jongboom |
0:910f5949759f | 180 | onError(_tcpsocket, -1); |
Jan Jongboom |
0:910f5949759f | 181 | return NULL; |
Jan Jongboom |
0:910f5949759f | 182 | } |
Jan Jongboom |
0:910f5949759f | 183 | |
Jan Jongboom |
0:910f5949759f | 184 | /* Start the handshake, the rest will be done in onReceive() */ |
Jan Jongboom |
0:910f5949759f | 185 | if (_debug) mbedtls_printf("Starting the TLS handshake...\r\n"); |
Jan Jongboom |
0:910f5949759f | 186 | ret = mbedtls_ssl_handshake(&_ssl); |
Jan Jongboom |
0:910f5949759f | 187 | if (ret < 0) { |
Jan Jongboom |
0:910f5949759f | 188 | if (ret != MBEDTLS_ERR_SSL_WANT_READ && |
Jan Jongboom |
0:910f5949759f | 189 | ret != MBEDTLS_ERR_SSL_WANT_WRITE) { |
Jan Jongboom |
0:910f5949759f | 190 | print_mbedtls_error("mbedtls_ssl_handshake", ret); |
Jan Jongboom |
0:910f5949759f | 191 | onError(_tcpsocket, -1); |
Jan Jongboom |
0:910f5949759f | 192 | } |
Jan Jongboom |
0:910f5949759f | 193 | else { |
Jan Jongboom |
0:910f5949759f | 194 | _error = ret; |
Jan Jongboom |
0:910f5949759f | 195 | } |
Jan Jongboom |
0:910f5949759f | 196 | return NULL; |
Jan Jongboom |
0:910f5949759f | 197 | } |
Jan Jongboom |
0:910f5949759f | 198 | |
Jan Jongboom |
10:b017c7d2cf23 | 199 | size_t request_size = 0; |
Jan Jongboom |
10:b017c7d2cf23 | 200 | char* request = _request_builder->build(body, body_size, request_size); |
Jan Jongboom |
0:910f5949759f | 201 | |
Jan Jongboom |
0:910f5949759f | 202 | ret = mbedtls_ssl_write(&_ssl, (const unsigned char *) request, request_size); |
Jan Jongboom |
0:910f5949759f | 203 | |
Jan Jongboom |
0:910f5949759f | 204 | free(request); |
Jan Jongboom |
0:910f5949759f | 205 | |
Jan Jongboom |
0:910f5949759f | 206 | if (ret < 0) { |
Jan Jongboom |
0:910f5949759f | 207 | if (ret != MBEDTLS_ERR_SSL_WANT_READ && |
Jan Jongboom |
0:910f5949759f | 208 | ret != MBEDTLS_ERR_SSL_WANT_WRITE) { |
Jan Jongboom |
0:910f5949759f | 209 | print_mbedtls_error("mbedtls_ssl_write", ret); |
Jan Jongboom |
0:910f5949759f | 210 | onError(_tcpsocket, -1 ); |
Jan Jongboom |
0:910f5949759f | 211 | } |
Jan Jongboom |
0:910f5949759f | 212 | else { |
Jan Jongboom |
0:910f5949759f | 213 | _error = ret; |
Jan Jongboom |
0:910f5949759f | 214 | } |
Jan Jongboom |
0:910f5949759f | 215 | return NULL; |
Jan Jongboom |
0:910f5949759f | 216 | } |
Jan Jongboom |
0:910f5949759f | 217 | |
Jan Jongboom |
0:910f5949759f | 218 | /* It also means the handshake is done, time to print info */ |
Jan Jongboom |
0:910f5949759f | 219 | if (_debug) mbedtls_printf("TLS connection to %s:%d established\r\n", _parsed_url->host(), _parsed_url->port()); |
Jan Jongboom |
0:910f5949759f | 220 | |
Jan Jongboom |
0:910f5949759f | 221 | const uint32_t buf_size = 1024; |
Jan Jongboom |
0:910f5949759f | 222 | char *buf = new char[buf_size]; |
Jan Jongboom |
0:910f5949759f | 223 | mbedtls_x509_crt_info(buf, buf_size, "\r ", |
Jan Jongboom |
0:910f5949759f | 224 | mbedtls_ssl_get_peer_cert(&_ssl)); |
Jan Jongboom |
0:910f5949759f | 225 | if (_debug) mbedtls_printf("Server certificate:\r\n%s\r", buf); |
Jan Jongboom |
0:910f5949759f | 226 | |
Jan Jongboom |
0:910f5949759f | 227 | uint32_t flags = mbedtls_ssl_get_verify_result(&_ssl); |
Jan Jongboom |
0:910f5949759f | 228 | if( flags != 0 ) |
Jan Jongboom |
0:910f5949759f | 229 | { |
Jan Jongboom |
0:910f5949759f | 230 | mbedtls_x509_crt_verify_info(buf, buf_size, "\r ! ", flags); |
Jan Jongboom |
0:910f5949759f | 231 | if (_debug) mbedtls_printf("Certificate verification failed:\r\n%s\r\r\n", buf); |
Jan Jongboom |
0:910f5949759f | 232 | } |
Jan Jongboom |
0:910f5949759f | 233 | else { |
Jan Jongboom |
0:910f5949759f | 234 | if (_debug) mbedtls_printf("Certificate verification passed\r\n\r\n"); |
Jan Jongboom |
0:910f5949759f | 235 | } |
Jan Jongboom |
0:910f5949759f | 236 | |
Jan Jongboom |
0:910f5949759f | 237 | // Create a response object |
Jan Jongboom |
0:910f5949759f | 238 | _response = new HttpResponse(); |
Jan Jongboom |
0:910f5949759f | 239 | // And a response parser |
Jan Jongboom |
0:910f5949759f | 240 | HttpResponseParser parser(_response, _body_callback); |
Jan Jongboom |
0:910f5949759f | 241 | |
Jan Jongboom |
0:910f5949759f | 242 | // Set up a receive buffer (on the heap) |
Jan Jongboom |
0:910f5949759f | 243 | uint8_t* recv_buffer = (uint8_t*)malloc(HTTP_RECEIVE_BUFFER_SIZE); |
Jan Jongboom |
0:910f5949759f | 244 | |
Jan Jongboom |
0:910f5949759f | 245 | /* Read data out of the socket */ |
Jan Jongboom |
0:910f5949759f | 246 | while ((ret = mbedtls_ssl_read(&_ssl, (unsigned char *) recv_buffer, HTTP_RECEIVE_BUFFER_SIZE)) > 0) { |
Jan Jongboom |
0:910f5949759f | 247 | // Don't know if this is actually needed, but OK |
Jan Jongboom |
0:910f5949759f | 248 | size_t _bpos = static_cast<size_t>(ret); |
Jan Jongboom |
0:910f5949759f | 249 | recv_buffer[_bpos] = 0; |
Jan Jongboom |
0:910f5949759f | 250 | |
Jan Jongboom |
0:910f5949759f | 251 | size_t nparsed = parser.execute((const char*)recv_buffer, _bpos); |
Jan Jongboom |
0:910f5949759f | 252 | if (nparsed != _bpos) { |
Jan Jongboom |
0:910f5949759f | 253 | print_mbedtls_error("parser_error", nparsed); |
Jan Jongboom |
0:910f5949759f | 254 | // parser error... |
Jan Jongboom |
0:910f5949759f | 255 | _error = -2101; |
Jan Jongboom |
0:910f5949759f | 256 | free(recv_buffer); |
Jan Jongboom |
0:910f5949759f | 257 | return NULL; |
Jan Jongboom |
0:910f5949759f | 258 | } |
Jan Jongboom |
6:112d72c60e07 | 259 | |
Jan Jongboom |
7:2e3eedb9ca5c | 260 | if (_response->is_message_complete()) { |
Jan Jongboom |
0:910f5949759f | 261 | break; |
Jan Jongboom |
0:910f5949759f | 262 | } |
Jan Jongboom |
0:910f5949759f | 263 | } |
Jan Jongboom |
0:910f5949759f | 264 | if (ret < 0) { |
Jan Jongboom |
0:910f5949759f | 265 | if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) { |
Jan Jongboom |
0:910f5949759f | 266 | print_mbedtls_error("mbedtls_ssl_read", ret); |
Jan Jongboom |
0:910f5949759f | 267 | onError(_tcpsocket, -1 ); |
Jan Jongboom |
0:910f5949759f | 268 | } |
Jan Jongboom |
0:910f5949759f | 269 | else { |
Jan Jongboom |
0:910f5949759f | 270 | _error = ret; |
Jan Jongboom |
0:910f5949759f | 271 | } |
Jan Jongboom |
0:910f5949759f | 272 | free(recv_buffer); |
Jan Jongboom |
0:910f5949759f | 273 | return NULL; |
Jan Jongboom |
0:910f5949759f | 274 | } |
Jan Jongboom |
0:910f5949759f | 275 | |
Jan Jongboom |
0:910f5949759f | 276 | parser.finish(); |
Jan Jongboom |
0:910f5949759f | 277 | |
Jan Jongboom |
0:910f5949759f | 278 | _tcpsocket->close(); |
Jan Jongboom |
0:910f5949759f | 279 | free(recv_buffer); |
Jan Jongboom |
0:910f5949759f | 280 | |
Jan Jongboom |
0:910f5949759f | 281 | return _response; |
Jan Jongboom |
0:910f5949759f | 282 | } |
Jan Jongboom |
0:910f5949759f | 283 | |
Jan Jongboom |
0:910f5949759f | 284 | /** |
Jan Jongboom |
0:910f5949759f | 285 | * Closes the TCP socket |
Jan Jongboom |
0:910f5949759f | 286 | */ |
Jan Jongboom |
0:910f5949759f | 287 | void close() { |
Jan Jongboom |
0:910f5949759f | 288 | _tcpsocket->close(); |
Jan Jongboom |
0:910f5949759f | 289 | } |
Jan Jongboom |
0:910f5949759f | 290 | |
Jan Jongboom |
0:910f5949759f | 291 | /** |
Jan Jongboom |
0:910f5949759f | 292 | * Set a header for the request. |
Jan Jongboom |
0:910f5949759f | 293 | * |
Jan Jongboom |
0:910f5949759f | 294 | * The 'Host' and 'Content-Length' headers are set automatically. |
Jan Jongboom |
0:910f5949759f | 295 | * Setting the same header twice will overwrite the previous entry. |
Jan Jongboom |
0:910f5949759f | 296 | * |
Jan Jongboom |
0:910f5949759f | 297 | * @param[in] key Header key |
Jan Jongboom |
0:910f5949759f | 298 | * @param[in] value Header value |
Jan Jongboom |
0:910f5949759f | 299 | */ |
Jan Jongboom |
0:910f5949759f | 300 | void set_header(string key, string value) { |
Jan Jongboom |
0:910f5949759f | 301 | _request_builder->set_header(key, value); |
Jan Jongboom |
0:910f5949759f | 302 | } |
Jan Jongboom |
0:910f5949759f | 303 | |
Jan Jongboom |
0:910f5949759f | 304 | /** |
Jan Jongboom |
0:910f5949759f | 305 | * Get the error code. |
Jan Jongboom |
0:910f5949759f | 306 | * |
Jan Jongboom |
0:910f5949759f | 307 | * When send() fails, this error is set. |
Jan Jongboom |
0:910f5949759f | 308 | */ |
Jan Jongboom |
0:910f5949759f | 309 | nsapi_error_t get_error() { |
Jan Jongboom |
0:910f5949759f | 310 | return _error; |
Jan Jongboom |
0:910f5949759f | 311 | } |
Jan Jongboom |
0:910f5949759f | 312 | |
Jan Jongboom |
0:910f5949759f | 313 | /** |
Jan Jongboom |
0:910f5949759f | 314 | * Set the debug flag. |
Jan Jongboom |
0:910f5949759f | 315 | * |
Jan Jongboom |
0:910f5949759f | 316 | * If this flag is set, debug information from mbed TLS will be logged to stdout. |
Jan Jongboom |
0:910f5949759f | 317 | */ |
Jan Jongboom |
0:910f5949759f | 318 | void set_debug(bool debug) { |
Jan Jongboom |
0:910f5949759f | 319 | _debug = debug; |
Jan Jongboom |
0:910f5949759f | 320 | } |
Jan Jongboom |
0:910f5949759f | 321 | |
Jan Jongboom |
0:910f5949759f | 322 | protected: |
Jan Jongboom |
0:910f5949759f | 323 | /** |
Jan Jongboom |
0:910f5949759f | 324 | * Helper for pretty-printing mbed TLS error codes |
Jan Jongboom |
0:910f5949759f | 325 | */ |
Jan Jongboom |
0:910f5949759f | 326 | static void print_mbedtls_error(const char *name, int err) { |
Jan Jongboom |
0:910f5949759f | 327 | char buf[128]; |
Jan Jongboom |
0:910f5949759f | 328 | mbedtls_strerror(err, buf, sizeof (buf)); |
Jan Jongboom |
0:910f5949759f | 329 | mbedtls_printf("%s() failed: -0x%04x (%d): %s\r\n", name, -err, err, buf); |
Jan Jongboom |
0:910f5949759f | 330 | } |
Jan Jongboom |
0:910f5949759f | 331 | |
Jan Jongboom |
0:910f5949759f | 332 | #if DEBUG_LEVEL > 0 |
Jan Jongboom |
0:910f5949759f | 333 | /** |
Jan Jongboom |
0:910f5949759f | 334 | * Debug callback for mbed TLS |
Jan Jongboom |
0:910f5949759f | 335 | * Just prints on the USB serial port |
Jan Jongboom |
0:910f5949759f | 336 | */ |
Jan Jongboom |
0:910f5949759f | 337 | static void my_debug(void *ctx, int level, const char *file, int line, |
Jan Jongboom |
0:910f5949759f | 338 | const char *str) |
Jan Jongboom |
0:910f5949759f | 339 | { |
Jan Jongboom |
0:910f5949759f | 340 | const char *p, *basename; |
Jan Jongboom |
0:910f5949759f | 341 | (void) ctx; |
Jan Jongboom |
0:910f5949759f | 342 | |
Jan Jongboom |
0:910f5949759f | 343 | /* Extract basename from file */ |
Jan Jongboom |
0:910f5949759f | 344 | for(p = basename = file; *p != '\0'; p++) { |
Jan Jongboom |
0:910f5949759f | 345 | if(*p == '/' || *p == '\\') { |
Jan Jongboom |
0:910f5949759f | 346 | basename = p + 1; |
Jan Jongboom |
0:910f5949759f | 347 | } |
Jan Jongboom |
0:910f5949759f | 348 | } |
Jan Jongboom |
0:910f5949759f | 349 | |
Jan Jongboom |
0:910f5949759f | 350 | if (_debug) { |
Jan Jongboom |
0:910f5949759f | 351 | mbedtls_printf("%s:%04d: |%d| %s", basename, line, level, str); |
Jan Jongboom |
0:910f5949759f | 352 | } |
Jan Jongboom |
0:910f5949759f | 353 | } |
Jan Jongboom |
0:910f5949759f | 354 | |
Jan Jongboom |
0:910f5949759f | 355 | /** |
Jan Jongboom |
0:910f5949759f | 356 | * Certificate verification callback for mbed TLS |
Jan Jongboom |
0:910f5949759f | 357 | * Here we only use it to display information on each cert in the chain |
Jan Jongboom |
0:910f5949759f | 358 | */ |
Jan Jongboom |
0:910f5949759f | 359 | static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags) |
Jan Jongboom |
0:910f5949759f | 360 | { |
Jan Jongboom |
0:910f5949759f | 361 | const uint32_t buf_size = 1024; |
Jan Jongboom |
0:910f5949759f | 362 | char *buf = new char[buf_size]; |
Jan Jongboom |
0:910f5949759f | 363 | (void) data; |
Jan Jongboom |
0:910f5949759f | 364 | |
Jan Jongboom |
0:910f5949759f | 365 | if (_debug) mbedtls_printf("\nVerifying certificate at depth %d:\n", depth); |
Jan Jongboom |
0:910f5949759f | 366 | mbedtls_x509_crt_info(buf, buf_size - 1, " ", crt); |
Jan Jongboom |
0:910f5949759f | 367 | if (_debug) mbedtls_printf("%s", buf); |
Jan Jongboom |
0:910f5949759f | 368 | |
Jan Jongboom |
0:910f5949759f | 369 | if (*flags == 0) |
Jan Jongboom |
0:910f5949759f | 370 | if (_debug) mbedtls_printf("No verification issue for this certificate\n"); |
Jan Jongboom |
0:910f5949759f | 371 | else |
Jan Jongboom |
0:910f5949759f | 372 | { |
Jan Jongboom |
0:910f5949759f | 373 | mbedtls_x509_crt_verify_info(buf, buf_size, " ! ", *flags); |
Jan Jongboom |
0:910f5949759f | 374 | if (_debug) mbedtls_printf("%s\n", buf); |
Jan Jongboom |
0:910f5949759f | 375 | } |
Jan Jongboom |
0:910f5949759f | 376 | |
Jan Jongboom |
0:910f5949759f | 377 | delete[] buf; |
Jan Jongboom |
0:910f5949759f | 378 | return 0; |
Jan Jongboom |
0:910f5949759f | 379 | } |
Jan Jongboom |
0:910f5949759f | 380 | #endif |
Jan Jongboom |
0:910f5949759f | 381 | |
Jan Jongboom |
0:910f5949759f | 382 | /** |
Jan Jongboom |
0:910f5949759f | 383 | * Receive callback for mbed TLS |
Jan Jongboom |
0:910f5949759f | 384 | */ |
Jan Jongboom |
0:910f5949759f | 385 | static int ssl_recv(void *ctx, unsigned char *buf, size_t len) { |
Jan Jongboom |
0:910f5949759f | 386 | int recv = -1; |
Jan Jongboom |
0:910f5949759f | 387 | TCPSocket *socket = static_cast<TCPSocket *>(ctx); |
Jan Jongboom |
0:910f5949759f | 388 | recv = socket->recv(buf, len); |
Jan Jongboom |
0:910f5949759f | 389 | |
Jan Jongboom |
0:910f5949759f | 390 | if (NSAPI_ERROR_WOULD_BLOCK == recv) { |
Jan Jongboom |
0:910f5949759f | 391 | return MBEDTLS_ERR_SSL_WANT_READ; |
Jan Jongboom |
0:910f5949759f | 392 | } |
Jan Jongboom |
0:910f5949759f | 393 | else if (recv < 0) { |
Jan Jongboom |
0:910f5949759f | 394 | return -1; |
Jan Jongboom |
0:910f5949759f | 395 | } |
Jan Jongboom |
0:910f5949759f | 396 | else { |
Jan Jongboom |
0:910f5949759f | 397 | return recv; |
Jan Jongboom |
0:910f5949759f | 398 | } |
Jan Jongboom |
0:910f5949759f | 399 | } |
Jan Jongboom |
0:910f5949759f | 400 | |
Jan Jongboom |
0:910f5949759f | 401 | /** |
Jan Jongboom |
0:910f5949759f | 402 | * Send callback for mbed TLS |
Jan Jongboom |
0:910f5949759f | 403 | */ |
Jan Jongboom |
0:910f5949759f | 404 | static int ssl_send(void *ctx, const unsigned char *buf, size_t len) { |
Jan Jongboom |
0:910f5949759f | 405 | int size = -1; |
Jan Jongboom |
0:910f5949759f | 406 | TCPSocket *socket = static_cast<TCPSocket *>(ctx); |
Jan Jongboom |
0:910f5949759f | 407 | size = socket->send(buf, len); |
Jan Jongboom |
0:910f5949759f | 408 | |
Jan Jongboom |
0:910f5949759f | 409 | if(NSAPI_ERROR_WOULD_BLOCK == size) { |
Jan Jongboom |
0:910f5949759f | 410 | return len; |
Jan Jongboom |
0:910f5949759f | 411 | } |
Jan Jongboom |
0:910f5949759f | 412 | else if (size < 0){ |
Jan Jongboom |
0:910f5949759f | 413 | return -1; |
Jan Jongboom |
0:910f5949759f | 414 | } |
Jan Jongboom |
0:910f5949759f | 415 | else { |
Jan Jongboom |
0:910f5949759f | 416 | return size; |
Jan Jongboom |
0:910f5949759f | 417 | } |
Jan Jongboom |
0:910f5949759f | 418 | } |
Jan Jongboom |
0:910f5949759f | 419 | |
Jan Jongboom |
0:910f5949759f | 420 | void onError(TCPSocket *s, int error) { |
Jan Jongboom |
0:910f5949759f | 421 | s->close(); |
Jan Jongboom |
0:910f5949759f | 422 | _error = error; |
Jan Jongboom |
0:910f5949759f | 423 | } |
Jan Jongboom |
0:910f5949759f | 424 | |
Jan Jongboom |
0:910f5949759f | 425 | protected: |
Jan Jongboom |
0:910f5949759f | 426 | TCPSocket* _tcpsocket; |
Jan Jongboom |
0:910f5949759f | 427 | |
Jan Jongboom |
0:910f5949759f | 428 | Callback<void(const char *at, size_t length)> _body_callback; |
Jan Jongboom |
0:910f5949759f | 429 | ParsedUrl* _parsed_url; |
Jan Jongboom |
0:910f5949759f | 430 | HttpRequestBuilder* _request_builder; |
Jan Jongboom |
0:910f5949759f | 431 | HttpResponse* _response; |
Jan Jongboom |
0:910f5949759f | 432 | const char *DRBG_PERS; |
Jan Jongboom |
0:910f5949759f | 433 | const char *_ssl_ca_pem; |
Jan Jongboom |
0:910f5949759f | 434 | |
Jan Jongboom |
0:910f5949759f | 435 | nsapi_error_t _error; |
Jan Jongboom |
0:910f5949759f | 436 | bool _debug; |
Jan Jongboom |
0:910f5949759f | 437 | |
Jan Jongboom |
0:910f5949759f | 438 | mbedtls_entropy_context _entropy; |
Jan Jongboom |
0:910f5949759f | 439 | mbedtls_ctr_drbg_context _ctr_drbg; |
Jan Jongboom |
0:910f5949759f | 440 | mbedtls_x509_crt _cacert; |
Jan Jongboom |
0:910f5949759f | 441 | mbedtls_ssl_context _ssl; |
Jan Jongboom |
0:910f5949759f | 442 | mbedtls_ssl_config _ssl_conf; |
Jan Jongboom |
0:910f5949759f | 443 | }; |
Jan Jongboom |
0:910f5949759f | 444 | |
Jan Jongboom |
0:910f5949759f | 445 | #endif // _MBED_HTTPS_REQUEST_H_ |