Skip to content
This repository was archived by the owner on Jan 20, 2025. It is now read-only.

IPv6 support #105

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
86 changes: 76 additions & 10 deletions src/AsyncTCP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ void AsyncClient::onPoll(AcConnectHandler cb, void* arg){
* Main Public Methods
* */

bool AsyncClient::connect(IPAddress ip, uint16_t port){
bool AsyncClient::_connect(ip_addr_t addr, uint16_t port){
if (_pcb){
log_w("already connected, state %d", _pcb->state);
return false;
Expand All @@ -684,11 +684,7 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){
return false;
}

ip_addr_t addr;
addr.type = IPADDR_TYPE_V4;
addr.u_addr.ip4.addr = ip;

tcp_pcb* pcb = tcp_new_ip_type(IPADDR_TYPE_V4);
tcp_pcb* pcb = tcp_new_ip_type(addr.type);
if (!pcb){
log_e("pcb == NULL");
return false;
Expand All @@ -699,11 +695,26 @@ bool AsyncClient::connect(IPAddress ip, uint16_t port){
tcp_recv(pcb, &_tcp_recv);
tcp_sent(pcb, &_tcp_sent);
tcp_poll(pcb, &_tcp_poll, 1);
//_tcp_connect(pcb, &addr, port,(tcp_connected_fn)&_s_connected);
_tcp_connect(pcb, _closed_slot, &addr, port,(tcp_connected_fn)&_tcp_connected);
return true;
}

bool AsyncClient::connect(IPAddress ip, uint16_t port){
ip_addr_t addr;
addr.type = IPADDR_TYPE_V4;
addr.u_addr.ip4.addr = ip;

return _connect(addr, port);
}

bool AsyncClient::connect(IPv6Address ip, uint16_t port){
ip_addr_t addr;
addr.type = IPADDR_TYPE_V6;
memcpy(addr.u_addr.ip6.addr, static_cast<const uint32_t*>(ip), sizeof(uint32_t) * 4);

return _connect(addr, port);
}

bool AsyncClient::connect(const char* host, uint16_t port){
ip_addr_t addr;

Expand All @@ -714,6 +725,9 @@ bool AsyncClient::connect(const char* host, uint16_t port){

err_t err = dns_gethostbyname(host, &addr, (dns_found_callback)&_tcp_dns_found, this);
if(err == ERR_OK) {
if(addr.type == IPADDR_TYPE_V6) {
return connect(IPv6Address(addr.u_addr.ip6.addr), port);
}
return connect(IPAddress(addr.u_addr.ip4.addr), port);
} else if(err == ERR_INPROGRESS) {
_connect_port = port;
Expand Down Expand Up @@ -980,6 +994,8 @@ int8_t AsyncClient::_poll(tcp_pcb* pcb){
void AsyncClient::_dns_found(struct ip_addr *ipaddr){
if(ipaddr && ipaddr->u_addr.ip4.addr){
connect(IPAddress(ipaddr->u_addr.ip4.addr), _connect_port);
} else if(ipaddr && ipaddr->u_addr.ip6.addr){
connect(IPv6Address(ipaddr->u_addr.ip6.addr), _connect_port);
} else {
if(_error_cb) {
_error_cb(_error_cb_arg, this, -55);
Expand Down Expand Up @@ -1071,6 +1087,15 @@ uint32_t AsyncClient::getRemoteAddress() {
return _pcb->remote_ip.u_addr.ip4.addr;
}

ip6_addr_t AsyncClient::getRemoteAddress6() {
if(!_pcb) {
ip6_addr_t nulladdr;
ip6_addr_set_zero(&nulladdr);
return nulladdr;
}
return _pcb->remote_ip.u_addr.ip6;
}

uint16_t AsyncClient::getRemotePort() {
if(!_pcb) {
return 0;
Expand All @@ -1085,6 +1110,15 @@ uint32_t AsyncClient::getLocalAddress() {
return _pcb->local_ip.u_addr.ip4.addr;
}

ip6_addr_t AsyncClient::getLocalAddress6() {
if(!_pcb) {
ip6_addr_t nulladdr;
ip6_addr_set_zero(&nulladdr);
return nulladdr;
}
return _pcb->local_ip.u_addr.ip6;
}

uint16_t AsyncClient::getLocalPort() {
if(!_pcb) {
return 0;
Expand All @@ -1096,6 +1130,10 @@ IPAddress AsyncClient::remoteIP() {
return IPAddress(getRemoteAddress());
}

IPv6Address AsyncClient::remoteIP6() {
return IPv6Address(getRemoteAddress6().addr);
}

uint16_t AsyncClient::remotePort() {
return getRemotePort();
}
Expand All @@ -1104,6 +1142,10 @@ IPAddress AsyncClient::localIP() {
return IPAddress(getLocalAddress());
}

IPv6Address AsyncClient::localIP6() {
return IPv6Address(getLocalAddress6().addr);
}

uint16_t AsyncClient::localPort() {
return getLocalPort();
}
Expand Down Expand Up @@ -1236,16 +1278,30 @@ int8_t AsyncClient::_s_connected(void * arg, void * pcb, int8_t err){

AsyncServer::AsyncServer(IPAddress addr, uint16_t port)
: _port(port)
, _bind4(true)
, _addr(addr)
, _noDelay(false)
, _pcb(0)
, _connect_cb(0)
, _connect_cb_arg(0)
{}

AsyncServer::AsyncServer(IPv6Address addr, uint16_t port)
: _port(port)
, _bind6(true)
, _addr6(addr)
, _noDelay(false)
, _pcb(0)
, _connect_cb(0)
, _connect_cb_arg(0)
{}

AsyncServer::AsyncServer(uint16_t port)
: _port(port)
, _bind4(true)
, _bind6(true)
, _addr((uint32_t) IPADDR_ANY)
, _addr6()
, _noDelay(false)
, _pcb(0)
, _connect_cb(0)
Expand All @@ -1270,16 +1326,26 @@ void AsyncServer::begin(){
log_e("failed to start task");
return;
}
int8_t err;
_pcb = tcp_new_ip_type(IPADDR_TYPE_V4);
int8_t err, bind_type;

if(_bind4 && _bind6) {
bind_type = IPADDR_TYPE_ANY;
} else if (_bind6) {
bind_type = IPADDR_TYPE_V6;
} else {
bind_type = IPADDR_TYPE_V4;
}

_pcb = tcp_new_ip_type(bind_type);
if (!_pcb){
log_e("_pcb == NULL");
return;
}

ip_addr_t local_addr;
local_addr.type = IPADDR_TYPE_V4;
local_addr.type = bind_type;
local_addr.u_addr.ip4.addr = (uint32_t) _addr;
memcpy(local_addr.u_addr.ip6.addr, static_cast<const uint32_t*>(_addr6), sizeof(uint32_t) * 4);
err = _tcp_bind(_pcb, &local_addr, _port);

if (err != ERR_OK) {
Expand Down
20 changes: 17 additions & 3 deletions src/AsyncTCP.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,14 @@
#define ASYNCTCP_H_

#include "IPAddress.h"
#include "IPv6Address.h"
#include "sdkconfig.h"
#include <functional>
extern "C" {
#include "freertos/semphr.h"
#include "lwip/pbuf.h"
#include "lwip/ip_addr.h"
#include "lwip/ip6_addr.h"
}

//If core is not defined, then we are running in Arduino or PIO
Expand Down Expand Up @@ -66,7 +69,8 @@ class AsyncClient {
return !(*this == other);
}
bool connect(IPAddress ip, uint16_t port);
bool connect(const char* host, uint16_t port);
bool connect(IPv6Address ip, uint16_t port);
bool connect(const char *host, uint16_t port);
void close(bool now = false);
void stop();
int8_t abort();
Expand Down Expand Up @@ -100,15 +104,19 @@ class AsyncClient {
bool getNoDelay();

uint32_t getRemoteAddress();
ip6_addr_t getRemoteAddress6();
uint16_t getRemotePort();
uint32_t getLocalAddress();
ip6_addr_t getLocalAddress6();
uint16_t getLocalPort();

//compatibility
IPAddress remoteIP();
uint16_t remotePort();
IPv6Address remoteIP6();
uint16_t remotePort();
IPAddress localIP();
uint16_t localPort();
IPv6Address localIP6();
uint16_t localPort();

void onConnect(AcConnectHandler cb, void* arg = 0); //on successful connect
void onDisconnect(AcConnectHandler cb, void* arg = 0); //disconnected
Expand Down Expand Up @@ -140,6 +148,8 @@ class AsyncClient {
tcp_pcb * pcb(){ return _pcb; }

protected:
bool _connect(ip_addr_t addr, uint16_t port);

tcp_pcb* _pcb;
int8_t _closed_slot;

Expand Down Expand Up @@ -188,6 +198,7 @@ class AsyncClient {
class AsyncServer {
public:
AsyncServer(IPAddress addr, uint16_t port);
AsyncServer(IPv6Address addr, uint16_t port);
AsyncServer(uint16_t port);
~AsyncServer();
void onClient(AcConnectHandler cb, void* arg);
Expand All @@ -203,7 +214,10 @@ class AsyncServer {

protected:
uint16_t _port;
bool _bind4 = false;
bool _bind6 = false;
IPAddress _addr;
IPv6Address _addr6;
bool _noDelay;
tcp_pcb* _pcb;
AcConnectHandler _connect_cb;
Expand Down