|
23 | 23 | #include <lwip/netdb.h> |
24 | 24 | #include <errno.h> |
25 | 25 |
|
| 26 | +#define IN6_IS_ADDR_V4MAPPED(a) \ |
| 27 | + ((((__const uint32_t *) (a))[0] == 0) \ |
| 28 | + && (((__const uint32_t *) (a))[1] == 0) \ |
| 29 | + && (((__const uint32_t *) (a))[2] == htonl (0xffff))) |
| 30 | + |
26 | 31 | #define WIFI_CLIENT_DEF_CONN_TIMEOUT_MS (3000) |
27 | 32 | #define WIFI_CLIENT_MAX_WRITE_RETRY (10) |
28 | 33 | #define WIFI_CLIENT_SELECT_TIMEOUT_US (1000000) |
@@ -219,22 +224,33 @@ int WiFiClient::connect(IPAddress ip, uint16_t port) |
219 | 224 | { |
220 | 225 | return connect(ip,port,_timeout); |
221 | 226 | } |
| 227 | + |
222 | 228 | int WiFiClient::connect(IPAddress ip, uint16_t port, int32_t timeout_ms) |
223 | 229 | { |
| 230 | + struct sockaddr_storage serveraddr = {}; |
224 | 231 | _timeout = timeout_ms; |
225 | | - int sockfd = socket(AF_INET, SOCK_STREAM, 0); |
| 232 | + int sockfd = -1; |
| 233 | + |
| 234 | + if (ip.type() == IPv6) { |
| 235 | + struct sockaddr_in6 *tmpaddr = (struct sockaddr_in6 *)&serveraddr; |
| 236 | + sockfd = socket(AF_INET6, SOCK_STREAM, 0); |
| 237 | + tmpaddr->sin6_family = AF_INET6; |
| 238 | + memcpy(tmpaddr->sin6_addr.un.u8_addr, &ip[0], 16); |
| 239 | + tmpaddr->sin6_port = htons(port); |
| 240 | + tmpaddr->sin6_scope_id = ip.zone(); |
| 241 | + } else { |
| 242 | + struct sockaddr_in *tmpaddr = (struct sockaddr_in *)&serveraddr; |
| 243 | + sockfd = socket(AF_INET, SOCK_STREAM, 0); |
| 244 | + tmpaddr->sin_family = AF_INET; |
| 245 | + tmpaddr->sin_addr.s_addr = ip; |
| 246 | + tmpaddr->sin_port = htons(port); |
| 247 | + } |
226 | 248 | if (sockfd < 0) { |
227 | 249 | log_e("socket: %d", errno); |
228 | 250 | return 0; |
229 | 251 | } |
230 | 252 | fcntl( sockfd, F_SETFL, fcntl( sockfd, F_GETFL, 0 ) | O_NONBLOCK ); |
231 | 253 |
|
232 | | - uint32_t ip_addr = ip; |
233 | | - struct sockaddr_in serveraddr; |
234 | | - memset((char *) &serveraddr, 0, sizeof(serveraddr)); |
235 | | - serveraddr.sin_family = AF_INET; |
236 | | - memcpy((void *)&serveraddr.sin_addr.s_addr, (const void *)(&ip_addr), 4); |
237 | | - serveraddr.sin_port = htons(port); |
238 | 254 | fd_set fdset; |
239 | 255 | struct timeval tv; |
240 | 256 | FD_ZERO(&fdset); |
@@ -303,6 +319,19 @@ int WiFiClient::connect(const char *host, uint16_t port) |
303 | 319 |
|
304 | 320 | int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout_ms) |
305 | 321 | { |
| 322 | + if (WiFiGenericClass::getStatusBits() & WIFI_WANT_IP6_BIT) { |
| 323 | + ip_addr_t srv6; |
| 324 | + if(!WiFiGenericClass::hostByName6(host, srv6)){ |
| 325 | + return 0; |
| 326 | + } |
| 327 | + if (srv6.type == IPADDR_TYPE_V4) { |
| 328 | + IPAddress ip(srv6.u_addr.ip4.addr); |
| 329 | + return connect(ip, port, timeout_ms); |
| 330 | + } else { |
| 331 | + IPAddress ip(IPv6, (uint8_t*)&srv6.u_addr.ip6.addr[0]); |
| 332 | + return connect(ip, port, timeout_ms); |
| 333 | + } |
| 334 | + } |
306 | 335 | IPAddress srv((uint32_t)0); |
307 | 336 | if(!WiFiGenericClass::hostByName(host, srv)){ |
308 | 337 | return 0; |
@@ -574,8 +603,24 @@ IPAddress WiFiClient::remoteIP(int fd) const |
574 | 603 | struct sockaddr_storage addr; |
575 | 604 | socklen_t len = sizeof addr; |
576 | 605 | getpeername(fd, (struct sockaddr*)&addr, &len); |
577 | | - struct sockaddr_in *s = (struct sockaddr_in *)&addr; |
578 | | - return IPAddress((uint32_t)(s->sin_addr.s_addr)); |
| 606 | + |
| 607 | + // IPv4 socket, old way |
| 608 | + if (((struct sockaddr*)&addr)->sa_family == AF_INET) { |
| 609 | + struct sockaddr_in *s = (struct sockaddr_in *)&addr; |
| 610 | + return IPAddress((uint32_t)(s->sin_addr.s_addr)); |
| 611 | + } |
| 612 | + |
| 613 | + // IPv6, but it might be IPv4 mapped address |
| 614 | + if (((struct sockaddr*)&addr)->sa_family == AF_INET6) { |
| 615 | + struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)&addr; |
| 616 | + if (IN6_IS_ADDR_V4MAPPED(saddr6->sin6_addr.un.u32_addr)) { |
| 617 | + return IPAddress(IPv4, (uint8_t*)saddr6->sin6_addr.s6_addr+12); |
| 618 | + } else { |
| 619 | + return IPAddress(IPv6, (uint8_t*)(saddr6->sin6_addr.s6_addr), saddr6->sin6_scope_id); |
| 620 | + } |
| 621 | + } |
| 622 | + log_e("WiFiClient::remoteIP Not AF_INET or AF_INET6?"); |
| 623 | + return (IPAddress(0,0,0,0)); |
579 | 624 | } |
580 | 625 |
|
581 | 626 | uint16_t WiFiClient::remotePort(int fd) const |
@@ -638,4 +683,3 @@ int WiFiClient::fd() const |
638 | 683 | return clientSocketHandle->fd(); |
639 | 684 | } |
640 | 685 | } |
641 | | - |
|
0 commit comments