@@ -294,6 +294,7 @@ AsyncClient::AsyncClient(int sockfd)
294
294
, _handshake_done (true )
295
295
, _psk_ident (0 )
296
296
, _psk (0 )
297
+ , _sslctx (NULL )
297
298
#endif // ASYNC_TCP_SSL_ENABLED
298
299
, _writeSpaceRemaining (TCP_SND_BUF)
299
300
, _conn_state (0 )
@@ -561,6 +562,7 @@ bool AsyncClient::connect(const char* host, uint16_t port){
561
562
if (err == ERR_OK) {
562
563
log_v (" \t addr resolved as %08x, connecting..." , addr.u_addr .ip4 .addr );
563
564
#if ASYNC_TCP_SSL_ENABLED
565
+ _hostname = host;
564
566
return connect (IPAddress (addr.u_addr .ip4 .addr ), port, secure);
565
567
#else
566
568
return connect (IPAddress (addr.u_addr .ip4 .addr ), port);
@@ -570,6 +572,7 @@ bool AsyncClient::connect(const char* host, uint16_t port){
570
572
_conn_state = 1 ;
571
573
_connect_port = port;
572
574
#if ASYNC_TCP_SSL_ENABLED
575
+ _hostname = host;
573
576
_secure = secure;
574
577
_handshake_done = !secure;
575
578
#endif // ASYNC_TCP_SSL_ENABLED
@@ -601,7 +604,11 @@ void _tcpsock_dns_found(const char * name, struct ip_addr * ipaddr, void * arg)
601
604
void AsyncClient::_sockDelayedConnect (void )
602
605
{
603
606
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
604
610
connect (IPAddress (_connect_addr.u_addr .ip4 .addr ), _connect_port);
611
+ #endif
605
612
} else {
606
613
_conn_state = 0 ;
607
614
if (_error_cb) {
@@ -613,6 +620,32 @@ void AsyncClient::_sockDelayedConnect(void)
613
620
}
614
621
}
615
622
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
+
616
649
bool AsyncClient::_sockIsWriteable (void )
617
650
{
618
651
int res;
@@ -635,6 +668,46 @@ bool AsyncClient::_sockIsWriteable(void)
635
668
} else if (sockerr != 0 ) {
636
669
_error (sockerr);
637
670
} 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
+
638
711
// Socket is now fully connected
639
712
_conn_state = 4 ;
640
713
activity = true ;
@@ -681,7 +754,27 @@ bool AsyncClient::_flushWriteQueue(void)
681
754
do {
682
755
uint8_t * p = it->data + it->written ;
683
756
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
685
778
686
779
if (r >= 0 ) {
687
780
// Written some data into the socket
@@ -755,7 +848,38 @@ void AsyncClient::_notifyWrittenBuffers(std::deque<notify_writebuf> & notifyqueu
755
848
void AsyncClient::_sockIsReadable (void )
756
849
{
757
850
_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
+
759
883
if (r > 0 ) {
760
884
if (_recv_cb) {
761
885
_recv_cb (_recv_cb_arg, this , _readBuffer, r);
@@ -844,6 +968,12 @@ void AsyncClient::_close(void)
844
968
_conn_state = 0 ;
845
969
::close (_socket);
846
970
_socket = -1 ;
971
+ #if ASYNC_TCP_SSL_ENABLED
972
+ if (_sslctx != NULL ) {
973
+ delete _sslctx;
974
+ _sslctx = NULL ;
975
+ }
976
+ #endif
847
977
xSemaphoreGiveRecursive (_asyncsock_mutex);
848
978
849
979
_clearWriteQueue ();
@@ -856,6 +986,12 @@ void AsyncClient::_error(int8_t err)
856
986
_conn_state = 0 ;
857
987
::close (_socket);
858
988
_socket = -1 ;
989
+ #if ASYNC_TCP_SSL_ENABLED
990
+ if (_sslctx != NULL ) {
991
+ delete _sslctx;
992
+ _sslctx = NULL ;
993
+ }
994
+ #endif
859
995
xSemaphoreGiveRecursive (_asyncsock_mutex);
860
996
861
997
_clearWriteQueue ();
0 commit comments