forked from fhessel/esp32_https_server
-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathHTTPSConnection.cpp
More file actions
159 lines (133 loc) · 4.55 KB
/
HTTPSConnection.cpp
File metadata and controls
159 lines (133 loc) · 4.55 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
#include "HTTPSConnection.hpp"
#include "mbedtls/net_sockets.h"
namespace httpsserver {
HTTPSConnection::HTTPSConnection(ResourceResolver * resResolver):
HTTPConnection(resResolver) {
_sslCreated = false;
_socket = 0;
}
HTTPSConnection::~HTTPSConnection() {
// Close the socket
closeConnection();
}
bool HTTPSConnection::isSecure() {
return true;
}
bool HTTPSConnection::setup(mbedtls_ssl_config *sslConfig) {
mbedtls_ssl_init(&_ssl);
int res = mbedtls_ssl_setup(&_ssl, sslConfig);
if (res == 0) {
return true;
} else {
char buf[100];
mbedtls_strerror(res, buf, sizeof(buf));
HTTPS_LOGE("mbedtls_ssl_setup res=%X (%s)", res, buf);
mbedtls_ssl_free(&_ssl);
return false;
}
}
bool HTTPSConnection::handshake() {
int res;
while (true) {
res = mbedtls_ssl_handshake(&_ssl);
if (res == 0) {
return true;
}
if (res != MBEDTLS_ERR_SSL_WANT_READ && res != MBEDTLS_ERR_SSL_WANT_WRITE) {
return false;
}
}
}
/**
* Initializes the connection from a server socket.
*
* The call WILL BLOCK if accept(serverSocketID) blocks. So use select() to check for that in advance.
*/
int HTTPSConnection::initialize(int serverSocketID, mbedtls_ssl_config *sslConfig, HTTPHeaders *defaultHeaders) {
if (_connectionState == STATE_UNDEFINED) {
// Let the base class connect the plain tcp socket
int resSocket = HTTPConnection::initialize(serverSocketID, defaultHeaders);
// Build up SSL Connection context if the socket has been created successfully
if (resSocket >= 0) {
_socket = resSocket;
_sslCreated = setup(sslConfig);
if (_sslCreated) {
// Bind SSL to the socket
mbedtls_ssl_set_bio(&_ssl, &_socket, mbedtls_net_send, mbedtls_net_recv, NULL);
// Perform the handshake
if (handshake()) {
return resSocket;
} else {
HTTPS_LOGE("SSL handshake failed. Aborting handshake. FID=%d", resSocket);
}
} else {
HTTPS_LOGE("SSL setup failed. Aborting handshake. FID=%d", resSocket);
}
} else {
HTTPS_LOGE("Could not accept() new connection. FID=%d", resSocket);
}
_connectionState = STATE_ERROR;
_clientState = CSTATE_ACTIVE;
// This will only be called if the connection could not be established and cleanup
// variables like _ssl etc.
closeConnection();
}
// Error: The connection has already been established or could not be established
return -1;
}
void HTTPSConnection::closeConnection() {
// FIXME: Copy from HTTPConnection, could be done better probably
if (_connectionState != STATE_ERROR && _connectionState != STATE_CLOSED) {
// First call to closeConnection - set the timestamp to calculate the timeout later on
if (_connectionState != STATE_CLOSING) {
_shutdownTS = millis();
}
// Set the connection state to closing. We stay in closing as long as SSL has not been shutdown
// correctly
_connectionState = STATE_CLOSING;
}
// Try to tear down SSL while we are in the _shutdownTS timeout period or if an error occurred
if (_sslCreated) {
if (_connectionState == STATE_ERROR || mbedtls_ssl_close_notify(&_ssl) == 0) {
// SSL shutdown will return 0 as soon as the client answered with close notify
// This means we are safe to close the socket
mbedtls_ssl_free(&_ssl);
_sslCreated = false;
} else if (_shutdownTS + HTTPS_SHUTDOWN_TIMEOUT < millis()) {
// The timeout has been hit, we force SSL shutdown now by resetting the session
mbedtls_ssl_free(&_ssl);
_sslCreated = false;
HTTPS_LOGW("SSL shutdown did not receive close notification from the client");
_connectionState = STATE_ERROR;
}
}
// If SSL has been brought down, close the socket
if (!_sslCreated) {
HTTPConnection::closeConnection();
}
}
size_t HTTPSConnection::writeBuffer(byte* buffer, size_t length) {
while (true) {
int res = mbedtls_ssl_write(&_ssl, buffer, length);
if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE) {
continue;
}
return res;
}
}
size_t HTTPSConnection::readBytesToBuffer(byte* buffer, size_t length) {
while (true) {
int res = mbedtls_ssl_read(&_ssl, buffer, length);
if (res == MBEDTLS_ERR_SSL_WANT_READ || res == MBEDTLS_ERR_SSL_WANT_WRITE) {
continue;
}
return res;
}
}
size_t HTTPSConnection::pendingByteCount() {
return mbedtls_ssl_get_bytes_avail(&_ssl);
}
bool HTTPSConnection::canReadData() {
return HTTPConnection::canReadData() || (mbedtls_ssl_get_bytes_avail(&_ssl) > 0);
}
} /* namespace httpsserver */