Skip to content

Commit 01dd9c4

Browse files
committed
IPv6 support for WiFiClientSecure / ssl_client
Similar to implementation in WiFiClient, we implement WiFiClientSecure with IPv6 support with minimal differences. As i'm trying to keep maximum compatibility, i introduce different behaviour if IPv6 is enabled, and backward compatible (as much as possible), if IPv6 is not enabled. IN future when IPv6 functions are tested well enough, it can be simplified. This implementation tested on esp32 in following scenarios using BasicHttpClient using https:// urls: IPv6 true: IPv6 only website (caveat 1) - OK Website with A and AAAA is present (caveat 1) - OK IPv4 only website - OK IPv6 not enabled: IPv6 only website - wont open (expected) Website with A and AAAA is present - OK, opens over IPv4 IPv4 only website - OK caveat 1 - sometimes SLAAC is slower than DHCPv4, so we might have status WL_CONNECTED, but IPv6 global scope is not ready yet. Signed-off-by: Denys Fedoryshchenko <[email protected]>
1 parent 7b27e78 commit 01dd9c4

File tree

1 file changed

+34
-12
lines changed

1 file changed

+34
-12
lines changed

Diff for: libraries/WiFiClientSecure/src/ssl_client.cpp

+34-12
Original file line numberDiff line numberDiff line change
@@ -60,31 +60,53 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
6060
int ret, flags;
6161
int enable = 1;
6262
log_v("Free internal heap before TLS %u", ESP.getFreeHeap());
63+
bool is_ipv4 = true;
6364

6465
if (rootCABuff == NULL && pskIdent == NULL && psKey == NULL && !insecure && !useRootCABundle) {
6566
return -1;
6667
}
6768

6869
log_v("Starting socket");
6970
ssl_client->socket = -1;
71+
struct sockaddr_storage serveraddr;
72+
ip_addr_t dstip;
73+
IPAddress srv((uint32_t)0);
74+
75+
if (WiFiGenericClass::getStatusBits() & WIFI_WANT_IP6_BIT) {
76+
ip_addr_t srv6;
77+
if(!WiFiGenericClass::hostByName6(host, srv6)){
78+
return -1;
79+
}
80+
if (IP_IS_V6(&srv6)) {
81+
is_ipv4 = false;
82+
ssl_client->socket = lwip_socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
83+
struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr;
84+
memset((char *) tmpaddr, 0, sizeof(struct sockaddr_in6));
85+
tmpaddr->sin6_family = AF_INET6;
86+
inet6_addr_from_ip6addr(&tmpaddr->sin6_addr, ip_2_ip6(&srv6));
87+
tmpaddr->sin6_port = htons(port);
88+
} else {
89+
srv = ip4_addr_get_u32(&srv6.u_addr.ip4);
90+
}
91+
} else {
92+
if(!WiFiGenericClass::hostByName(host, srv))
93+
return -1;
94+
}
95+
if (is_ipv4 == true) {
96+
ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
97+
struct sockaddr_in *serv_addr = (struct sockaddr_in*)&serveraddr;
98+
memset(serv_addr, 0, sizeof(serv_addr));
99+
serv_addr->sin_family = AF_INET;
100+
serv_addr->sin_addr.s_addr = srv;
101+
serv_addr->sin_port = htons(port);
102+
}
70103

71-
ssl_client->socket = lwip_socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
72104
if (ssl_client->socket < 0) {
73105
log_e("ERROR opening socket");
74106
return ssl_client->socket;
75107
}
76108

77-
IPAddress srv((uint32_t)0);
78-
if(!WiFiGenericClass::hostByName(host, srv)){
79-
return -1;
80-
}
81-
82109
fcntl( ssl_client->socket, F_SETFL, fcntl( ssl_client->socket, F_GETFL, 0 ) | O_NONBLOCK );
83-
struct sockaddr_in serv_addr;
84-
memset(&serv_addr, 0, sizeof(serv_addr));
85-
serv_addr.sin_family = AF_INET;
86-
serv_addr.sin_addr.s_addr = srv;
87-
serv_addr.sin_port = htons(port);
88110

89111
if(timeout <= 0){
90112
timeout = 30000; // Milli seconds.
@@ -97,7 +119,7 @@ int start_ssl_client(sslclient_context *ssl_client, const char *host, uint32_t p
97119
tv.tv_sec = timeout / 1000;
98120
tv.tv_usec = (timeout % 1000) * 1000;
99121

100-
int res = lwip_connect(ssl_client->socket, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
122+
int res = lwip_connect(ssl_client->socket, (struct sockaddr*)&serveraddr, sizeof(serveraddr));
101123
if (res < 0 && errno != EINPROGRESS) {
102124
log_e("connect on fd %d, errno: %d, \"%s\"", ssl_client->socket, errno, strerror(errno));
103125
close(ssl_client->socket);

0 commit comments

Comments
 (0)