Skip to content

Commit 37974a7

Browse files
committed
Use TLS context on AsyncTCP if enabled
Compile tested only.
1 parent a042d8e commit 37974a7

File tree

2 files changed

+145
-2
lines changed

2 files changed

+145
-2
lines changed

src/AsyncTCP.cpp

Lines changed: 138 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,7 @@ AsyncClient::AsyncClient(int sockfd)
294294
, _handshake_done(true)
295295
, _psk_ident(0)
296296
, _psk(0)
297+
, _sslctx(NULL)
297298
#endif // ASYNC_TCP_SSL_ENABLED
298299
, _writeSpaceRemaining(TCP_SND_BUF)
299300
, _conn_state(0)
@@ -561,6 +562,7 @@ bool AsyncClient::connect(const char* host, uint16_t port){
561562
if(err == ERR_OK) {
562563
log_v("\taddr resolved as %08x, connecting...", addr.u_addr.ip4.addr);
563564
#if ASYNC_TCP_SSL_ENABLED
565+
_hostname = host;
564566
return connect(IPAddress(addr.u_addr.ip4.addr), port, secure);
565567
#else
566568
return connect(IPAddress(addr.u_addr.ip4.addr), port);
@@ -570,6 +572,7 @@ bool AsyncClient::connect(const char* host, uint16_t port){
570572
_conn_state = 1;
571573
_connect_port = port;
572574
#if ASYNC_TCP_SSL_ENABLED
575+
_hostname = host;
573576
_secure = secure;
574577
_handshake_done = !secure;
575578
#endif // ASYNC_TCP_SSL_ENABLED
@@ -601,7 +604,11 @@ void _tcpsock_dns_found(const char * name, struct ip_addr * ipaddr, void * arg)
601604
void AsyncClient::_sockDelayedConnect(void)
602605
{
603606
if (_connect_addr.u_addr.ip4.addr) {
607+
#if ASYNC_TCP_SSL_ENABLED
608+
connect(IPAddress(_connect_addr.u_addr.ip4.addr), _connect_port, _secure);
609+
#else
604610
connect(IPAddress(_connect_addr.u_addr.ip4.addr), _connect_port);
611+
#endif
605612
} else {
606613
_conn_state = 0;
607614
if(_error_cb) {
@@ -613,6 +620,32 @@ void AsyncClient::_sockDelayedConnect(void)
613620
}
614621
}
615622

623+
#if ASYNC_TCP_SSL_ENABLED
624+
int AsyncClient::_runSSLHandshakeLoop(void)
625+
{
626+
int res = 0;
627+
628+
while (!_handshake_done) {
629+
res = _sslctx->runSSLHandshake();
630+
if (res == 0) {
631+
// Handshake successful
632+
_handshake_done = true;
633+
} else if (ASYNCTCP_TLS_CAN_RETRY(res)) {
634+
// Ran out of readable data or writable space on socket, must continue later
635+
break;
636+
} else {
637+
// SSL handshake for AsyncTCP does not inform SSL errors
638+
log_e("TLS setup failed with error %d, closing socket...", res);
639+
_close();
640+
// _sslctx should be NULL after this
641+
break;
642+
}
643+
}
644+
645+
return res;
646+
}
647+
#endif
648+
616649
bool AsyncClient::_sockIsWriteable(void)
617650
{
618651
int res;
@@ -635,6 +668,46 @@ bool AsyncClient::_sockIsWriteable(void)
635668
} else if (sockerr != 0) {
636669
_error(sockerr);
637670
} else {
671+
#if ASYNC_TCP_SSL_ENABLED
672+
if (_secure) {
673+
int res = 0;
674+
675+
if (_sslctx == NULL) {
676+
String remIP_str = remoteIP().toString();
677+
const char * host_or_ip = _hostname.isEmpty()
678+
? remIP_str.c_str()
679+
: _hostname.c_str();
680+
681+
_sslctx = new AsyncTCP_TLS_Context();
682+
if (_root_ca != NULL) {
683+
res = _sslctx->startSSLClient(_socket, host_or_ip,
684+
(const unsigned char *)_root_ca, _root_ca_len,
685+
(const unsigned char *)_cli_cert, _cli_cert_len,
686+
(const unsigned char *)_cli_key, _cli_key_len);
687+
} else if (_psk_ident != NULL) {
688+
res = _sslctx->startSSLClient(_socket, host_or_ip,
689+
_psk_ident, _psk);
690+
} else {
691+
res = _sslctx->startSSLClientInsecure(_socket, host_or_ip);
692+
}
693+
694+
if (res != 0) {
695+
// SSL setup for AsyncTCP does not inform SSL errors
696+
log_e("TLS setup failed with error %d, closing socket...", res);
697+
_close();
698+
// _sslctx should be NULL after this
699+
}
700+
}
701+
702+
// _handshake_done is set to FALSE on connect() if encrypted connection
703+
if (_sslctx != NULL && res == 0) res = _runSSLHandshakeLoop();
704+
705+
if (!_handshake_done) return ASYNCTCP_TLS_CAN_RETRY(res);
706+
707+
// Fallthrough to ordinary successful connection
708+
}
709+
#endif
710+
638711
// Socket is now fully connected
639712
_conn_state = 4;
640713
activity = true;
@@ -681,7 +754,27 @@ bool AsyncClient::_flushWriteQueue(void)
681754
do {
682755
uint8_t * p = it->data + it->written;
683756
size_t n = it->length - it->written;
684-
errno = 0; ssize_t r = lwip_write(_socket, p, n);
757+
errno = 0;
758+
ssize_t r;
759+
760+
#if ASYNC_TCP_SSL_ENABLED
761+
if (_sslctx != NULL) {
762+
r = _sslctx->write(p, n);
763+
if (ASYNCTCP_TLS_CAN_RETRY(r)) {
764+
r = -1;
765+
errno = EAGAIN;
766+
} else if (ASYNCTCP_TLS_EOF(r)) {
767+
r = -1;
768+
errno = EPIPE;
769+
} else if (r < 0) {
770+
if (errno == 0) errno = EIO;
771+
}
772+
} else {
773+
#endif
774+
r = lwip_write(_socket, p, n);
775+
#if ASYNC_TCP_SSL_ENABLED
776+
}
777+
#endif
685778

686779
if (r >= 0) {
687780
// Written some data into the socket
@@ -755,7 +848,38 @@ void AsyncClient::_notifyWrittenBuffers(std::deque<notify_writebuf> & notifyqueu
755848
void AsyncClient::_sockIsReadable(void)
756849
{
757850
_rx_last_packet = millis();
758-
errno = 0; ssize_t r = lwip_read(_socket, _readBuffer, MAX_PAYLOAD_SIZE);
851+
errno = 0;
852+
ssize_t r;
853+
854+
#if ASYNC_TCP_SSL_ENABLED
855+
if (_sslctx != NULL) {
856+
if (!_handshake_done) {
857+
// Handshake process has stopped for want of data, must be
858+
// continued here for connection to complete.
859+
_runSSLHandshakeLoop();
860+
861+
// If handshake was successful, this will be recognized when the socket
862+
// next becomes writable. No other read operation should be done here.
863+
return;
864+
} else {
865+
r = _sslctx->read(_readBuffer, MAX_PAYLOAD_SIZE);
866+
if (ASYNCTCP_TLS_CAN_RETRY(r)) {
867+
r = -1;
868+
errno = EAGAIN;
869+
} else if (ASYNCTCP_TLS_EOF(r)) {
870+
// Simulate "successful" end-of-stream condition
871+
r = 0;
872+
} else if (r < 0) {
873+
if (errno == 0) errno = EIO;
874+
}
875+
}
876+
} else {
877+
#endif
878+
r = lwip_read(_socket, _readBuffer, MAX_PAYLOAD_SIZE);
879+
#if ASYNC_TCP_SSL_ENABLED
880+
}
881+
#endif
882+
759883
if (r > 0) {
760884
if(_recv_cb) {
761885
_recv_cb(_recv_cb_arg, this, _readBuffer, r);
@@ -844,6 +968,12 @@ void AsyncClient::_close(void)
844968
_conn_state = 0;
845969
::close(_socket);
846970
_socket = -1;
971+
#if ASYNC_TCP_SSL_ENABLED
972+
if (_sslctx != NULL) {
973+
delete _sslctx;
974+
_sslctx = NULL;
975+
}
976+
#endif
847977
xSemaphoreGiveRecursive(_asyncsock_mutex);
848978

849979
_clearWriteQueue();
@@ -856,6 +986,12 @@ void AsyncClient::_error(int8_t err)
856986
_conn_state = 0;
857987
::close(_socket);
858988
_socket = -1;
989+
#if ASYNC_TCP_SSL_ENABLED
990+
if (_sslctx != NULL) {
991+
delete _sslctx;
992+
_sslctx = NULL;
993+
}
994+
#endif
859995
xSemaphoreGiveRecursive(_asyncsock_mutex);
860996

861997
_clearWriteQueue();

src/AsyncTCP.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ class AsyncClient : public AsyncSocketBase
203203
bool _handshake_done;
204204
const char* _psk_ident;
205205
const char* _psk;
206+
207+
String _hostname;
208+
AsyncTCP_TLS_Context * _sslctx;
206209
#endif // ASYNC_TCP_SSL_ENABLED
207210

208211
// The following private struct represents a buffer enqueued with the add()
@@ -244,6 +247,10 @@ class AsyncClient : public AsyncSocketBase
244247
void _collectNotifyWrittenBuffers(std::deque<notify_writebuf> &, int &);
245248
void _notifyWrittenBuffers(std::deque<notify_writebuf> &, int);
246249

250+
#if ASYNC_TCP_SSL_ENABLED
251+
int _runSSLHandshakeLoop(void);
252+
#endif
253+
247254
friend void _tcpsock_dns_found(const char * name, struct ip_addr * ipaddr, void * arg);
248255
};
249256

0 commit comments

Comments
 (0)