@@ -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 (" \t addr 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)
601604void 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+
616649bool 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
755848void 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 ();
0 commit comments