* Add support for the WiFi chip on the Pico W board. * USB interrupt now no longer hard coded (conflicted with the WiFi IRQ). * Add in Pico W board to makeboards.py * Add in GPIO and variant support * Initialize WiFi in the Variant * Use manual LWIP, fix size accounting * Remove the SDK WiFi overrides * Pulling in work done in the ESP8266 core. * Make IPAddress support IPv6 * Build LWIP with IPv4 and IPv6 support * Use proper MAC * Avoid cyw_warn crash. Make macro to a comment while building * Add WiFiServer * Add WiFiUdp * Move LWIP-specific support files to LWIP_Ethernet * Add WiFi::ping (ICMP ping) * Move ICMP echo (ping) to LWIPIntfDev * Move hostByName to LwipIntfDev * Add AP mode with simple DHCP server * Add some examples and basic ESP8266 compat hacks * Update Adafruit TinyUSB to fix crash * Set DHCP hostname * Make Wifi.begin() return CONNECTED with link + IP * Return connected() on WiFi::begin * Fix spurious TCP retransmission * Protect LWIP from reentrancy The Pico SDK calls "sys_check_timeouts() from inside a periodic interrupt. This appears unsafe, as the interrupt could happen while already in the (non-reentrant) LWIP code. Block the interrupt from calling sys_check_timeouts by using a global flag manually set via an RAII recursive lock. Add interrupt protection macros around critical sections inside LWIP via the standard defines. These two changes should make LWIP significantly more stable and long running. * Support disconnecting and reconnecting WiFi * Add WiFiServer simple example * Update documentation Fixes #666 Fixed #665
247 lines
5.8 KiB
C++
247 lines
5.8 KiB
C++
/*
|
|
IPAddress.cpp - Base class that provides IPAddress
|
|
Copyright (c) 2011 Adrian McEwen. All right reserved.
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2.1 of the License, or (at your option) any later version.
|
|
|
|
This library is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Lesser General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Lesser General Public
|
|
License along with this library; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*/
|
|
|
|
#include <Arduino.h>
|
|
#include <IPAddress.h>
|
|
#include <Print.h>
|
|
|
|
IPAddress::IPAddress(const IPAddress& from)
|
|
{
|
|
ip_addr_copy(_ip, from._ip);
|
|
}
|
|
|
|
IPAddress::IPAddress() {
|
|
_ip = *IP_ANY_TYPE; // lwIP's v4-or-v6 generic address
|
|
}
|
|
|
|
bool IPAddress::isSet () const {
|
|
return !ip_addr_isany(&_ip) && ((*this) != IPADDR_NONE);
|
|
}
|
|
|
|
IPAddress::IPAddress(uint8_t first_octet, uint8_t second_octet, uint8_t third_octet, uint8_t fourth_octet) {
|
|
setV4();
|
|
(*this)[0] = first_octet;
|
|
(*this)[1] = second_octet;
|
|
(*this)[2] = third_octet;
|
|
(*this)[3] = fourth_octet;
|
|
}
|
|
|
|
void IPAddress::ctor32(uint32_t address) {
|
|
setV4();
|
|
v4() = address;
|
|
}
|
|
|
|
IPAddress::IPAddress(const uint8_t *address) {
|
|
setV4();
|
|
(*this)[0] = address[0];
|
|
(*this)[1] = address[1];
|
|
(*this)[2] = address[2];
|
|
(*this)[3] = address[3];
|
|
}
|
|
|
|
bool IPAddress::fromString(const char *address) {
|
|
if (!fromString4(address)) {
|
|
#if LWIP_IPV6
|
|
return fromString6(address);
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool IPAddress::fromString4(const char *address) {
|
|
// TODO: (IPv4) add support for "a", "a.b", "a.b.c" formats
|
|
|
|
uint16_t acc = 0; // Accumulator
|
|
uint8_t dots = 0;
|
|
|
|
while (*address)
|
|
{
|
|
char c = *address++;
|
|
if (c >= '0' && c <= '9')
|
|
{
|
|
acc = acc * 10 + (c - '0');
|
|
if (acc > 255) {
|
|
// Value out of [0..255] range
|
|
return false;
|
|
}
|
|
}
|
|
else if (c == '.')
|
|
{
|
|
if (dots == 3) {
|
|
// Too much dots (there must be 3 dots)
|
|
return false;
|
|
}
|
|
(*this)[dots++] = acc;
|
|
acc = 0;
|
|
}
|
|
else
|
|
{
|
|
// Invalid char
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (dots != 3) {
|
|
// Too few dots (there must be 3 dots)
|
|
return false;
|
|
}
|
|
(*this)[3] = acc;
|
|
|
|
setV4();
|
|
return true;
|
|
}
|
|
|
|
IPAddress& IPAddress::operator=(const uint8_t *address) {
|
|
setV4();
|
|
v4() = *reinterpret_cast<const uint32_t*>(address);
|
|
return *this;
|
|
}
|
|
|
|
IPAddress& IPAddress::operator=(uint32_t address) {
|
|
setV4();
|
|
v4() = address;
|
|
return *this;
|
|
}
|
|
|
|
bool IPAddress::operator==(const uint8_t* addr) const {
|
|
return isV4() && v4() == *reinterpret_cast<const uint32_t*>(addr);
|
|
}
|
|
|
|
size_t IPAddress::printTo(Print& p) const {
|
|
String s = toString();
|
|
return p.print(s);
|
|
}
|
|
|
|
String IPAddress::toString() const
|
|
{
|
|
String s;
|
|
|
|
if (!isSet())
|
|
return "(IP unset)";
|
|
|
|
#if LWIP_IPV6
|
|
if (isV6()) {
|
|
int count0 = 0;
|
|
for (int i = 0; i < 8; i++) {
|
|
uint16_t bit = PP_NTOHS(raw6()[i]);
|
|
if (bit || count0 < 0) {
|
|
char buff[64];
|
|
snprintf(buff, 64, "%x", bit);
|
|
buff[63] = 0;
|
|
s += buff;
|
|
if (count0 > 0)
|
|
// no more hiding 0
|
|
count0 = -8;
|
|
} else
|
|
count0++;
|
|
if ((i != 7 && count0 < 2) || count0 == 7)
|
|
s += ':';
|
|
}
|
|
return s;
|
|
}
|
|
#endif
|
|
|
|
for(int i = 0; i < 4; i++) {
|
|
char buff[16];
|
|
snprintf(buff, 16, "%d", (*this)[i]);
|
|
buff[15] = 0;
|
|
s += buff;
|
|
if (i != 3)
|
|
s += '.';
|
|
}
|
|
return s;
|
|
|
|
}
|
|
|
|
bool IPAddress::isValid(const String& arg) {
|
|
return IPAddress().fromString(arg);
|
|
}
|
|
|
|
bool IPAddress::isValid(const char* arg) {
|
|
return IPAddress().fromString(arg);
|
|
}
|
|
|
|
const IPAddress INADDR_ANY; // generic "0.0.0.0" for IPv4 & IPv6
|
|
const IPAddress INADDR_NONE(255,255,255,255);
|
|
|
|
void IPAddress::clear() {
|
|
(*this) = INADDR_ANY;
|
|
}
|
|
|
|
/**************************************/
|
|
|
|
#if LWIP_IPV6
|
|
|
|
bool IPAddress::fromString6(const char *address) {
|
|
// TODO: test test test
|
|
|
|
uint32_t acc = 0; // Accumulator
|
|
int dots = 0, doubledots = -1;
|
|
|
|
while (*address)
|
|
{
|
|
char c = tolower(*address++);
|
|
if (isalnum(c)) {
|
|
if (c >= 'a')
|
|
c -= 'a' - '0' - 10;
|
|
acc = acc * 16 + (c - '0');
|
|
if (acc > 0xffff)
|
|
// Value out of range
|
|
return false;
|
|
}
|
|
else if (c == ':') {
|
|
if (*address == ':') {
|
|
if (doubledots >= 0)
|
|
// :: allowed once
|
|
return false;
|
|
// remember location
|
|
doubledots = dots + !!acc;
|
|
address++;
|
|
}
|
|
if (dots == 7)
|
|
// too many separators
|
|
return false;
|
|
raw6()[dots++] = PP_HTONS(acc);
|
|
acc = 0;
|
|
}
|
|
else
|
|
// Invalid char
|
|
return false;
|
|
}
|
|
|
|
if (doubledots == -1 && dots != 7)
|
|
// Too few separators
|
|
return false;
|
|
raw6()[dots++] = PP_HTONS(acc);
|
|
|
|
if (doubledots != -1) {
|
|
for (int i = dots - doubledots - 1; i >= 0; i--)
|
|
raw6()[8 - dots + doubledots + i] = raw6()[doubledots + i];
|
|
for (int i = doubledots; i < 8 - dots + doubledots; i++)
|
|
raw6()[i] = 0;
|
|
}
|
|
|
|
setV6();
|
|
return true;
|
|
}
|
|
|
|
#endif
|