From 27fb6ea08abf9b2281e350d8a5d40b40d1c73934 Mon Sep 17 00:00:00 2001 From: Benjamin Cance <49796265+rowingdude@users.noreply.github.com> Date: Fri, 16 Aug 2024 12:44:43 -0400 Subject: [PATCH] This is in response to a 'to-do' in the codebase, the idea is to complete an IP address with 0s. --- cores/esp32/IPAddress.cpp | 107 ++++++++++++++++++++++++-------------- cores/esp32/IPAddress.h | 3 ++ 2 files changed, 72 insertions(+), 38 deletions(-) diff --git a/cores/esp32/IPAddress.cpp b/cores/esp32/IPAddress.cpp index b4fc4c3f7e0..6c5919c26ac 100644 --- a/cores/esp32/IPAddress.cpp +++ b/cores/esp32/IPAddress.cpp @@ -116,48 +116,79 @@ bool IPAddress::fromString(const char *address) { } bool IPAddress::fromString4(const char *address) { - // TODO: add support for "a", "a.b", "a.b.c" formats - int16_t acc = -1; // Accumulator - uint8_t dots = 0; + // 192 will be interpreted as 192.0.0.0 + // 192.168 will be interpreted as 192.168.0.0 + // 192.168.1 will be interpreted as 192.168.1.0 + // 192.168.1.1 will be interpreted as 192.168.1.1 - memset(_address.bytes, 0, sizeof(_address.bytes)); - while (*address) { - char c = *address++; - if (c >= '0' && c <= '9') { - acc = (acc < 0) ? (c - '0') : acc * 10 + (c - '0'); - if (acc > 255) { - // Value out of [0..255] range - return false; - } - } else if (c == '.') { - if (dots == 3) { - // Too many dots (there must be 3 dots) - return false; - } - if (acc < 0) { - /* No value between dots, e.g. '1..' */ - return false; - } - _address.bytes[IPADDRESS_V4_BYTES_INDEX + dots++] = acc; - acc = -1; - } else { - // Invalid char - return false; + // Should we have made it end in .1? + + uint8_t parts[4] = {0}; + int part = 0; + + memset(_address.bytes, 0, sizeof(_address.bytes)); + + while (*address && part < 4) { + if (!parseIPv4Part(address, parts[part])) { + return false; + } + part++; + + if (*address == '.') { + address++; + + } else if (*address != '\0') { + + return false; + } } - } - if (dots != 3) { - // Too few dots (there must be 3 dots) - return false; - } - if (acc < 0) { - /* No value between dots, e.g. '1..' */ - return false; - } - _address.bytes[IPADDRESS_V4_BYTES_INDEX + 3] = acc; - _type = IPv4; - return true; + // If address is incomplete, simply add more zeros until it's full + for (int i = part; i < 4; i++) { + parts[i] = 0; + } + + // Build the address + for (int i = 0; i < 4; i++) { + _address.bytes[IPADDRESS_V4_BYTES_INDEX + i] = parts[i]; + } + + _type = IPv4; + return true; +} + +bool IPAddress::parseIPv4Part(const char*& address, uint8_t& result) { + + // This works by parsing each section of the IP address + // It checks if the value is within the value space (<= 255) + // Uses the 'dot' as a delineater + + + int acc = 0; + int dots = 0; + + while (*address) { + char c = *address; + if (c >= '0' && c <= '9') { + acc = acc * 10 + (c - '0'); + if (acc > 255) { + return false; + } + } else if (c == '.' || c == '\0') { + if (dots == 3 || acc > 255) { + return false; + } + result = acc; + return true; + } else { + return false; + } + address++; + } + + result = acc; + return true; } bool IPAddress::fromString6(const char *address) { diff --git a/cores/esp32/IPAddress.h b/cores/esp32/IPAddress.h index b88aeed3026..492582a28c4 100644 --- a/cores/esp32/IPAddress.h +++ b/cores/esp32/IPAddress.h @@ -44,6 +44,9 @@ class IPAddress : public Printable { IPType _type; uint8_t _zone; + // Helper for parsing IPv4 address sections + bool parseIPv4Part(const char*& address, uint8_t& result); + // Access the raw byte array containing the address. Because this returns a pointer // to the internal structure rather than a copy of the address this function should only // be used when you know that the usage of the returned uint8_t* will be transient and not