@@ -28,6 +28,7 @@ extern "C"{
28
28
#include " lwip/inet.h"
29
29
#include " lwip/dns.h"
30
30
}
31
+ #include " lwipr_compat.h"
31
32
32
33
/*
33
34
Async TCP Client
@@ -47,6 +48,8 @@ AsyncClient::AsyncClient(tcp_pcb* pcb):
47
48
, _timeout_cb(0 )
48
49
, _timeout_cb_arg(0 )
49
50
, _pcb_busy(false )
51
+ , _pcb_secure(false )
52
+ , _handshake_done(true )
50
53
, _pcb_sent_at(0 )
51
54
, _close_pcb(false )
52
55
, _ack_pcb(true )
@@ -73,7 +76,7 @@ AsyncClient::~AsyncClient(){
73
76
_close ();
74
77
}
75
78
76
- bool AsyncClient::connect (IPAddress ip, uint16_t port){
79
+ bool AsyncClient::connect (IPAddress ip, uint16_t port, bool secure ){
77
80
78
81
if (_pcb) // already connected
79
82
return false ;
@@ -88,18 +91,22 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){
88
91
if (!pcb) // could not allocate pcb
89
92
return false ;
90
93
94
+ _pcb_secure = secure;
95
+ _handshake_done = !secure;
91
96
tcp_arg (pcb, this );
92
97
tcp_err (pcb, &_s_error);
93
98
tcp_connect (pcb, &addr, port,(tcp_connected_fn)&_s_connected);
94
99
return true ;
95
100
}
96
101
97
- bool AsyncClient::connect (const char * host, uint16_t port) {
102
+ bool AsyncClient::connect (const char * host, uint16_t port, bool secure ) {
98
103
ip_addr_t addr;
99
104
err_t err = dns_gethostbyname (host, &addr, (dns_found_callback)&_s_dns_found, this );
100
105
if (err == ERR_OK) {
101
- return connect (IPAddress (addr.addr ), port);
106
+ return connect (IPAddress (addr.addr ), port, secure );
102
107
} else if (err == ERR_INPROGRESS) {
108
+ _pcb_secure = secure;
109
+ _handshake_done = !secure;
103
110
_connect_port = port;
104
111
return true ;
105
112
}
@@ -165,6 +172,13 @@ size_t AsyncClient::write(const char* data, size_t size) {
165
172
return 0 ;
166
173
if (!canSend ())
167
174
return 0 ;
175
+ if (_pcb_secure){
176
+ int sent = axl_write (_pcb, (uint8_t *)data, size);
177
+ if (sent >= 0 )
178
+ return sent;
179
+ // ssl error
180
+ return 0 ;
181
+ }
168
182
size_t room = tcp_sndbuf (_pcb);
169
183
size_t will_send = (room < size) ? room : size;
170
184
int8_t err = tcp_write (_pcb, data, will_send, 0 );
@@ -188,6 +202,13 @@ size_t AsyncClient::add(const char* data, size_t size) {
188
202
size_t room = tcp_sndbuf (_pcb);
189
203
if (!room)
190
204
return 0 ;
205
+ if (_pcb_secure){
206
+ int sent = axl_write (_pcb, (uint8_t *)data, size);
207
+ if (sent >= 0 )
208
+ return sent;
209
+ // ssl error
210
+ return 0 ;
211
+ }
191
212
size_t will_send = (room < size) ? room : size;
192
213
int8_t err = tcp_write (_pcb, data, will_send, 0 );
193
214
if (err != ERR_OK)
@@ -196,6 +217,8 @@ size_t AsyncClient::add(const char* data, size_t size) {
196
217
}
197
218
198
219
bool AsyncClient::send (){
220
+ if (_pcb_secure)
221
+ return true ;
199
222
if (!canSend ())
200
223
return false ;
201
224
if (tcp_output (_pcb) == ERR_OK){
@@ -225,6 +248,8 @@ int8_t AsyncClient::_close(){
225
248
tcp_recv (_pcb, NULL );
226
249
tcp_err (_pcb, NULL );
227
250
tcp_poll (_pcb, NULL , 0 );
251
+ if (_pcb_secure)
252
+ axl_free (_pcb);
228
253
err = tcp_close (_pcb);
229
254
if (err != ERR_OK) {
230
255
err = abort ();
@@ -239,13 +264,23 @@ int8_t AsyncClient::_close(){
239
264
int8_t AsyncClient::_connected (void * pcb, int8_t err){
240
265
_pcb = reinterpret_cast <tcp_pcb*>(pcb);
241
266
if (_pcb){
267
+ if (_pcb_secure){
268
+ axl_tcp_t * axl = axl_new (_pcb);
269
+ if (axl == NULL ){
270
+ return _close ();
271
+ }
272
+ axl_arg (_pcb, this );
273
+ axl_data (_pcb, &_s_data);
274
+ axl_handshake (_pcb, &_s_handshake);
275
+ axl_err (_pcb, &_s_ssl_error);
276
+ }
242
277
tcp_setprio (_pcb, TCP_PRIO_MIN);
243
278
tcp_recv (_pcb, &_s_recv);
244
279
tcp_sent (_pcb, &_s_sent);
245
280
tcp_poll (_pcb, &_s_poll, 1 );
246
281
_pcb_busy = false ;
247
282
}
248
- if (_connect_cb)
283
+ if (!_pcb_secure && _connect_cb)
249
284
_connect_cb (_connect_cb_arg, this );
250
285
return ERR_OK;
251
286
}
@@ -257,6 +292,8 @@ void AsyncClient::_error(int8_t err) {
257
292
tcp_recv (_pcb, NULL );
258
293
tcp_err (_pcb, NULL );
259
294
tcp_poll (_pcb, NULL , 0 );
295
+ if (_pcb_secure)
296
+ axl_free (_pcb);
260
297
_pcb = NULL ;
261
298
}
262
299
if (_error_cb)
@@ -265,6 +302,11 @@ void AsyncClient::_error(int8_t err) {
265
302
_discard_cb (_discard_cb_arg, this );
266
303
}
267
304
305
+ void AsyncClient::_ssl_error (int8_t err){
306
+ if (_error_cb)
307
+ _error_cb (_error_cb_arg, this , err+64 );
308
+ }
309
+
268
310
int8_t AsyncClient::_sent (tcp_pcb* pcb, uint16_t len) {
269
311
_rx_last_packet = millis ();
270
312
_pcb_busy = false ;
@@ -279,7 +321,16 @@ int8_t AsyncClient::_recv(tcp_pcb* pcb, pbuf* pb, int8_t err) {
279
321
}
280
322
281
323
_rx_last_packet = millis ();
282
- // use callback (onData defined)
324
+ if (_pcb_secure){
325
+ int read_bytes = axl_read (pcb, pb);
326
+ if (read_bytes < 0 ){
327
+ if (read_bytes != SSL_CLOSE_NOTIFY && read_bytes != SSL_ERROR_CONN_LOST) {
328
+ _close ();
329
+ }
330
+ return read_bytes;
331
+ }
332
+ return ERR_OK;
333
+ }
283
334
while (pb != NULL ){
284
335
// we should not ack before we assimilate the data
285
336
_ack_pcb = true ;
@@ -326,7 +377,7 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){
326
377
327
378
void AsyncClient::_dns_found (ip_addr_t *ipaddr){
328
379
if (ipaddr){
329
- connect (IPAddress (ipaddr->addr ), _connect_port);
380
+ connect (IPAddress (ipaddr->addr ), _connect_port, _pcb_secure );
330
381
} else {
331
382
if (_error_cb)
332
383
_error_cb (_error_cb_arg, this , -55 );
@@ -361,6 +412,24 @@ int8_t AsyncClient::_s_connected(void* arg, void* tpcb, int8_t err){
361
412
return reinterpret_cast <AsyncClient*>(arg)->_connected (tpcb, err);
362
413
}
363
414
415
+ void AsyncClient::_s_data (void *arg, struct tcp_pcb *tcp, uint8_t * data, size_t len){
416
+ AsyncClient *c = reinterpret_cast <AsyncClient*>(arg);
417
+ if (c->_recv_cb )
418
+ c->_recv_cb (c->_recv_cb_arg , c, data, len);
419
+ }
420
+
421
+ void AsyncClient::_s_handshake (void *arg, struct tcp_pcb *tcp, SSL *ssl){
422
+ AsyncClient *c = reinterpret_cast <AsyncClient*>(arg);
423
+ c->_handshake_done = true ;
424
+ if (c->_connect_cb )
425
+ c->_connect_cb (c->_connect_cb_arg , c);
426
+ }
427
+
428
+ void AsyncClient::_s_ssl_error (void *arg, struct tcp_pcb *tcp, int8_t err){
429
+ reinterpret_cast <AsyncClient*>(arg)->_ssl_error (err);
430
+ }
431
+
432
+
364
433
// Operators
365
434
366
435
AsyncClient & AsyncClient::operator +=(const AsyncClient &other) {
@@ -447,6 +516,16 @@ uint16_t AsyncClient::localPort() {
447
516
return getLocalPort ();
448
517
}
449
518
519
+ SSL * AsyncClient::getSSL (){
520
+ if (_pcb && _pcb_secure){
521
+ axl_tcp_t * axl = axl_get (_pcb);
522
+ if (axl){
523
+ return axl->ssl ;
524
+ }
525
+ }
526
+ return NULL ;
527
+ }
528
+
450
529
uint8_t AsyncClient::state () {
451
530
if (!_pcb)
452
531
return 0 ;
@@ -456,7 +535,7 @@ uint8_t AsyncClient::state() {
456
535
bool AsyncClient::connected (){
457
536
if (!_pcb)
458
537
return false ;
459
- return _pcb->state == 4 ;
538
+ return _pcb->state == 4 && _handshake_done ;
460
539
}
461
540
462
541
bool AsyncClient::connecting (){
0 commit comments