mbed-os
Fork of mbed-os by
features/unsupported/net/https/HTTPSClient.cpp@1:3deb71413561, 2017-07-20 (annotated)
- Committer:
- xuaner
- Date:
- Thu Jul 20 14:26:57 2017 +0000
- Revision:
- 1:3deb71413561
- Parent:
- 0:f269e3021894
mbed_os
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
elessair | 0:f269e3021894 | 1 | #include "HTTPSClient.h" |
elessair | 0:f269e3021894 | 2 | #include "HTTPHeader.h" |
elessair | 0:f269e3021894 | 3 | #include <string> |
elessair | 0:f269e3021894 | 4 | #include <cstring> |
elessair | 0:f269e3021894 | 5 | #include "mbed.h" |
elessair | 0:f269e3021894 | 6 | #include <stdlib.h> |
elessair | 0:f269e3021894 | 7 | #include <stdio.h> |
elessair | 0:f269e3021894 | 8 | |
elessair | 0:f269e3021894 | 9 | using std::memset; |
elessair | 0:f269e3021894 | 10 | using std::memcpy; |
elessair | 0:f269e3021894 | 11 | using std::string; |
elessair | 0:f269e3021894 | 12 | |
elessair | 0:f269e3021894 | 13 | const static int HTTPS_PORT = 443; |
elessair | 0:f269e3021894 | 14 | char buf[256]; |
elessair | 0:f269e3021894 | 15 | |
elessair | 0:f269e3021894 | 16 | HTTPSClient::HTTPSClient() : |
elessair | 0:f269e3021894 | 17 | _is_connected(false), |
elessair | 0:f269e3021894 | 18 | _ssl_ctx(), |
elessair | 0:f269e3021894 | 19 | _ssl(), |
elessair | 0:f269e3021894 | 20 | _host() { |
elessair | 0:f269e3021894 | 21 | } |
elessair | 0:f269e3021894 | 22 | |
elessair | 0:f269e3021894 | 23 | HTTPSClient::~HTTPSClient() { |
elessair | 0:f269e3021894 | 24 | close(); |
elessair | 0:f269e3021894 | 25 | } |
elessair | 0:f269e3021894 | 26 | |
elessair | 0:f269e3021894 | 27 | int HTTPSClient::connect(const char* host) { |
elessair | 0:f269e3021894 | 28 | if (init_socket(SOCK_STREAM) < 0) |
elessair | 0:f269e3021894 | 29 | return -1; |
elessair | 0:f269e3021894 | 30 | |
elessair | 0:f269e3021894 | 31 | if (set_address(host, HTTPS_PORT) != 0) |
elessair | 0:f269e3021894 | 32 | return -1; |
elessair | 0:f269e3021894 | 33 | |
elessair | 0:f269e3021894 | 34 | if (lwip_connect(_sock_fd, (const struct sockaddr *) &_remoteHost, sizeof(_remoteHost)) < 0) { |
elessair | 0:f269e3021894 | 35 | close(); |
elessair | 0:f269e3021894 | 36 | return -1; |
elessair | 0:f269e3021894 | 37 | } |
elessair | 0:f269e3021894 | 38 | |
elessair | 0:f269e3021894 | 39 | if(ssl_ctx_new(&_ssl_ctx, SSL_SERVER_VERIFY_LATER, SSL_DEFAULT_CLNT_SESS) != &_ssl_ctx) |
elessair | 0:f269e3021894 | 40 | return -1; |
elessair | 0:f269e3021894 | 41 | |
elessair | 0:f269e3021894 | 42 | _ssl.ssl_ctx = &_ssl_ctx; |
elessair | 0:f269e3021894 | 43 | |
elessair | 0:f269e3021894 | 44 | if(ssl_client_new(&_ssl, _sock_fd, NULL, 0) == NULL) |
elessair | 0:f269e3021894 | 45 | { |
elessair | 0:f269e3021894 | 46 | close(); |
elessair | 0:f269e3021894 | 47 | return -1; |
elessair | 0:f269e3021894 | 48 | } |
elessair | 0:f269e3021894 | 49 | if(_ssl.hs_status != SSL_OK) |
elessair | 0:f269e3021894 | 50 | { |
elessair | 0:f269e3021894 | 51 | close(); |
elessair | 0:f269e3021894 | 52 | return -1; |
elessair | 0:f269e3021894 | 53 | } |
elessair | 0:f269e3021894 | 54 | |
elessair | 0:f269e3021894 | 55 | _is_connected = true; |
elessair | 0:f269e3021894 | 56 | _host = host; |
elessair | 0:f269e3021894 | 57 | return 0; |
elessair | 0:f269e3021894 | 58 | } |
elessair | 0:f269e3021894 | 59 | |
elessair | 0:f269e3021894 | 60 | bool HTTPSClient::is_connected(void) { |
elessair | 0:f269e3021894 | 61 | return _is_connected; |
elessair | 0:f269e3021894 | 62 | } |
elessair | 0:f269e3021894 | 63 | |
elessair | 0:f269e3021894 | 64 | int HTTPSClient::send(char* data, int length) { |
elessair | 0:f269e3021894 | 65 | if ((_sock_fd < 0) || !_is_connected) |
elessair | 0:f269e3021894 | 66 | return -1; |
elessair | 0:f269e3021894 | 67 | |
elessair | 0:f269e3021894 | 68 | return ssl_write(&_ssl, (uint8_t*)data, length); |
elessair | 0:f269e3021894 | 69 | } |
elessair | 0:f269e3021894 | 70 | |
elessair | 0:f269e3021894 | 71 | |
elessair | 0:f269e3021894 | 72 | |
elessair | 0:f269e3021894 | 73 | HTTPHeader HTTPSClient::get(char *request) |
elessair | 0:f269e3021894 | 74 | { |
elessair | 0:f269e3021894 | 75 | if((_sock_fd < 0) || !_is_connected) |
elessair | 0:f269e3021894 | 76 | return HTTPHeader(); |
elessair | 0:f269e3021894 | 77 | |
elessair | 0:f269e3021894 | 78 | sprintf(buf, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", request, _host.c_str()); |
elessair | 0:f269e3021894 | 79 | printf("buf=%s\n", buf); |
elessair | 0:f269e3021894 | 80 | if(send(buf, strlen(buf)) != strlen(buf)) |
elessair | 0:f269e3021894 | 81 | return HTTPHeader(); |
elessair | 0:f269e3021894 | 82 | printf("Finished sending request\n"); |
elessair | 0:f269e3021894 | 83 | return read_header(); |
elessair | 0:f269e3021894 | 84 | } |
elessair | 0:f269e3021894 | 85 | |
elessair | 0:f269e3021894 | 86 | |
elessair | 0:f269e3021894 | 87 | HTTPHeader HTTPSClient::read_header() |
elessair | 0:f269e3021894 | 88 | { |
elessair | 0:f269e3021894 | 89 | _ssl.bm_read_index = 0; |
elessair | 0:f269e3021894 | 90 | _ssl.bm_index = 0; |
elessair | 0:f269e3021894 | 91 | HTTPHeader hdr; |
elessair | 0:f269e3021894 | 92 | if(read_line()) |
elessair | 0:f269e3021894 | 93 | return hdr; |
elessair | 0:f269e3021894 | 94 | |
elessair | 0:f269e3021894 | 95 | int status; |
elessair | 0:f269e3021894 | 96 | |
elessair | 0:f269e3021894 | 97 | if(sscanf(buf, "HTTP/%*d.%*d %d %*s", &status) == -1) |
elessair | 0:f269e3021894 | 98 | return hdr; |
elessair | 0:f269e3021894 | 99 | |
elessair | 0:f269e3021894 | 100 | if(status == 200) |
elessair | 0:f269e3021894 | 101 | hdr._status = HTTP_OK; |
elessair | 0:f269e3021894 | 102 | if(read_line()) |
elessair | 0:f269e3021894 | 103 | return hdr; |
elessair | 0:f269e3021894 | 104 | do |
elessair | 0:f269e3021894 | 105 | { |
elessair | 0:f269e3021894 | 106 | string tmp(buf); |
elessair | 0:f269e3021894 | 107 | std::size_t sep = tmp.find(':'); |
elessair | 0:f269e3021894 | 108 | string name = tmp.substr(0, sep); |
elessair | 0:f269e3021894 | 109 | string value = tmp.substr(sep+2, tmp.size()); |
elessair | 0:f269e3021894 | 110 | hdr._fields[name] = value; |
elessair | 0:f269e3021894 | 111 | if(read_line()) |
elessair | 0:f269e3021894 | 112 | return hdr; |
elessair | 0:f269e3021894 | 113 | }while(strlen(buf)); |
elessair | 0:f269e3021894 | 114 | |
elessair | 0:f269e3021894 | 115 | return hdr; |
elessair | 0:f269e3021894 | 116 | } |
elessair | 0:f269e3021894 | 117 | |
elessair | 0:f269e3021894 | 118 | uint8_t HTTPSClient::read_line() |
elessair | 0:f269e3021894 | 119 | { |
elessair | 0:f269e3021894 | 120 | int index = 0; |
elessair | 0:f269e3021894 | 121 | do |
elessair | 0:f269e3021894 | 122 | { |
elessair | 0:f269e3021894 | 123 | if(ssl_read(&_ssl, (uint8_t*)(&buf[index]), 1) != 1) |
elessair | 0:f269e3021894 | 124 | { |
elessair | 0:f269e3021894 | 125 | return 1; |
elessair | 0:f269e3021894 | 126 | } |
elessair | 0:f269e3021894 | 127 | index++; |
elessair | 0:f269e3021894 | 128 | }while(buf[index-1] != '\r' && index < 256); |
elessair | 0:f269e3021894 | 129 | ssl_read(&_ssl, (uint8_t*)(&buf[index-1]), 1); // skip '\n' |
elessair | 0:f269e3021894 | 130 | buf[index-1] = '\0'; |
elessair | 0:f269e3021894 | 131 | |
elessair | 0:f269e3021894 | 132 | return 0; |
elessair | 0:f269e3021894 | 133 | } |
elessair | 0:f269e3021894 | 134 | |
elessair | 0:f269e3021894 | 135 | // -1:error |
elessair | 0:f269e3021894 | 136 | // otherwise return nb of characters read. Cannot be > than len |
elessair | 0:f269e3021894 | 137 | int HTTPSClient::read(char *data, int len) |
elessair | 0:f269e3021894 | 138 | { |
elessair | 0:f269e3021894 | 139 | return ssl_read(&_ssl, (uint8_t*)data, len); |
elessair | 0:f269e3021894 | 140 | } |
elessair | 0:f269e3021894 | 141 | /* |
elessair | 0:f269e3021894 | 142 | 0 : must close connection |
elessair | 0:f269e3021894 | 143 | -1 : error |
elessair | 0:f269e3021894 | 144 | else : get data |
elessair | 0:f269e3021894 | 145 | |
elessair | 0:f269e3021894 | 146 | int HTTPSClient::receive(char* data, int length) { |
elessair | 0:f269e3021894 | 147 | if ((_sock_fd < 0) || !_is_connected) |
elessair | 0:f269e3021894 | 148 | return -1; |
elessair | 0:f269e3021894 | 149 | |
elessair | 0:f269e3021894 | 150 | if(read_record(&_ssl) < 0) |
elessair | 0:f269e3021894 | 151 | return -1; |
elessair | 0:f269e3021894 | 152 | return process_data(&_ssl, (uint8_t*)data, length); |
elessair | 0:f269e3021894 | 153 | } |
elessair | 0:f269e3021894 | 154 | */ |
elessair | 0:f269e3021894 | 155 | void HTTPSClient::close() |
elessair | 0:f269e3021894 | 156 | { |
elessair | 0:f269e3021894 | 157 | if(!_is_connected) |
elessair | 0:f269e3021894 | 158 | return; |
elessair | 0:f269e3021894 | 159 | ssl_ctx_free(_ssl.ssl_ctx); |
elessair | 0:f269e3021894 | 160 | Socket::close(); |
elessair | 0:f269e3021894 | 161 | _is_connected = false; |
elessair | 0:f269e3021894 | 162 | _host.clear(); |
elessair | 0:f269e3021894 | 163 | } |