Browse Source

Various improvements and bug-fixes to the IPAddress class - added more comparison operators and support for IPv4-mapped IPv6 addresses

tags/2021-05-28
ed 7 years ago
parent
commit
8e463b4051
2 changed files with 139 additions and 29 deletions
  1. +102
    -17
      modules/juce_core/network/juce_IPAddress.cpp
  2. +37
    -12
      modules/juce_core/network/juce_IPAddress.h

+ 102
- 17
modules/juce_core/network/juce_IPAddress.cpp View File

@@ -85,24 +85,34 @@ IPAddress::IPAddress (uint32 n) noexcept : isIPv6 (false)
zeroUnusedBytes();
}
static String removePort (const String& adr)
{
if (adr.containsAnyOf ("[]"))
return adr.fromFirstOccurrenceOf ("[", false, true).upToLastOccurrenceOf ("]", false, true);
else if (adr.indexOf (":") == adr.lastIndexOf (":"))
return adr.upToLastOccurrenceOf (":", false, true);
return adr;
}
IPAddress::IPAddress (const String& adr)
{
isIPv6 = adr.contains (":");
auto ipAddress = removePort (adr);
isIPv6 = ipAddress.contains (":");
if (! isIPv6)
{
StringArray tokens;
tokens.addTokens (adr, ".", String());
auto tokens = StringArray::fromTokens (ipAddress, ".", {});
for (int i = 0; i < 4; ++i)
address[i] = (uint8) tokens[i].getIntValue();
}
else
{
StringArray tokens;
tokens.addTokens (adr.removeCharacters ("[]"), ":", String());
auto tokens = StringArray::fromTokens (ipAddress, ":", {});
if (tokens.contains (StringRef())) // if :: shorthand has been used
if (tokens.contains ({})) // if :: shorthand has been used
{
int idx = tokens.indexOf (StringRef());
tokens.set (idx, "0");
@@ -111,8 +121,22 @@ IPAddress::IPAddress (const String& adr)
tokens.insert (idx, "0");
}
tokens.removeEmptyStrings();
for (int i = 0; i < 8; ++i)
{
if (i == 6 && isIPv4MappedAddress (IPAddress (address, true)))
{
IPAddress v4Address (tokens[i]);
address[12] = v4Address.address[0];
address[13] = v4Address.address[1];
address[14] = v4Address.address[2];
address[15] = v4Address.address[3];
break;
}
ByteUnion temp;
temp.combined = (uint16) CharacterFunctions::HexParser<int>::parse (tokens[i].getCharPointer());
@@ -134,25 +158,62 @@ String IPAddress::toString() const
return s;
}
String addressString;
ByteUnion temp;
temp.split[0] = address[0];
temp.split[1] = address[1];
addressString = String (String::toHexString (temp.combined));
auto addressString = String::toHexString (temp.combined);
for (int i = 1; i < 8; ++i)
{
temp.split[0] = address[i * 2];
temp.split[1] = address[i * 2 + 1];
addressString << ':' << String (String::toHexString (temp.combined));
addressString << ':' << String::toHexString (temp.combined);
}
return getFormattedAddress (addressString);
}
bool IPAddress::operator== (const IPAddress& other) const noexcept { return compare (other) == 0; }
bool IPAddress::operator!= (const IPAddress& other) const noexcept { return compare (other) != 0; }
bool IPAddress::operator< (const IPAddress& other) const noexcept { return compare (other) < 0; }
bool IPAddress::operator<= (const IPAddress& other) const noexcept { return compare (other) <= 0; }
bool IPAddress::operator> (const IPAddress& other) const noexcept { return compare (other) > 0; }
bool IPAddress::operator>= (const IPAddress& other) const noexcept { return compare (other) >= 0; }
int IPAddress::compare (const IPAddress& other) const noexcept
{
if (isIPv6 != other.isIPv6)
{
if (isIPv6)
{
if (isIPv4MappedAddress (*this))
return convertIPv4MappedAddressToIPv4 (*this).compare (other);
return 1;
}
else
{
if (isIPv4MappedAddress (other))
return compare (convertIPv4MappedAddressToIPv4 (other));
return -1;
}
}
for (int i = 0; i < (isIPv6 ? 16 : 4); ++i)
{
if (address[i] > other.address[i])
return 1;
else if (address[i] < other.address[i])
return -1;
}
return 0;
}
IPAddress IPAddress::any() noexcept { return IPAddress(); }
IPAddress IPAddress::broadcast() noexcept { return IPAddress (255, 255, 255, 255); }
IPAddress IPAddress::local (bool IPv6) noexcept { return IPv6 ? IPAddress (0, 0, 0, 0, 0, 0, 0, 1)
@@ -174,7 +235,7 @@ String IPAddress::getFormattedAddress (const String& unformattedAddress)
for (int i = 0; i < tokens.size(); ++i)
{
const auto& t = tokens.getReference (i);
auto& t = tokens.getReference (i);
if (t.getHexValue32() == 0x0000)
{
@@ -232,21 +293,46 @@ String IPAddress::getFormattedAddress (const String& unformattedAddress)
return addressString;
}
bool IPAddress::operator== (const IPAddress& other) const noexcept
bool IPAddress::isIPv4MappedAddress (const IPAddress& mappedAddress)
{
for (int i = 0; i < (isIPv6 ? 16 : 4); ++i)
if (address[i] != other.address[i])
if (! mappedAddress.isIPv6)
return false;
for (int i = 0; i < 10; ++i)
{
if (mappedAddress.address[i] != 0)
return false;
}
if (mappedAddress.address[10] != 255 || mappedAddress.address[11] != 255)
return false;
return true;
}
IPAddress IPAddress::convertIPv4MappedAddressToIPv4 (const IPAddress& mappedAddress)
{
// The address that you're converting needs to be IPv6!
jassert (mappedAddress.isIPv6);
if (isIPv4MappedAddress (mappedAddress))
return { mappedAddress.address[12], mappedAddress.address[13],
mappedAddress.address[14], mappedAddress.address[15] };
return {};
}
bool IPAddress::operator!= (const IPAddress& other) const noexcept
IPAddress IPAddress::convertIPv4AddressToIPv4Mapped (const IPAddress& addressToMap)
{
return ! operator== (other);
// The address that you're converting needs to be IPv4!
jassert (! addressToMap.isIPv6);
return { 0x0, 0x0, 0x0, 0x0, 0x0, 0xffff,
static_cast<uint16> ((addressToMap.address[0] << 8) | addressToMap.address[1]),
static_cast<uint16> ((addressToMap.address[2] << 8) | addressToMap.address[3]) };
}
#if (! JUCE_WINDOWS) && (! JUCE_ANDROID)
static void addAddress (const sockaddr_in* addr_in, Array<IPAddress>& result)
{
@@ -277,8 +363,7 @@ static void addAddress (const sockaddr_in6* addr_in, Array<IPAddress>& result)
arr[i] = temp.combined;
}
IPAddress ip (arr);
result.addIfNotAlreadyThere (ip);
result.addIfNotAlreadyThere (IPAddress (arr));
}
void IPAddress::findAllAddresses (Array<IPAddress>& result, bool includeIPv6)


+ 37
- 12
modules/juce_core/network/juce_IPAddress.h View File

@@ -36,6 +36,15 @@ public:
/** Populates a list of all the IP addresses that this machine is using. */
static void findAllAddresses (Array<IPAddress>& results, bool includeIPv6 = false);
/** Returns an IP address meaning "any", equivalent to 0.0.0.0 (IPv4) or ::, (IPv6) */
static IPAddress any() noexcept;
/** Returns an IPv4 address meaning "broadcast" (255.255.255.255) */
static IPAddress broadcast() noexcept;
/** Returns an IPv4 or IPv6 address meaning "localhost", equivalent to 127.0.0.1 (IPv4) or ::1 (IPv6) */
static IPAddress local (bool IPv6 = false) noexcept;
//==============================================================================
/** Creates a null address - 0.0.0.0 (IPv4) or ::, (IPv6) */
IPAddress() noexcept;
@@ -66,32 +75,48 @@ public:
/** Parses a string IP address of the form "1.2.3.4" (IPv4) or "1:2:3:4:5:6:7:8" (IPv6). */
explicit IPAddress (const String& address);
//==============================================================================
/** Returns a dot- or colon-separated string in the form "1.2.3.4" (IPv4) or "1:2:3:4:5:6:7:8" (IPv6). */
String toString() const;
/** Returns an IPv4 or IPv6 address meaning "any", equivalent to 0.0.0.0 (IPv4) or ::, (IPv6) */
static IPAddress any() noexcept;
/** Compares this IPAddress with another.
/** Returns an IPv4 address meaning "broadcast" (255.255.255.255) */
static IPAddress broadcast() noexcept;
@returns 0 if the two addresses are identical, negative if this address is smaller than
the other one, or positive if is greater.
*/
int compare (const IPAddress& other) const noexcept;
/** Returns an IPv4 or IPv6 address meaning "localhost", equivalent to 127.0.0.1 (IPv4) or ::1 (IPv6) */
static IPAddress local (bool IPv6 = false) noexcept;
bool operator== (const IPAddress& other) const noexcept;
bool operator!= (const IPAddress& other) const noexcept;
bool operator< (const IPAddress& other) const noexcept;
bool operator> (const IPAddress& other) const noexcept;
bool operator<= (const IPAddress& other) const noexcept;
bool operator>= (const IPAddress& other) const noexcept;
//==============================================================================
/** The elements of the IP address. */
uint8 address[16];
bool isIPv6 = false;
//==============================================================================
/** Returns a formatted version of the provided IPv6 address conforming to RFC 5952 with leading zeros suppressed,
lower case characters, and double-colon notation used to represent contiguous 16-bit fields of zeros.
@param unformattedAddress the IPv6 address to be formatted
@param unformattedAddress the IPv6 address to be formatted
*/
static String getFormattedAddress (const String& unformattedAddress);
bool operator== (const IPAddress& other) const noexcept;
bool operator!= (const IPAddress& other) const noexcept;
/** Returns true if the given IP address is an IPv4-mapped IPv6 address. */
static bool isIPv4MappedAddress (const IPAddress& mappedAddress);
/** The elements of the IP address. */
uint8 address[16];
/** Converts an IPv4-mapped IPv6 address to an IPv4 address.
If the address is not IPv4-mapped, this will return a null address.
*/
static IPAddress convertIPv4MappedAddressToIPv4 (const IPAddress& mappedAddress);
bool isIPv6 = false;
/** Converts an IPv4 address to an IPv4-mapped IPv6 address. */
static IPAddress convertIPv4AddressToIPv4Mapped (const IPAddress& addressToMap);
private:
/** Union used to split a 16-bit unsigned integer into 2 8-bit unsigned integers or vice-versa */


Loading…
Cancel
Save