1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-07-27 18:02:17 +03:00

IPv6 on esp8266-nonos-sdk and arduino (#5136)

This commit is contained in:
david gauchard
2018-11-27 23:07:47 +01:00
committed by GitHub
parent a501d3ca3b
commit 5c4db3acf4
59 changed files with 1270 additions and 809 deletions

View File

@ -124,7 +124,7 @@ void ArduinoOTAClass::begin() {
_udp_ota = new UdpContext;
_udp_ota->ref();
if(!_udp_ota->listen(*IP_ADDR_ANY, _port))
if(!_udp_ota->listen(IP_ADDR_ANY, _port))
return;
_udp_ota->onRx(std::bind(&ArduinoOTAClass::_onRx, this));
MDNS.begin(_hostname.c_str());
@ -172,7 +172,7 @@ String ArduinoOTAClass::readStringUntil(char end){
void ArduinoOTAClass::_onRx(){
if(!_udp_ota->next()) return;
ip_addr_t ota_ip;
IPAddress ota_ip;
if (_state == OTA_IDLE) {
int cmd = parseInt();
@ -189,7 +189,7 @@ void ArduinoOTAClass::_onRx(){
if(_md5.length() != 32)
return;
ota_ip.addr = (uint32_t)_ota_ip;
ota_ip = _ota_ip;
if (_password.length()){
MD5Builder nonce_md5;
@ -201,7 +201,7 @@ void ArduinoOTAClass::_onRx(){
char auth_req[38];
sprintf(auth_req, "AUTH %s", _nonce.c_str());
_udp_ota->append((const char *)auth_req, strlen(auth_req));
_udp_ota->send(&ota_ip, _ota_udp_port);
_udp_ota->send(ota_ip, _ota_udp_port);
_state = OTA_WAITAUTH;
return;
} else {
@ -228,12 +228,12 @@ void ArduinoOTAClass::_onRx(){
_challengemd5.calculate();
String result = _challengemd5.toString();
ota_ip.addr = (uint32_t)_ota_ip;
ota_ip = _ota_ip;
if(result.equalsConstantTime(response)) {
_state = OTA_RUNUPDATE;
} else {
_udp_ota->append("Authentication Failed", 21);
_udp_ota->send(&ota_ip, _ota_udp_port);
_udp_ota->send(ota_ip, _ota_udp_port);
if (_error_callback) _error_callback(OTA_AUTH_ERROR);
_state = OTA_IDLE;
}
@ -243,8 +243,7 @@ void ArduinoOTAClass::_onRx(){
}
void ArduinoOTAClass::_runUpdate() {
ip_addr_t ota_ip;
ota_ip.addr = (uint32_t)_ota_ip;
IPAddress ota_ip = _ota_ip;
if (!Update.begin(_size, _cmd)) {
#ifdef OTA_DEBUG
@ -258,14 +257,14 @@ void ArduinoOTAClass::_runUpdate() {
Update.printError(ss);
_udp_ota->append("ERR: ", 5);
_udp_ota->append(ss.c_str(), ss.length());
_udp_ota->send(&ota_ip, _ota_udp_port);
_udp_ota->send(ota_ip, _ota_udp_port);
delay(100);
_udp_ota->listen(*IP_ADDR_ANY, _port);
_udp_ota->listen(IP_ADDR_ANY, _port);
_state = OTA_IDLE;
return;
}
_udp_ota->append("OK", 2);
_udp_ota->send(&ota_ip, _ota_udp_port);
_udp_ota->send(ota_ip, _ota_udp_port);
delay(100);
Update.setMD5(_md5.c_str());
@ -284,7 +283,7 @@ void ArduinoOTAClass::_runUpdate() {
#ifdef OTA_DEBUG
OTA_DEBUG.printf("Connect Failed\n");
#endif
_udp_ota->listen(*IP_ADDR_ANY, _port);
_udp_ota->listen(IP_ADDR_ANY, _port);
if (_error_callback) {
_error_callback(OTA_CONNECT_ERROR);
}
@ -302,7 +301,7 @@ void ArduinoOTAClass::_runUpdate() {
#ifdef OTA_DEBUG
OTA_DEBUG.printf("Receive Failed\n");
#endif
_udp_ota->listen(*IP_ADDR_ANY, _port);
_udp_ota->listen(IP_ADDR_ANY, _port);
if (_error_callback) {
_error_callback(OTA_RECEIVE_ERROR);
}
@ -337,7 +336,7 @@ void ArduinoOTAClass::_runUpdate() {
ESP.restart();
}
} else {
_udp_ota->listen(*IP_ADDR_ANY, _port);
_udp_ota->listen(IP_ADDR_ANY, _port);
if (_error_callback) {
_error_callback(OTA_END_ERROR);
}

View File

@ -65,7 +65,9 @@ extern "C" {
#define _conn_read8() _conn->read()
#define _conn_readS(b, l) _conn->read((b), (l));
static const IPAddress LLMNR_MULTICAST_ADDR(224, 0, 0, 252);
// llmnr ipv6 is FF02:0:0:0:0:0:1:3
// lwip-v2's igmp_joingroup only supports IPv4
#define LLMNR_MULTICAST_ADDR 224, 0, 0, 252
static const int LLMNR_MULTICAST_TTL = 1;
static const int LLMNR_PORT = 5355;
@ -109,21 +111,20 @@ bool LLMNRResponder::_restart() {
_conn = 0;
}
ip_addr_t multicast_addr;
multicast_addr.addr = (uint32_t)LLMNR_MULTICAST_ADDR;
IPAddress llmnr(LLMNR_MULTICAST_ADDR);
if (igmp_joingroup(IP_ADDR_ANY, &multicast_addr) != ERR_OK)
if (igmp_joingroup(IP4_ADDR_ANY4, llmnr) != ERR_OK)
return false;
_conn = new UdpContext;
_conn->ref();
if (!_conn->listen(*IP_ADDR_ANY, LLMNR_PORT))
if (!_conn->listen(IP_ADDR_ANY, LLMNR_PORT))
return false;
_conn->setMulticastTTL(LLMNR_MULTICAST_TTL);
_conn->onRx(std::bind(&LLMNRResponder::_process_packet, this));
_conn->connect(multicast_addr, LLMNR_PORT);
_conn->connect(llmnr, LLMNR_PORT);
return true;
}
@ -229,15 +230,16 @@ void LLMNRResponder::_process_packet() {
Serial.println("(no matching RRs)");
#endif
ip_addr_t remote_ip;
remote_ip.addr = _conn->getRemoteAddress();
IPAddress remote_ip = _conn->getRemoteAddress();
struct ip_info ip_info;
bool match_ap = false;
if (wifi_get_opmode() & SOFTAP_MODE) {
wifi_get_ip_info(SOFTAP_IF, &ip_info);
if (ip_info.ip.addr && ip_addr_netcmp(&remote_ip, &ip_info.ip, &ip_info.netmask))
match_ap = true;
IPAddress infoIp(ip_info.ip);
IPAddress infoMask(ip_info.netmask);
if (ip_info.ip.addr && ip_addr_netcmp((const ip_addr_t*)remote_ip, (const ip_addr_t*)infoIp, ip_2_ip4((const ip_addr_t*)infoMask)))
match_ap = true;
}
if (!match_ap)
wifi_get_ip_info(STATION_IF, &ip_info);
@ -277,7 +279,7 @@ void LLMNRResponder::_process_packet() {
_conn->append(reinterpret_cast<const char*>(rr), sizeof(rr));
}
_conn->setMulticastInterface(remote_ip);
_conn->send(&remote_ip, _conn->getRemotePort());
_conn->send(remote_ip, _conn->getRemotePort());
}
#if !defined(NO_GLOBAL_INSTANCES) && !defined(NO_GLOBAL_LLMNR)

12
libraries/ESP8266NetBIOS/ESP8266NetBIOS.cpp Executable file → Normal file
View File

@ -174,11 +174,7 @@ void ESP8266NetBIOS::end()
}
}
#if LWIP_VERSION_MAJOR == 1
void ESP8266NetBIOS::_recv(udp_pcb *upcb, pbuf *pb, ip_addr_t *addr, uint16_t port)
#else
void ESP8266NetBIOS::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t port)
#endif
void ESP8266NetBIOS::_recv(udp_pcb *upcb, pbuf *pb, CONST ip_addr_t *addr, uint16_t port)
{
(void)upcb;
(void)addr;
@ -269,11 +265,7 @@ void ESP8266NetBIOS::_recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint1
}
}
#if LWIP_VERSION_MAJOR == 1
void ESP8266NetBIOS::_s_recv(void *arg, udp_pcb *upcb, pbuf *p, struct ip_addr *addr, uint16_t port)
#else
void ESP8266NetBIOS::_s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port)
#endif
void ESP8266NetBIOS::_s_recv(void *arg, udp_pcb *upcb, pbuf *p, CONST ip_addr_t *addr, uint16_t port)
{
reinterpret_cast<ESP8266NetBIOS*>(arg)->_recv(upcb, p, addr, port);
}

10
libraries/ESP8266NetBIOS/ESP8266NetBIOS.h Executable file → Normal file
View File

@ -28,13 +28,9 @@ protected:
void _getnbname(char *nbname, char *name, uint8_t maxlen);
void _makenbname(char *name, char *nbname, uint8_t outlen);
#if LWIP_VERSION_MAJOR == 1
void _recv(udp_pcb *upcb, pbuf *pb, struct ip_addr *addr, uint16_t port);
static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, struct ip_addr *addr, uint16_t port);
#else
void _recv(udp_pcb *upcb, pbuf *pb, const ip_addr_t *addr, uint16_t port);
static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, const ip_addr_t *addr, uint16_t port);
#endif
void _recv(udp_pcb *upcb, pbuf *pb, CONST ip_addr_t *addr, uint16_t port);
static void _s_recv(void *arg, udp_pcb *upcb, pbuf *p, CONST ip_addr_t *addr, uint16_t port);
public:
ESP8266NetBIOS();
~ESP8266NetBIOS();

View File

@ -53,7 +53,10 @@ extern "C" {
#define SSDP_URI_SIZE 2
#define SSDP_BUFFER_SIZE 64
#define SSDP_MULTICAST_TTL 2
static const IPAddress SSDP_MULTICAST_ADDR(239, 255, 255, 250);
// ssdp ipv6 is FF05::C
// lwip-v2's igmp_joingroup only supports IPv4
#define SSDP_MULTICAST_ADDR 239, 255, 255, 250
static const char _ssdp_response_template[] PROGMEM =
"HTTP/1.1 200 OK\r\n"
@ -172,23 +175,22 @@ bool SSDPClass::begin() {
_server = new UdpContext;
_server->ref();
ip_addr_t ifaddr;
ifaddr.addr = WiFi.localIP();
ip_addr_t multicast_addr;
multicast_addr.addr = (uint32_t) SSDP_MULTICAST_ADDR;
if (igmp_joingroup(&ifaddr, &multicast_addr) != ERR_OK ) {
IPAddress local = WiFi.localIP();
IPAddress mcast(SSDP_MULTICAST_ADDR);
if (igmp_joingroup(local, mcast) != ERR_OK ) {
DEBUGV("SSDP failed to join igmp group");
return false;
}
if (!_server->listen(*IP_ADDR_ANY, SSDP_PORT)) {
if (!_server->listen(IP_ADDR_ANY, SSDP_PORT)) {
return false;
}
_server->setMulticastInterface(ifaddr);
_server->setMulticastInterface(local);
_server->setMulticastTTL(_ttl);
_server->onRx(std::bind(&SSDPClass::_update, this));
if (!_server->connect(multicast_addr, SSDP_PORT)) {
if (!_server->connect(mcast, SSDP_PORT)) {
return false;
}
@ -209,7 +211,7 @@ void SSDPClass::_send(ssdp_method_t method) {
valueBuffer,
SSDP_INTERVAL,
_modelName,
_modelNumber,
_modelNumber,
_uuid,
(method == NONE) ? "ST" : "NT",
_deviceType,
@ -218,28 +220,28 @@ void SSDPClass::_send(ssdp_method_t method) {
_server->append(buffer, len);
ip_addr_t remoteAddr;
IPAddress remoteAddr;
uint16_t remotePort;
if (method == NONE) {
remoteAddr.addr = _respondToAddr;
remoteAddr = _respondToAddr;
remotePort = _respondToPort;
#ifdef DEBUG_SSDP
DEBUG_SSDP.print("Sending Response to ");
#endif
} else {
remoteAddr.addr = SSDP_MULTICAST_ADDR;
remoteAddr = IPAddress(SSDP_MULTICAST_ADDR);
remotePort = SSDP_PORT;
#ifdef DEBUG_SSDP
DEBUG_SSDP.println("Sending Notify to ");
#endif
}
#ifdef DEBUG_SSDP
DEBUG_SSDP.print(IPAddress(remoteAddr.addr));
DEBUG_SSDP.print(IPAddress(remoteAddr));
DEBUG_SSDP.print(":");
DEBUG_SSDP.println(remotePort);
#endif
_server->send(&remoteAddr, remotePort);
_server->send(remoteAddr, remotePort);
}
void SSDPClass::schema(WiFiClient client) {

View File

@ -201,10 +201,19 @@ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPA
}
bool ret = true;
if ( !local_ip.isV4()
|| !subnet.isV4()
#if LWIP_IPV6
// uninitialized gateway is valid
|| gateway.isV6()
#endif
) {
return false;
}
struct ip_info info;
info.ip.addr = static_cast<uint32_t>(local_ip);
info.gw.addr = static_cast<uint32_t>(gateway);
info.netmask.addr = static_cast<uint32_t>(subnet);
info.ip.addr = local_ip.v4();
info.gw.addr = gateway.v4();
info.netmask.addr = subnet.v4();
if(!wifi_softap_dhcps_stop()) {
DEBUG_WIFI("[APConfig] wifi_softap_dhcps_stop failed!\n");
@ -218,11 +227,11 @@ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPA
struct dhcps_lease dhcp_lease;
IPAddress ip = local_ip;
ip[3] += 99;
dhcp_lease.start_ip.addr = static_cast<uint32_t>(ip);
dhcp_lease.start_ip.addr = ip.v4();
DEBUG_WIFI("[APConfig] DHCP IP start: %s\n", ip.toString().c_str());
ip[3] += 100;
dhcp_lease.end_ip.addr = static_cast<uint32_t>(ip);
dhcp_lease.end_ip.addr = ip.v4();
DEBUG_WIFI("[APConfig] DHCP IP end: %s\n", ip.toString().c_str());
if(!wifi_softap_set_dhcps_lease(&dhcp_lease)) {
@ -252,7 +261,7 @@ bool ESP8266WiFiAPClass::softAPConfig(IPAddress local_ip, IPAddress gateway, IPA
if(info.ip.addr == 0x00000000) {
DEBUG_WIFI("[APConfig] IP config Invalid?!\n");
ret = false;
} else if(local_ip != info.ip.addr) {
} else if(local_ip.v4() != info.ip.addr) {
ip = info.ip.addr;
DEBUG_WIFI("[APConfig] IP config not set correct?! new IP: %s\n", ip.toString().c_str());
ret = false;

View File

@ -510,11 +510,7 @@ bool ESP8266WiFiGenericClass::isSleepLevelMax () {
// ------------------------------------------------ Generic Network function ---------------------------------------------
// -----------------------------------------------------------------------------------------------------------------------
#if LWIP_VERSION_MAJOR == 1
void wifi_dns_found_callback(const char *name, ip_addr_t *ipaddr, void *callback_arg);
#else
void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg);
#endif
void wifi_dns_found_callback(const char *name, CONST ip_addr_t *ipaddr, void *callback_arg);
static bool _dns_lookup_pending = false;
@ -545,13 +541,13 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul
DEBUG_WIFI_GENERIC("[hostByName] request IP for: %s\n", aHostname);
err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult);
if(err == ERR_OK) {
aResult = addr.addr;
aResult = IPAddress(&addr);
} else if(err == ERR_INPROGRESS) {
_dns_lookup_pending = true;
delay(timeout_ms);
_dns_lookup_pending = false;
// will return here when dns_found_callback fires
if(aResult != 0) {
if(aResult.isSet()) {
err = ERR_OK;
}
}
@ -571,18 +567,14 @@ int ESP8266WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResul
* @param ipaddr
* @param callback_arg
*/
#if LWIP_VERSION_MAJOR == 1
void wifi_dns_found_callback(const char *name, ip_addr_t *ipaddr, void *callback_arg)
#else
void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
#endif
void wifi_dns_found_callback(const char *name, CONST ip_addr_t *ipaddr, void *callback_arg)
{
(void) name;
if (!_dns_lookup_pending) {
return;
}
if(ipaddr) {
(*reinterpret_cast<IPAddress*>(callback_arg)) = ipaddr->addr;
(*reinterpret_cast<IPAddress*>(callback_arg)) = IPAddress(ipaddr);
}
esp_schedule(); // resume the hostByName function
}

View File

@ -38,6 +38,9 @@ extern "C" {
#include "lwip/err.h"
#include "lwip/dns.h"
#include "lwip/init.h" // LWIP_VERSION_
#if LWIP_IPV6
#include "lwip/netif.h" // struct netif
#endif
}
#include "debug.h"
@ -117,7 +120,7 @@ wl_status_t ESP8266WiFiSTAClass::begin(const char* ssid, const char *passphrase,
struct station_config conf;
strcpy(reinterpret_cast<char*>(conf.ssid), ssid);
conf.threshold.authmode = AUTH_OPEN;
if(passphrase) {
@ -244,15 +247,20 @@ bool ESP8266WiFiSTAClass::config(IPAddress local_ip, IPAddress arg1, IPAddress a
dns1 = arg1;
}
// check whether all is IPv4 (or gateway not set)
if (!(local_ip.isV4() && subnet.isV4() && (!gateway.isSet() || gateway.isV4()))) {
return false;
}
//ip and gateway must be in the same subnet
if((local_ip & subnet) != (gateway & subnet)) {
if((local_ip.v4() & subnet.v4()) != (gateway.v4() & subnet.v4())) {
return false;
}
struct ip_info info;
info.ip.addr = static_cast<uint32_t>(local_ip);
info.gw.addr = static_cast<uint32_t>(gateway);
info.netmask.addr = static_cast<uint32_t>(subnet);
info.ip.addr = local_ip.v4();
info.gw.addr = gateway.v4();
info.netmask.addr = subnet.v4();
wifi_station_dhcpc_stop();
if(wifi_set_ip_info(STATION_IF, &info)) {
@ -260,18 +268,15 @@ bool ESP8266WiFiSTAClass::config(IPAddress local_ip, IPAddress arg1, IPAddress a
} else {
return false;
}
ip_addr_t d;
if(dns1 != (uint32_t)0x00000000) {
if(dns1.isSet()) {
// Set DNS1-Server
d.addr = static_cast<uint32_t>(dns1);
dns_setserver(0, &d);
dns_setserver(0, dns1);
}
if(dns2 != (uint32_t)0x00000000) {
if(dns2.isSet()) {
// Set DNS2-Server
d.addr = static_cast<uint32_t>(dns2);
dns_setserver(1, &d);
dns_setserver(1, dns2);
}
return true;
@ -392,7 +397,6 @@ IPAddress ESP8266WiFiSTAClass::localIP() {
return IPAddress(ip.ip.addr);
}
/**
* Get the station interface MAC address.
* @param mac pointer to uint8_t array with length WL_MAC_ADDR_LENGTH
@ -446,8 +450,7 @@ IPAddress ESP8266WiFiSTAClass::dnsIP(uint8_t dns_no) {
ip_addr_t dns_ip = dns_getserver(dns_no);
return IPAddress(dns_ip.addr);
#else
const ip_addr_t* dns_ip = dns_getserver(dns_no);
return IPAddress(dns_ip->addr);
return IPAddress(dns_getserver(dns_no));
#endif
}

View File

@ -137,22 +137,19 @@ int WiFiClient::connect(const String& host, uint16_t port)
return connect(host.c_str(), port);
}
int WiFiClient::connect(IPAddress ip, uint16_t port)
int WiFiClient::connect(CONST IPAddress& ip, uint16_t port)
{
ip_addr_t addr;
addr.addr = ip;
if (_client) {
stop();
_client->unref();
_client = nullptr;
}
#if LWIP_VERSION_MAJOR == 1
// if the default interface is down, tcp_connect exits early without
// ever calling tcp_err
// http://lists.gnu.org/archive/html/lwip-devel/2010-05/msg00001.html
#if LWIP_VERSION_MAJOR == 1
netif* interface = ip_route(&addr);
netif* interface = ip_route(ip);
if (!interface) {
DEBUGV("no route to host\r\n");
return 0;
@ -170,7 +167,7 @@ int WiFiClient::connect(IPAddress ip, uint16_t port)
_client = new ClientContext(pcb, nullptr, nullptr);
_client->ref();
_client->setTimeout(_timeout);
int res = _client->connect(&addr, port);
int res = _client->connect(ip, port);
if (res == 0) {
_client->unref();
_client = nullptr;

View File

@ -53,7 +53,7 @@ public:
WiFiClient& operator=(const WiFiClient&);
uint8_t status();
virtual int connect(IPAddress ip, uint16_t port);
virtual int connect(CONST IPAddress& ip, uint16_t port);
virtual int connect(const char *host, uint16_t port);
virtual int connect(const String& host, uint16_t port);
virtual size_t write(uint8_t);

View File

@ -95,7 +95,7 @@ WiFiClientSecure::WiFiClientSecure(ClientContext* client, bool usePMEM,
_ssl->connectServer(client, _timeout);
}
int WiFiClientSecure::connect(IPAddress ip, uint16_t port)
int WiFiClientSecure::connect(CONST IPAddress& ip, uint16_t port)
{
if (!WiFiClient::connect(ip, port)) {
return 0;

View File

@ -35,7 +35,7 @@ public:
WiFiClientSecure();
~WiFiClientSecure() override;
int connect(IPAddress ip, uint16_t port) override;
int connect(CONST IPAddress& ip, uint16_t port) override;
int connect(const String& host, uint16_t port) override;
int connect(const char* name, uint16_t port) override;

View File

@ -200,7 +200,7 @@ bool WiFiClientSecure::flush(unsigned int maxWaitMs) {
return WiFiClient::flush(maxWaitMs);
}
int WiFiClientSecure::connect(IPAddress ip, uint16_t port) {
int WiFiClientSecure::connect(CONST IPAddress& ip, uint16_t port) {
if (!WiFiClient::connect(ip, port)) {
return 0;
}

View File

@ -36,7 +36,7 @@ class WiFiClientSecure : public WiFiClient {
WiFiClientSecure();
~WiFiClientSecure() override;
int connect(IPAddress ip, uint16_t port) override;
int connect(CONST IPAddress& ip, uint16_t port) override;
int connect(const String& host, uint16_t port) override;
int connect(const char* name, uint16_t port) override;

View File

@ -37,7 +37,7 @@ extern "C" {
#include "lwip/inet.h"
#include <include/ClientContext.h>
WiFiServer::WiFiServer(IPAddress addr, uint16_t port)
WiFiServer::WiFiServer(const IPAddress& addr, uint16_t port)
: _port(port)
, _addr(addr)
, _pcb(nullptr)
@ -48,7 +48,7 @@ WiFiServer::WiFiServer(IPAddress addr, uint16_t port)
WiFiServer::WiFiServer(uint16_t port)
: _port(port)
, _addr((uint32_t) IPADDR_ANY)
, _addr(IP_ANY_TYPE)
, _pcb(nullptr)
, _unclaimed(nullptr)
, _discarded(nullptr)
@ -61,16 +61,16 @@ void WiFiServer::begin() {
void WiFiServer::begin(uint16_t port) {
close();
_port = port;
_port = port;
err_t err;
tcp_pcb* pcb = tcp_new();
if (!pcb)
return;
ip_addr_t local_addr;
local_addr.addr = (uint32_t) _addr;
pcb->so_options |= SOF_REUSEADDR;
err = tcp_bind(pcb, &local_addr, _port);
// (IPAddress _addr) operator-converted to (const ip_addr_t*)
err = tcp_bind(pcb, _addr, _port);
if (err != ERR_OK) {
tcp_close(pcb);

View File

@ -46,7 +46,7 @@ protected:
enum { _ndDefault, _ndFalse, _ndTrue } _noDelay = _ndDefault;
public:
WiFiServer(IPAddress addr, uint16_t port);
WiFiServer(const IPAddress& addr, uint16_t port);
WiFiServer(uint16_t port);
virtual ~WiFiServer() {}
WiFiClient available(uint8_t* status = NULL);

View File

@ -40,7 +40,6 @@ extern "C"
#include "lwip/mem.h"
#include <include/UdpContext.h>
template<>
WiFiUDP* SList<WiFiUDP>::_s_first = 0;
@ -83,9 +82,7 @@ uint8_t WiFiUDP::begin(uint16_t port)
_ctx = new UdpContext;
_ctx->ref();
ip_addr_t addr;
addr.addr = INADDR_ANY;
return (_ctx->listen(addr, port)) ? 1 : 0;
return (_ctx->listen(IPAddress(), port)) ? 1 : 0;
}
uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port)
@ -95,20 +92,14 @@ uint8_t WiFiUDP::beginMulticast(IPAddress interfaceAddr, IPAddress multicast, ui
_ctx = 0;
}
ip_addr_t ifaddr;
ifaddr.addr = (uint32_t) interfaceAddr;
ip_addr_t multicast_addr;
multicast_addr.addr = (uint32_t) multicast;
if (igmp_joingroup(&ifaddr, &multicast_addr)!= ERR_OK) {
if (igmp_joingroup(interfaceAddr, multicast)!= ERR_OK) {
return 0;
}
_ctx = new UdpContext;
_ctx->ref();
ip_addr_t addr;
addr.addr = INADDR_ANY;
if (!_ctx->listen(addr, port)) {
ip_addr_t addr = IPADDR4_INIT(INADDR_ANY);
if (!_ctx->listen(&addr, port)) {
return 0;
}
@ -155,32 +146,24 @@ int WiFiUDP::beginPacket(const char *host, uint16_t port)
int WiFiUDP::beginPacket(IPAddress ip, uint16_t port)
{
ip_addr_t addr;
addr.addr = ip;
if (!_ctx) {
_ctx = new UdpContext;
_ctx->ref();
}
return (_ctx->connect(addr, port)) ? 1 : 0;
return (_ctx->connect(ip, port)) ? 1 : 0;
}
int WiFiUDP::beginPacketMulticast(IPAddress multicastAddress, uint16_t port,
IPAddress interfaceAddress, int ttl)
{
ip_addr_t mcastAddr;
mcastAddr.addr = multicastAddress;
ip_addr_t ifaceAddr;
ifaceAddr.addr = interfaceAddress;
if (!_ctx) {
_ctx = new UdpContext;
_ctx->ref();
}
if (!_ctx->connect(mcastAddr, port)) {
if (!_ctx->connect(multicastAddress, port)) {
return 0;
}
_ctx->setMulticastInterface(ifaceAddr);
_ctx->setMulticastInterface(interfaceAddress);
_ctx->setMulticastTTL(ttl);
return 1;
}
@ -248,15 +231,15 @@ void WiFiUDP::flush()
endPacket();
}
IPAddress WiFiUDP::remoteIP()
IPAddress WiFiUDP::remoteIP() const
{
if (!_ctx)
return IPAddress(0U);
return IPNoAddress;
return IPAddress(_ctx->getRemoteAddress());
return _ctx->getRemoteAddress();
}
uint16_t WiFiUDP::remotePort()
uint16_t WiFiUDP::remotePort() const
{
if (!_ctx)
return 0;
@ -264,18 +247,15 @@ uint16_t WiFiUDP::remotePort()
return _ctx->getRemotePort();
}
IPAddress WiFiUDP::destinationIP()
IPAddress WiFiUDP::destinationIP() const
{
IPAddress addr;
if (!_ctx)
return addr;
return IPNoAddress;
addr = _ctx->getDestAddress();
return addr;
return _ctx->getDestAddress();
}
uint16_t WiFiUDP::localPort()
uint16_t WiFiUDP::localPort() const
{
if (!_ctx)
return 0;

View File

@ -47,7 +47,7 @@ public:
// Finish with the UDP connetion
virtual void stop();
// join a multicast group and listen on the given port
uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port);
uint8_t beginMulticast(IPAddress interfaceAddr, IPAddress multicast, uint16_t port);
// Sending UDP packets
@ -63,9 +63,9 @@ public:
// use WiFi.localIP() or WiFi.softAPIP() depending on the interface you need
// ttl - multicast packet TTL (default is 1)
// Returns 1 if successful, 0 if there was a problem with the supplied IP address or port
virtual int beginPacketMulticast(IPAddress multicastAddress,
virtual int beginPacketMulticast(IPAddress multicastAddress,
uint16_t port,
IPAddress interfaceAddress,
IPAddress interfaceAddress,
int ttl = 1);
// Finish off this packet and send it
// Returns 1 if the packet was sent successfully, 0 if there was an error
@ -95,14 +95,14 @@ public:
virtual void flush(); // Finish reading the current packet
// Return the IP address of the host who sent the current incoming packet
virtual IPAddress remoteIP();
virtual IPAddress remoteIP() const;
// Return the port of the host who sent the current incoming packet
virtual uint16_t remotePort();
virtual uint16_t remotePort() const;
// Return the destination address for incoming packets,
// useful to distinguish multicast and ordinary packets
IPAddress destinationIP();
IPAddress destinationIP() const;
// Return the local port for outgoing packets
uint16_t localPort();
uint16_t localPort() const;
static void stopAll();
static void stopAllExcept(WiFiUDP * exC);

View File

@ -122,7 +122,7 @@ public:
}
}
int connect(ip_addr_t* addr, uint16_t port)
int connect(CONST ip_addr_t* addr, uint16_t port)
{
err_t err = tcp_connect(_pcb, addr, port, &ClientContext::_s_connected);
if (err != ERR_OK) {
@ -145,7 +145,7 @@ public:
return 1;
}
size_t availableForWrite()
size_t availableForWrite() const
{
return _pcb? tcp_sndbuf(_pcb): 0;
}
@ -180,13 +180,13 @@ public:
return _timeout_ms;
}
uint32_t getRemoteAddress() const
const ip_addr_t* getRemoteAddress() const
{
if(!_pcb) {
return 0;
}
return _pcb->remote_ip.addr;
return &_pcb->remote_ip;
}
uint16_t getRemotePort() const
@ -198,13 +198,13 @@ public:
return _pcb->remote_port;
}
uint32_t getLocalAddress() const
const ip_addr_t* getLocalAddress() const
{
if(!_pcb) {
return 0;
}
return _pcb->local_ip.addr;
return &_pcb->local_ip;
}
uint16_t getLocalPort() const

View File

@ -30,9 +30,7 @@ void esp_schedule();
#include <assert.h>
}
#define GET_IP_HDR(pb) reinterpret_cast<ip_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN - IP_HLEN);
#define GET_UDP_HDR(pb) reinterpret_cast<udp_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN);
#define GET_UDP_HDR(pb) (reinterpret_cast<udp_hdr*>(((uint8_t*)((pb)->payload)) - UDP_HLEN))
class UdpContext
{
@ -90,17 +88,17 @@ public:
}
}
bool connect(ip_addr_t addr, uint16_t port)
bool connect(const ip_addr_t* addr, uint16_t port)
{
ip_addr_copy(_pcb->remote_ip, addr);
_pcb->remote_ip = *addr;
_pcb->remote_port = port;
return true;
}
bool listen(ip_addr_t addr, uint16_t port)
bool listen(CONST ip_addr_t* addr, uint16_t port)
{
udp_recv(_pcb, &_s_recv, (void *) this);
err_t err = udp_bind(_pcb, &addr, port);
err_t err = udp_bind(_pcb, addr, port);
return err == ERR_OK;
}
@ -110,14 +108,14 @@ public:
}
#if LWIP_VERSION_MAJOR == 1
void setMulticastInterface(ip_addr_t addr)
void setMulticastInterface(const ip_addr_t addr)
{
udp_set_multicast_netif_addr(_pcb, addr);
}
#else
void setMulticastInterface(const ip_addr_t& addr)
void setMulticastInterface(const ip_addr_t* addr)
{
udp_set_multicast_netif_addr(_pcb, &addr);
udp_set_multicast_netif_addr(_pcb, ip_2_ip4(addr));
}
#endif
@ -159,16 +157,12 @@ public:
return (pos <= _rx_buf->len);
}
uint32_t getRemoteAddress()
CONST IPAddress& getRemoteAddress() CONST
{
if (!_rx_buf)
return 0;
ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
return iphdr->src.addr;
return _src_addr;
}
uint16_t getRemotePort()
uint16_t getRemotePort() const
{
if (!_rx_buf)
return 0;
@ -177,20 +171,15 @@ public:
return lwip_ntohs(udphdr->src);
}
uint32_t getDestAddress()
const IPAddress& getDestAddress() const
{
if (!_rx_buf)
return 0;
ip_hdr* iphdr = GET_IP_HDR(_rx_buf);
return iphdr->dest.addr;
return _dst_addr;
}
uint16_t getLocalPort()
uint16_t getLocalPort() const
{
if (!_pcb)
return 0;
return _pcb->local_port;
}
@ -242,7 +231,7 @@ public:
return size;
}
int peek()
int peek() const
{
if (!_rx_buf || _rx_buf_offset == _rx_buf->len)
return -1;
@ -259,7 +248,6 @@ public:
_consume(_rx_buf->len - _rx_buf_offset);
}
size_t append(const char* data, size_t size)
{
if (!_tx_buf_head || _tx_buf_head->tot_len < _tx_buf_offset + size)
@ -292,7 +280,7 @@ public:
return size;
}
bool send(ip_addr_t* addr = 0, uint16_t port = 0)
bool send(CONST ip_addr_t* addr = 0, uint16_t port = 0)
{
size_t data_size = _tx_buf_offset;
pbuf* tx_copy = pbuf_alloc(PBUF_TRANSPORT, data_size, PBUF_RAM);
@ -403,21 +391,33 @@ private:
_rx_buf = pb;
_rx_buf_offset = 0;
}
// --> Arduino's UDP is a stream but UDP is not <--
// When IPv6 is enabled, we store addresses from here
// because lwIP's macro are valid only in this callback
// (there's no easy way to safely guess whether packet
// is from v4 or v6 when we have only access to payload)
// Because of this stream-ed way this is inacurate when
// user does not swallow data quickly enough (the former
// IPv4-only way suffers from the exact same issue.
#if LWIP_VERSION_MAJOR == 1
_src_addr = current_iphdr_src;
_dst_addr = current_iphdr_dest;
#else
_src_addr = ip_data.current_iphdr_src;
_dst_addr = ip_data.current_iphdr_dest;
#endif
if (_on_rx) {
_on_rx();
}
}
#if LWIP_VERSION_MAJOR == 1
static void _s_recv(void *arg,
udp_pcb *upcb, pbuf *p,
ip_addr_t *addr, u16_t port)
#else
static void _s_recv(void *arg,
udp_pcb *upcb, pbuf *p,
const ip_addr_t *addr, u16_t port)
#endif
CONST ip_addr_t *addr, u16_t port)
{
reinterpret_cast<UdpContext*>(arg)->_recv(upcb, p, addr, port);
}
@ -435,6 +435,7 @@ private:
#ifdef LWIP_MAYBE_XCC
uint16_t _mcast_ttl;
#endif
IPAddress _src_addr, _dst_addr;
};

View File

@ -192,22 +192,22 @@ bool MDNSResponder::_listen() {
#ifdef DEBUG_ESP_MDNS_RX
DEBUG_ESP_PORT.println("MDNS listening");
#endif
ip_addr_t multicast_addr;
multicast_addr.addr = (uint32_t) MDNS_MULTICAST_ADDR;
if (igmp_joingroup(IP_ADDR_ANY, &multicast_addr)!= ERR_OK) {
IPAddress mdns(MDNS_MULTICAST_ADDR);
if (igmp_joingroup(IP4_ADDR_ANY4, mdns)!= ERR_OK) {
return false;
}
_conn = new UdpContext;
_conn->ref();
if (!_conn->listen(*IP_ADDR_ANY, MDNS_PORT)) {
if (!_conn->listen(IP_ADDR_ANY, MDNS_PORT)) {
return false;
}
_conn->setMulticastTTL(MDNS_MULTICAST_TTL);
_conn->onRx(std::bind(&MDNSResponder::update, this));
_conn->connect(multicast_addr, MDNS_PORT);
_conn->connect(mdns, MDNS_PORT);
}
return true;
}
@ -332,13 +332,11 @@ int MDNSResponder::queryService(char *service, char *proto) {
_waitingForAnswers = true;
for (int itfn = 0; itfn < 2; itfn++) {
struct ip_info ip_info;
ip_addr_t ifaddr;
wifi_get_ip_info((!itfn) ? SOFTAP_IF : STATION_IF, &ip_info);
if (!ip_info.ip.addr)
continue;
ifaddr.addr = ip_info.ip.addr;
_conn->setMulticastInterface(ifaddr);
_conn->setMulticastInterface(IPAddress(ip_info.ip.addr));
// Write the header
_conn->flush();
@ -464,10 +462,11 @@ IPAddress MDNSResponder::_getRequestMulticastInterface(){
struct ip_info ip_info;
bool match_ap = false;
if (wifi_get_opmode() & SOFTAP_MODE) {
struct ip_info remote_ip_info;
remote_ip_info.ip.addr = _conn->getRemoteAddress();
const IPAddress& remote_ip = _conn->getRemoteAddress();
wifi_get_ip_info(SOFTAP_IF, &ip_info);
if (ip_info.ip.addr && ip_addr_netcmp(&remote_ip_info.ip, &ip_info.ip, &ip_info.netmask))
IPAddress infoIp(ip_info.ip);
IPAddress infoMask(ip_info.netmask);
if (ip_info.ip.addr && ip_addr_netcmp((const ip_addr_t*)remote_ip, (const ip_addr_t*)infoIp, ip_2_ip4((const ip_addr_t*)infoMask)))
match_ap = true;
}
if (!match_ap)
@ -1056,9 +1055,7 @@ void MDNSResponder::_replyToTypeEnumRequest(IPAddress multicastInterface) {
_conn->append(reinterpret_cast<const char*>(localName), localNameLen); // "local"
_conn->append(reinterpret_cast<const char*>(&terminator), 1); // terminator
ip_addr_t ifaddr;
ifaddr.addr = multicastInterface;
_conn->setMulticastInterface(ifaddr);
_conn->setMulticastInterface(multicastInterface);
_conn->send();
}
}
@ -1263,9 +1260,7 @@ void MDNSResponder::_replyToInstanceRequest(uint8_t questionMask, uint8_t respon
}
}
ip_addr_t ifaddr;
ifaddr.addr = multicastInterface;
_conn->setMulticastInterface(ifaddr);
_conn->setMulticastInterface(multicastInterface);
_conn->send();
}

View File

@ -127,7 +127,7 @@ int DNSClient::getHostByName(const char* aHostname, IPAddress& aResult)
}
// Check we've got a valid DNS server to use
if (iDNSServer == INADDR_NONE)
if (iDNSServer == IPNoAddress)
{
return INVALID_SERVER;
}

View File

@ -35,7 +35,7 @@ int EthernetClient::connect(const char* host, uint16_t port) {
}
}
int EthernetClient::connect(IPAddress ip, uint16_t port) {
int EthernetClient::connect(CONST IPAddress& ip, uint16_t port) {
if (_sock != MAX_SOCK_NUM)
return 0;

View File

@ -12,7 +12,7 @@ public:
EthernetClient(uint8_t sock);
uint8_t status();
virtual int connect(IPAddress ip, uint16_t port);
virtual int connect(CONST IPAddress& ip, uint16_t port);
virtual int connect(const char *host, uint16_t port);
virtual size_t write(uint8_t);
virtual size_t write(const uint8_t *buf, size_t size);

View File

@ -94,9 +94,9 @@ public:
virtual void flush(); // Finish reading the current packet
// Return the IP address of the host who sent the current incoming packet
virtual IPAddress remoteIP() { return _remoteIP; };
virtual IPAddress remoteIP() const { return _remoteIP; };
// Return the port of the host who sent the current incoming packet
virtual uint16_t remotePort() { return _remotePort; };
virtual uint16_t remotePort() const { return _remotePort; };
};
#endif

View File

@ -75,7 +75,7 @@ uint8_t listen(SOCKET s)
*
* @return 1 for success else 0.
*/
uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port)
uint8_t connect(SOCKET s, const uint8_t * addr, uint16_t port)
{
if
(
@ -420,7 +420,7 @@ uint16_t bufferData(SOCKET s, uint16_t offset, const uint8_t* buf, uint16_t len)
return ret;
}
int startUDP(SOCKET s, uint8_t* addr, uint16_t port)
int startUDP(SOCKET s, const uint8_t* addr, uint16_t port)
{
if
(

View File

@ -6,7 +6,7 @@
extern uint8_t socket(SOCKET s, uint8_t protocol, uint16_t port, uint8_t flag); // Opens a socket(TCP or UDP or IP_RAW mode)
extern uint8_t socketStatus(SOCKET s);
extern void close(SOCKET s); // Close socket
extern uint8_t connect(SOCKET s, uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection)
extern uint8_t connect(SOCKET s, const uint8_t * addr, uint16_t port); // Establish TCP connection (Active connection)
extern void disconnect(SOCKET s); // disconnect the connection
extern uint8_t listen(SOCKET s); // Establish TCP connection (Passive connection)
extern uint16_t send(SOCKET s, const uint8_t * buf, uint16_t len); // Send data (TCP)
@ -26,7 +26,7 @@ extern uint16_t igmpsend(SOCKET s, const uint8_t * buf, uint16_t len);
or more calls to bufferData and then finally sent with sendUDP.
@return 1 if the datagram was successfully set up, or 0 if there was an error
*/
extern int startUDP(SOCKET s, uint8_t* addr, uint16_t port);
extern int startUDP(SOCKET s, const uint8_t* addr, uint16_t port);
/*
@brief This function copies up to len bytes of data from buf into a UDP datagram to be
sent later by sendUDP. Allows datagrams to be built up from a series of bufferData calls.

View File

@ -1,14 +1,24 @@
#ifndef UTIL_H
#define UTIL_H
#ifndef htons
#define htons(x) ( ((x)<< 8 & 0xFF00) | \
((x)>> 8 & 0x00FF) )
#define ntohs(x) htons(x)
#endif
#ifndef ntohs
#define ntohs(x) htons(x)
#endif
#ifndef htonl
#define htonl(x) ( ((x)<<24 & 0xFF000000UL) | \
((x)<< 8 & 0x00FF0000UL) | \
((x)>> 8 & 0x0000FF00UL) | \
((x)>>24 & 0x000000FFUL) )
#endif
#ifndef ntohl
#define ntohl(x) htonl(x)
#endif
#endif

View File

@ -260,7 +260,7 @@ private:
static inline uint8_t readSn(SOCKET _s, uint16_t _addr);
static inline uint8_t writeSn(SOCKET _s, uint16_t _addr, uint8_t _data);
static inline uint16_t readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t len);
static inline uint16_t writeSn(SOCKET _s, uint16_t _addr, const uint8_t *_buf, uint16_t len);
static const uint16_t CH_BASE = 0x0400;
static const uint16_t CH_SIZE = 0x0100;
@ -286,7 +286,7 @@ private:
return res; \
}
#define __SOCKET_REGISTER_N(name, address, size) \
static uint16_t write##name(SOCKET _s, uint8_t *_buff) { \
static uint16_t write##name(SOCKET _s, const uint8_t *_buff) { \
return writeSn(_s, address, _buff, size); \
} \
static uint16_t read##name(SOCKET _s, uint8_t *_buff) { \
@ -371,7 +371,7 @@ uint16_t W5100Class::readSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _
return read(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
}
uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, uint8_t *_buf, uint16_t _len) {
uint16_t W5100Class::writeSn(SOCKET _s, uint16_t _addr, const uint8_t *_buf, uint16_t _len) {
return write(CH_BASE + _s * CH_SIZE + _addr, _buf, _len);
}

View File

@ -0,0 +1,183 @@
/*
arduino IPv6 example
released to public domain
output is like:
SDK:2.2.1(cfd48f3)/Core:2.4.2-141-g4f97603/lwIP:IPv6+STABLE-2_1_0_RC1/glue:arduino-2.4.2-30-ga53619c/BearSSL:6d1cefc
dns0=10.43.1.254
Try me at these addresses:
(with 'telnet <addr> or 'nc -u <addr> 23')
IF='st'(0) IPv6=0 local=0 hostname='ipv6test' addr= 10.43.1.244 / mask:255.255.255.0 / gw:10.43.1.254
IF='st'(0) IPv6=1 local=1 hostname='ipv6test' addr= fe80::1afe:34ff:fed1:cec7
IF='st'(0) IPV6=1 local=0 hostname='ipv6test' addr= 2xxx:xxxx:xxxx:xxxx:1afe:34ff:fed1:cec7
resolving www.google.com: 216.58.205.100
resolving ipv6.google.com: 2a00:1450:4002:808::200e
*/
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <PolledTimeout.h>
#include <lwip/dns.h>
#ifndef STASSID
#define STASSID "your-ssid"
#define STAPSK "your-password"
#endif
#define FQDN F("www.google.com") // with both IPv4 & IPv6 addresses
#define FQDN6 F("ipv6.google.com") // does not resolve in IPv4
#define STATUSDELAY_MS 10000
#define TCP_PORT 23
#define UDP_PORT 23
WiFiServer statusServer(TCP_PORT);
WiFiUDP udp;
esp8266::polledTimeout::periodic statusPeriod(STATUSDELAY_MS);
void fqdn(Print& out, const String& fqdn) {
out.print(F("resolving "));
out.print(fqdn);
out.print(F(": "));
IPAddress result;
if (WiFi.hostByName(fqdn.c_str(), result)) {
result.printTo(out);
out.println();
} else {
out.println(F("timeout or not found"));
}
}
void status(Print& out) {
out.println(F("------------------------------"));
out.println(ESP.getFullVersion());
dns_setserver(DNS_MAX_SERVERS - 1, IPAddress(8, 8, 8, 8));
for (int i = 0; i < DNS_MAX_SERVERS; i++) {
IPAddress dns = WiFi.dnsIP(i);
if (dns.isSet()) {
out.printf("dns%d: %s\n", i, dns.toString().c_str());
}
}
out.println(F("Try me at these addresses:"));
out.println(F("(with 'telnet <addr> or 'nc -u <addr> 23')"));
for (auto a : addrList) {
out.printf("IF='%s' IPv6=%d local=%d hostname='%s' addr= %s",
a->iface().c_str(),
!a->addr().isV4(),
a->addr().isLocal(),
a->hostname(),
a->addr().toString().c_str());
if (a->isLegacy()) {
out.printf(" / mask:%s / gw:%s",
a->netmask().toString().c_str(),
a->gw().toString().c_str());
}
out.println();
}
// lwIP's dns client will ask for IPv4 first (by default)
// an example is provided with a fqdn which does not resolve with IPv4
fqdn(out, FQDN);
fqdn(out, FQDN6);
out.println(F("------------------------------"));
}
void setup() {
WiFi.hostname("ipv6test");
Serial.begin(115200);
Serial.println();
Serial.println(ESP.getFullVersion());
WiFi.mode(WIFI_STA);
WiFi.begin(STASSID, STAPSK);
status(Serial);
#if 0
// legacy loop (still valid with IPv4 only)
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(500);
}
#else
// Use this loop instead to wait for an IPv6 routable address
// addr->isLocal() (meaning "not routable on internet") is true with:
// - IPV4 DHCP autoconfigured address 169.254.x.x
// (false for any other including 192.168./16 and 10./24 since NAT may be in the equation)
// - IPV6 link-local addresses (fe80::/64)
for (bool configured = false; !configured;) {
for (auto addr : addrList)
if ((configured = !addr->isLocal()
// && addr->isV6() // uncomment when IPv6 is mandatory
// && addr->ifnumber() == STATION_IF
)) {
break;
}
Serial.print('.');
delay(500);
}
#endif
Serial.println(F("connected: "));
statusServer.begin();
udp.begin(UDP_PORT);
Serial.print(F("TCP server on port "));
Serial.print(TCP_PORT);
Serial.print(F(" - UDP server on port "));
Serial.println(UDP_PORT);
statusPeriod.reset();
}
unsigned long statusTimeMs = 0;
void loop() {
if (statusServer.hasClient()) {
WiFiClient cli = statusServer.available();
status(cli);
}
// if there's data available, read a packet
int packetSize = udp.parsePacket();
if (packetSize) {
Serial.print(F("udp received "));
Serial.print(packetSize);
Serial.print(F(" bytes from "));
udp.remoteIP().printTo(Serial);
Serial.print(F(" :"));
Serial.println(udp.remotePort());
int c;
while ((c = udp.read()) >= 0) {
Serial.write(c);
}
// send a reply, to the IP address and port that sent us the packet we received
udp.beginPacket(udp.remoteIP(), udp.remotePort());
status(udp);
udp.endPacket();
}
if (statusPeriod) {
status(Serial);
}
}