@@ -55,10 +55,6 @@ | |||||
#if JUCE_WINDOWS | #if JUCE_WINDOWS | ||||
#include <ctime> | #include <ctime> | ||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1 | |||||
#include <winsock2.h> | |||||
#include <ws2tcpip.h> | |||||
#if ! JUCE_MINGW | #if ! JUCE_MINGW | ||||
#pragma warning (push) | #pragma warning (push) | ||||
#pragma warning (disable: 4091) | #pragma warning (disable: 4091) | ||||
@@ -121,6 +121,7 @@ | |||||
#define NOMINMAX | #define NOMINMAX | ||||
#define _WINSOCK_DEPRECATED_NO_WARNINGS 1 | |||||
#define STRICT 1 | #define STRICT 1 | ||||
#define WIN32_LEAN_AND_MEAN 1 | #define WIN32_LEAN_AND_MEAN 1 | ||||
#if JUCE_MINGW | #if JUCE_MINGW | ||||
@@ -141,6 +142,8 @@ | |||||
#include <ctime> | #include <ctime> | ||||
#include <wininet.h> | #include <wininet.h> | ||||
#include <nb30.h> | #include <nb30.h> | ||||
#include <winsock2.h> | |||||
#include <ws2tcpip.h> | |||||
#include <iphlpapi.h> | #include <iphlpapi.h> | ||||
#include <mapi.h> | #include <mapi.h> | ||||
#include <float.h> | #include <float.h> | ||||
@@ -400,26 +400,26 @@ private: | |||||
//============================================================================== | //============================================================================== | ||||
struct GetAdaptersInfoHelper | |||||
struct GetAdaptersAddressesHelper | |||||
{ | { | ||||
bool callGetAdaptersInfo() | |||||
bool callGetAdaptersAddresses() | |||||
{ | { | ||||
DynamicLibrary dll ("iphlpapi.dll"); | DynamicLibrary dll ("iphlpapi.dll"); | ||||
JUCE_LOAD_WINAPI_FUNCTION (dll, GetAdaptersInfo, getAdaptersInfo, DWORD, (PIP_ADAPTER_INFO, PULONG)) | |||||
JUCE_LOAD_WINAPI_FUNCTION (dll, GetAdaptersAddresses, getAdaptersAddresses, DWORD, (ULONG, ULONG, PVOID, PIP_ADAPTER_ADDRESSES, PULONG)) | |||||
if (getAdaptersInfo == nullptr) | |||||
if (getAdaptersAddresses == nullptr) | |||||
return false; | return false; | ||||
adapterInfo.malloc (1); | |||||
ULONG len = sizeof (IP_ADAPTER_INFO); | |||||
adaptersAddresses.malloc (1); | |||||
ULONG len = sizeof (IP_ADAPTER_ADDRESSES); | |||||
if (getAdaptersInfo (adapterInfo, &len) == ERROR_BUFFER_OVERFLOW) | |||||
adapterInfo.malloc (len, 1); | |||||
if (getAdaptersAddresses (AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, adaptersAddresses, &len) == ERROR_BUFFER_OVERFLOW) | |||||
adaptersAddresses.malloc (len, 1); | |||||
return getAdaptersInfo (adapterInfo, &len) == NO_ERROR; | |||||
return getAdaptersAddresses (AF_UNSPEC, GAA_FLAG_INCLUDE_PREFIX, NULL, adaptersAddresses, &len) == NO_ERROR; | |||||
} | } | ||||
HeapBlock<IP_ADAPTER_INFO> adapterInfo; | |||||
HeapBlock<IP_ADAPTER_ADDRESSES> adaptersAddresses; | |||||
}; | }; | ||||
namespace MACAddressHelpers | namespace MACAddressHelpers | ||||
@@ -430,15 +430,17 @@ namespace MACAddressHelpers | |||||
result.addIfNotAlreadyThere (ma); | result.addIfNotAlreadyThere (ma); | ||||
} | } | ||||
static void getViaGetAdaptersInfo (Array<MACAddress>& result) | |||||
static void getViaGetAdaptersAddresses (Array<MACAddress>& result) | |||||
{ | { | ||||
GetAdaptersInfoHelper gah; | |||||
GetAdaptersAddressesHelper addressesHelper; | |||||
if (gah.callGetAdaptersInfo()) | |||||
if (addressesHelper.callGetAdaptersAddresses()) | |||||
{ | { | ||||
for (PIP_ADAPTER_INFO adapter = gah.adapterInfo; adapter != nullptr; adapter = adapter->Next) | |||||
if (adapter->AddressLength >= 6) | |||||
addAddress (result, MACAddress (adapter->Address)); | |||||
for (PIP_ADAPTER_ADDRESSES adapter = addressesHelper.adaptersAddresses; adapter != nullptr; adapter = adapter->Next) | |||||
{ | |||||
if (adapter->PhysicalAddressLength >= 6) | |||||
addAddress (result, MACAddress (adapter->PhysicalAddress)); | |||||
} | |||||
} | } | ||||
} | } | ||||
@@ -493,24 +495,108 @@ namespace MACAddressHelpers | |||||
void MACAddress::findAllAddresses (Array<MACAddress>& result) | void MACAddress::findAllAddresses (Array<MACAddress>& result) | ||||
{ | { | ||||
MACAddressHelpers::getViaGetAdaptersInfo (result); | |||||
MACAddressHelpers::getViaGetAdaptersAddresses (result); | |||||
MACAddressHelpers::getViaNetBios (result); | MACAddressHelpers::getViaNetBios (result); | ||||
} | } | ||||
void IPAddress::findAllAddresses (Array<IPAddress>& result) | |||||
void IPAddress::findAllAddresses (Array<IPAddress>& result, bool includeIPv6) | |||||
{ | { | ||||
result.addIfNotAlreadyThere (IPAddress::local()); | |||||
result.addIfNotAlreadyThere (IPAddress::local ()); | |||||
GetAdaptersInfoHelper gah; | |||||
if (includeIPv6) | |||||
result.addIfNotAlreadyThere (IPAddress::local (true)); | |||||
if (gah.callGetAdaptersInfo()) | |||||
GetAdaptersAddressesHelper addressesHelper; | |||||
if (addressesHelper.callGetAdaptersAddresses()) | |||||
{ | { | ||||
for (PIP_ADAPTER_INFO adapter = gah.adapterInfo; adapter != nullptr; adapter = adapter->Next) | |||||
for (PIP_ADAPTER_ADDRESSES adapter = addressesHelper.adaptersAddresses; adapter != nullptr; adapter = adapter->Next) | |||||
{ | { | ||||
IPAddress ip (adapter->IpAddressList.IpAddress.String); | |||||
PIP_ADAPTER_UNICAST_ADDRESS pUnicast = nullptr; | |||||
for (pUnicast = adapter->FirstUnicastAddress; pUnicast != nullptr; pUnicast = pUnicast->Next) | |||||
{ | |||||
if (pUnicast->Address.lpSockaddr->sa_family == AF_INET) | |||||
{ | |||||
const sockaddr_in* sa_in = (sockaddr_in*)pUnicast->Address.lpSockaddr; | |||||
IPAddress ip ((uint8*)&sa_in->sin_addr.s_addr, false); | |||||
result.addIfNotAlreadyThere (ip); | |||||
} | |||||
else if (pUnicast->Address.lpSockaddr->sa_family == AF_INET6 && includeIPv6) | |||||
{ | |||||
const sockaddr_in6* sa_in6 = (sockaddr_in6*)pUnicast->Address.lpSockaddr; | |||||
ByteUnion temp; | |||||
uint16 arr[8]; | |||||
for (int i = 0; i < 8; ++i) | |||||
{ | |||||
temp.split[0] = sa_in6->sin6_addr.u.Byte[i * 2 + 1]; | |||||
temp.split[1] = sa_in6->sin6_addr.u.Byte[i * 2]; | |||||
arr[i] = temp.combined; | |||||
} | |||||
IPAddress ip (arr); | |||||
result.addIfNotAlreadyThere (ip); | |||||
} | |||||
} | |||||
PIP_ADAPTER_ANYCAST_ADDRESS pAnycast = nullptr; | |||||
for (pAnycast = adapter->FirstAnycastAddress; pAnycast != nullptr; pAnycast = pAnycast->Next) | |||||
{ | |||||
if (pAnycast->Address.lpSockaddr->sa_family == AF_INET) | |||||
{ | |||||
const sockaddr_in* sa_in = (sockaddr_in*)pAnycast->Address.lpSockaddr; | |||||
IPAddress ip ((uint8*)&sa_in->sin_addr.s_addr, false); | |||||
result.addIfNotAlreadyThere (ip); | |||||
} | |||||
else if (pAnycast->Address.lpSockaddr->sa_family == AF_INET6 && includeIPv6) | |||||
{ | |||||
const sockaddr_in6* sa_in6 = (sockaddr_in6*)pAnycast->Address.lpSockaddr; | |||||
ByteUnion temp; | |||||
uint16 arr[8]; | |||||
if (ip != IPAddress::any()) | |||||
result.addIfNotAlreadyThere (ip); | |||||
for (int i = 0; i < 8; ++i) | |||||
{ | |||||
temp.split[0] = sa_in6->sin6_addr.u.Byte[i * 2 + 1]; | |||||
temp.split[1] = sa_in6->sin6_addr.u.Byte[i * 2]; | |||||
arr[i] = temp.combined; | |||||
} | |||||
IPAddress ip (arr); | |||||
result.addIfNotAlreadyThere (ip); | |||||
} | |||||
} | |||||
PIP_ADAPTER_MULTICAST_ADDRESS pMulticast = nullptr; | |||||
for (pMulticast = adapter->FirstMulticastAddress; pMulticast != nullptr; pMulticast = pMulticast->Next) | |||||
{ | |||||
if (pMulticast->Address.lpSockaddr->sa_family == AF_INET) | |||||
{ | |||||
const sockaddr_in* sa_in = (sockaddr_in*)pMulticast->Address.lpSockaddr; | |||||
IPAddress ip ((uint8*)&sa_in->sin_addr.s_addr, false); | |||||
result.addIfNotAlreadyThere (ip); | |||||
} | |||||
else if (pMulticast->Address.lpSockaddr->sa_family == AF_INET6 && includeIPv6) | |||||
{ | |||||
const sockaddr_in6* sa_in6 = (sockaddr_in6*)pMulticast->Address.lpSockaddr; | |||||
ByteUnion temp; | |||||
uint16 arr[8]; | |||||
for (int i = 0; i < 8; ++i) | |||||
{ | |||||
temp.split[0] = sa_in6->sin6_addr.u.Byte[i * 2 + 1]; | |||||
temp.split[1] = sa_in6->sin6_addr.u.Byte[i * 2]; | |||||
arr[i] = temp.combined; | |||||
} | |||||
IPAddress ip (arr); | |||||
result.addIfNotAlreadyThere (ip); | |||||
} | |||||
} | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -28,61 +28,222 @@ | |||||
============================================================================== | ============================================================================== | ||||
*/ | */ | ||||
IPAddress::IPAddress() noexcept | |||||
IPAddress::IPAddress (bool IPv6) noexcept : isIPv6 (IPv6) | |||||
{ | { | ||||
address[0] = 0; address[1] = 0; | |||||
address[2] = 0; address[3] = 0; | |||||
for (int i = 0; i < 16; ++i) | |||||
address[i] = 0; | |||||
} | } | ||||
IPAddress::IPAddress (const uint8 bytes[4]) noexcept | |||||
IPAddress::IPAddress (const uint8 bytes[], bool IPv6) noexcept : isIPv6 (IPv6) | |||||
{ | { | ||||
address[0] = bytes[0]; address[1] = bytes[1]; | |||||
address[2] = bytes[2]; address[3] = bytes[3]; | |||||
for (int i = 0; i < (isIPv6 ? 16 : 4); ++i) | |||||
address[i] = bytes[i]; | |||||
if (! isIPv6) | |||||
zeroUnusedBytes(); | |||||
} | } | ||||
IPAddress::IPAddress (uint8 a0, uint8 a1, uint8 a2, uint8 a3) noexcept | |||||
IPAddress::IPAddress (const uint16 bytes[8]) noexcept : isIPv6 (true) | |||||
{ | |||||
ByteUnion temp; | |||||
for (int i = 0; i < 8; ++i) | |||||
{ | |||||
temp.combined = bytes[i]; | |||||
address[i * 2] = temp.split[0]; | |||||
address[i * 2 + 1] = temp.split[1]; | |||||
} | |||||
} | |||||
IPAddress::IPAddress (uint8 a0, uint8 a1, uint8 a2, uint8 a3) noexcept : isIPv6 (false) | |||||
{ | { | ||||
address[0] = a0; address[1] = a1; | address[0] = a0; address[1] = a1; | ||||
address[2] = a2; address[3] = a3; | address[2] = a2; address[3] = a3; | ||||
zeroUnusedBytes(); | |||||
} | } | ||||
IPAddress::IPAddress (uint32 n) noexcept | |||||
IPAddress::IPAddress (uint16 a1, uint16 a2, uint16 a3, uint16 a4, | |||||
uint16 a5, uint16 a6, uint16 a7, uint16 a8) noexcept : isIPv6 (true) | |||||
{ | |||||
uint16 array[8] = { a1, a2, a3, a4, a5, a6, a7, a8 }; | |||||
ByteUnion temp; | |||||
for (int i = 0; i < 8; ++i) | |||||
{ | |||||
temp.combined = array[i]; | |||||
address[i * 2] = temp.split[0]; | |||||
address[i * 2 + 1] = temp.split[1]; | |||||
} | |||||
} | |||||
IPAddress::IPAddress (uint32 n) noexcept : isIPv6 (false) | |||||
{ | { | ||||
address[0] = (n >> 24); | address[0] = (n >> 24); | ||||
address[1] = (n >> 16) & 255; | address[1] = (n >> 16) & 255; | ||||
address[2] = (n >> 8) & 255; | |||||
address[2] = (n >> 8) & 255; | |||||
address[3] = (n & 255); | address[3] = (n & 255); | ||||
zeroUnusedBytes(); | |||||
} | } | ||||
IPAddress::IPAddress (const String& adr) | IPAddress::IPAddress (const String& adr) | ||||
{ | { | ||||
StringArray tokens; | |||||
tokens.addTokens (adr, ".", String()); | |||||
isIPv6 = adr.contains (":"); | |||||
if (! isIPv6) | |||||
{ | |||||
StringArray tokens; | |||||
tokens.addTokens (adr, ".", String()); | |||||
for (int i = 0; i < 4; ++i) | |||||
address[i] = (uint8) tokens[i].getIntValue(); | |||||
} | |||||
else | |||||
{ | |||||
StringArray tokens; | |||||
tokens.addTokens (adr.removeCharacters ("[]"), ":", String()); | |||||
if (tokens.contains (StringRef())) // if :: shorthand has been used | |||||
{ | |||||
int idx = tokens.indexOf (StringRef()); | |||||
tokens.set (idx, "0"); | |||||
while (tokens.size() < 8) | |||||
tokens.insert (idx, "0"); | |||||
} | |||||
for (int i = 0; i < 8; ++i) | |||||
{ | |||||
ByteUnion temp; | |||||
temp.combined = (uint16) CharacterFunctions::HexParser<int>::parse (tokens[i].getCharPointer()); | |||||
for (int i = 0; i < 4; ++i) | |||||
address[i] = (uint8) tokens[i].getIntValue(); | |||||
address[i * 2] = temp.split[0]; | |||||
address[i * 2 + 1] = temp.split[1]; | |||||
} | |||||
} | |||||
} | } | ||||
String IPAddress::toString() const | String IPAddress::toString() const | ||||
{ | { | ||||
String s ((int) address[0]); | |||||
if (! isIPv6) | |||||
{ | |||||
String s ((int) address[0]); | |||||
for (int i = 1; i < 4; ++i) | |||||
s << '.' << (int) address[i]; | |||||
return s; | |||||
} | |||||
for (int i = 1; i < 4; ++i) | |||||
s << '.' << (int) address[i]; | |||||
String addressString; | |||||
ByteUnion temp; | |||||
temp.split[0] = address[0]; | |||||
temp.split[1] = address[1]; | |||||
addressString = String (String::toHexString (temp.combined)); | |||||
for (int i = 1; i < 8; ++i) | |||||
{ | |||||
temp.split[0] = address[i * 2]; | |||||
temp.split[1] = address[i * 2 + 1]; | |||||
return s; | |||||
addressString << ':' << String (String::toHexString (temp.combined)); | |||||
} | |||||
return getFormattedAddress (addressString); | |||||
} | } | ||||
IPAddress IPAddress::any() noexcept { return IPAddress(); } | |||||
IPAddress IPAddress::broadcast() noexcept { return IPAddress (255, 255, 255, 255); } | |||||
IPAddress IPAddress::local() noexcept { return IPAddress (127, 0, 0, 1); } | |||||
IPAddress IPAddress::any (bool IPv6) noexcept { return IPAddress (IPv6); } | |||||
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) | |||||
: IPAddress (127, 0, 0, 1); } | |||||
String IPAddress::getFormattedAddress (const String& unformattedAddress) | |||||
{ | |||||
jassert (unformattedAddress.contains (":") && ! unformattedAddress.contains ("::")); // needs to be an unformatted IPv6 address! | |||||
String portString = unformattedAddress.fromFirstOccurrenceOf ("]", false, true); | |||||
String addressString = unformattedAddress.dropLastCharacters (portString.length()).removeCharacters ("[]"); | |||||
StringArray tokens; | |||||
tokens.addTokens (addressString, ":", String()); | |||||
int numZeros = 0; | |||||
int numZerosTemp = 0; | |||||
bool isFirst = false; | |||||
bool isLast = false; | |||||
for (int i = 0; i < tokens.size(); ++i) | |||||
{ | |||||
String t = tokens.getReference (i); | |||||
if (t.getHexValue32() == 0x0000) | |||||
{ | |||||
++numZeros; | |||||
if (i == 0) | |||||
isFirst = true; | |||||
else if (i == tokens.size() - 1 && numZeros > numZerosTemp) | |||||
isLast = true; | |||||
if (t.length() > 1) | |||||
addressString = addressString.replace (String::repeatedString ("0", t.length()), "0"); | |||||
if (isFirst && numZerosTemp != 0 && numZeros > numZerosTemp) | |||||
isFirst = false; | |||||
} | |||||
else | |||||
{ | |||||
addressString = addressString.replace (t, t.trimCharactersAtStart ("0").toLowerCase()); | |||||
if (numZeros > 0) | |||||
{ | |||||
if (numZeros > numZerosTemp) | |||||
numZerosTemp = numZeros; | |||||
numZeros = 0; | |||||
} | |||||
} | |||||
} | |||||
if (numZerosTemp > numZeros) | |||||
numZeros = numZerosTemp; | |||||
if (numZeros > 1) | |||||
{ | |||||
if (numZeros == tokens.size()) | |||||
addressString = "::,"; | |||||
else | |||||
{ | |||||
String zeroString = isFirst ? String ("0") + String::repeatedString (":0", numZeros - 1) | |||||
: String::repeatedString (":0", numZeros); | |||||
addressString = addressString.replaceFirstOccurrenceOf (zeroString, ":"); | |||||
if (isLast) | |||||
addressString += String (":"); | |||||
} | |||||
} | |||||
if (portString.isNotEmpty()) | |||||
addressString = String ("[") + addressString + String ("]") + portString; | |||||
return addressString; | |||||
} | |||||
bool IPAddress::operator== (const IPAddress& other) const noexcept | bool IPAddress::operator== (const IPAddress& other) const noexcept | ||||
{ | { | ||||
return address[0] == other.address[0] | |||||
&& address[1] == other.address[1] | |||||
&& address[2] == other.address[2] | |||||
&& address[3] == other.address[3]; | |||||
for (int i = 0; i < (isIPv6 ? 16 : 4); ++i) | |||||
if (address[i] != other.address[i]) | |||||
return false; | |||||
return true; | |||||
} | } | ||||
bool IPAddress::operator!= (const IPAddress& other) const noexcept | bool IPAddress::operator!= (const IPAddress& other) const noexcept | ||||
@@ -99,53 +260,47 @@ static void addAddress (const sockaddr_in* addr_in, Array<IPAddress>& result) | |||||
result.addIfNotAlreadyThere (IPAddress (ntohl (addr))); | result.addIfNotAlreadyThere (IPAddress (ntohl (addr))); | ||||
} | } | ||||
static void findIPAddresses (int sock, Array<IPAddress>& result) | |||||
static void addAddress (const sockaddr_in6* addr_in, Array<IPAddress>& result) | |||||
{ | { | ||||
ifconf cfg; | |||||
HeapBlock<char> buffer; | |||||
int bufferSize = 1024; | |||||
in6_addr addr = addr_in->sin6_addr; | |||||
do | |||||
typedef union | |||||
{ | { | ||||
bufferSize *= 2; | |||||
buffer.calloc ((size_t) bufferSize); | |||||
cfg.ifc_len = bufferSize; | |||||
cfg.ifc_buf = buffer; | |||||
uint16 combined; | |||||
uint8 split[2]; | |||||
} ByteUnion; | |||||
if (ioctl (sock, SIOCGIFCONF, &cfg) < 0 && errno != EINVAL) | |||||
return; | |||||
ByteUnion temp; | |||||
uint16 arr[8]; | |||||
} while (bufferSize < cfg.ifc_len + 2 * (int) (IFNAMSIZ + sizeof (struct sockaddr_in6))); | |||||
#if JUCE_MAC || JUCE_IOS | |||||
while (cfg.ifc_len >= (int) (IFNAMSIZ + sizeof (struct sockaddr_in))) | |||||
for (int i = 0; i < 8; ++i) // Swap bytes from network to host order | |||||
{ | { | ||||
if (cfg.ifc_req->ifr_addr.sa_family == AF_INET) // Skip non-internet addresses | |||||
addAddress ((const sockaddr_in*) &cfg.ifc_req->ifr_addr, result); | |||||
temp.split[0] = addr.s6_addr[i * 2 + 1]; | |||||
temp.split[1] = addr.s6_addr[i * 2]; | |||||
cfg.ifc_len -= IFNAMSIZ + cfg.ifc_req->ifr_addr.sa_len; | |||||
cfg.ifc_buf += IFNAMSIZ + cfg.ifc_req->ifr_addr.sa_len; | |||||
arr[i] = temp.combined; | |||||
} | } | ||||
#else | |||||
for (size_t i = 0; i < (size_t) cfg.ifc_len / (size_t) sizeof (struct ifreq); ++i) | |||||
{ | |||||
const ifreq& item = cfg.ifc_req[i]; | |||||
if (item.ifr_addr.sa_family == AF_INET) | |||||
addAddress ((const sockaddr_in*) &item.ifr_addr, result); | |||||
} | |||||
#endif | |||||
IPAddress ip (arr); | |||||
result.addIfNotAlreadyThere (ip); | |||||
} | } | ||||
void IPAddress::findAllAddresses (Array<IPAddress>& result) | |||||
void IPAddress::findAllAddresses (Array<IPAddress>& result, bool includeIPv6) | |||||
{ | { | ||||
const int sock = socket (AF_INET, SOCK_DGRAM, 0); // a dummy socket to execute the IO control | |||||
struct ifaddrs *ifaddr, *ifa; | |||||
if (getifaddrs (&ifaddr) == -1) | |||||
return; | |||||
if (sock >= 0) | |||||
for (ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) | |||||
{ | { | ||||
findIPAddresses (sock, result); | |||||
::close (sock); | |||||
if (ifa->ifa_addr == nullptr) | |||||
continue; | |||||
if (ifa->ifa_addr->sa_family == AF_INET) addAddress ((const sockaddr_in*) ifa->ifa_addr, result); | |||||
else if (ifa->ifa_addr->sa_family == AF_INET6 && includeIPv6) addAddress ((const sockaddr_in6*) ifa->ifa_addr, result); | |||||
} | } | ||||
freeifaddrs (ifaddr); | |||||
} | } | ||||
#endif | #endif |
@@ -33,48 +33,83 @@ | |||||
//============================================================================== | //============================================================================== | ||||
/** | /** | ||||
An IPV4 address. | |||||
Represents an IP address. | |||||
*/ | */ | ||||
class JUCE_API IPAddress | class JUCE_API IPAddress | ||||
{ | { | ||||
public: | public: | ||||
//============================================================================== | //============================================================================== | ||||
/** Populates a list of all the IP addresses that this machine is using. */ | /** Populates a list of all the IP addresses that this machine is using. */ | ||||
static void findAllAddresses (Array<IPAddress>& results); | |||||
static void findAllAddresses (Array<IPAddress>& results, bool includeIPv6 = false); | |||||
//============================================================================== | //============================================================================== | ||||
/** Creates a null address (0.0.0.0). */ | |||||
IPAddress() noexcept; | |||||
/** Creates a null address - 0.0.0.0 (IPv4) or ::, (IPv6) | |||||
@param IPv6 if true indicates that this is an IPv6 address | |||||
*/ | |||||
IPAddress (bool IPv6 = false) noexcept; | |||||
/** Creates an IPv4 or IPv6 address by reading 4 or 16 bytes from an array. | |||||
@param IPv6 if true indicates that 16 bytes should be read instead of 4. | |||||
*/ | |||||
explicit IPAddress (const uint8 bytes[], bool IPv6 = false) noexcept; | |||||
/** Creates an address from 4 bytes. */ | |||||
explicit IPAddress (const uint8 bytes[4]) noexcept; | |||||
/** Creates an IPv6 address from an array of 8 16-bit integers */ | |||||
explicit IPAddress (const uint16 bytes[8]) noexcept; | |||||
/** Creates an address from 4 bytes. */ | |||||
/** Creates an IPv4 address from 4 bytes. */ | |||||
IPAddress (uint8 address1, uint8 address2, uint8 address3, uint8 address4) noexcept; | IPAddress (uint8 address1, uint8 address2, uint8 address3, uint8 address4) noexcept; | ||||
/** Creates an address from a packed 32-bit integer, where the MSB is | |||||
the first number in the address, and the LSB is the last. | |||||
/** Creates an IPv6 address from 8 16-bit integers */ | |||||
IPAddress (uint16 address1, uint16 address2, uint16 address3, uint16 address4, | |||||
uint16 address5, uint16 address6, uint16 address7, uint16 address8) noexcept; | |||||
/** Creates an IPv4 address from a packed 32-bit integer, where the | |||||
MSB is the first number in the address, and the LSB is the last. | |||||
*/ | */ | ||||
explicit IPAddress (uint32 asNativeEndian32Bit) noexcept; | explicit IPAddress (uint32 asNativeEndian32Bit) noexcept; | ||||
/** Parses a string IP address of the form "a.b.c.d". */ | |||||
/** 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); | explicit IPAddress (const String& address); | ||||
/** Returns a dot-separated string in the form "1.2.3.4" */ | |||||
/** 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; | String toString() const; | ||||
/** Returns an address meaning "any" (0.0.0.0) */ | |||||
static IPAddress any() noexcept; | |||||
/** Returns an IPv4 or IPv6 address meaning "any", equivalent to 0.0.0.0 (IPv4) or ::, (IPv6) */ | |||||
static IPAddress any (bool IPv6 = false) noexcept; | |||||
/** Returns an address meaning "broadcast" (255.255.255.255) */ | |||||
/** Returns an IPv4 address meaning "broadcast" (255.255.255.255) */ | |||||
static IPAddress broadcast() noexcept; | static IPAddress broadcast() noexcept; | ||||
/** Returns an address meaning "localhost" (127.0.0.1) */ | |||||
static IPAddress local() 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; | |||||
/** 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 | |||||
*/ | |||||
static String getFormattedAddress (const String& unformattedAddress); | |||||
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. */ | /** The elements of the IP address. */ | ||||
uint8 address[4]; | |||||
uint8 address[16]; | |||||
bool isIPv6; | |||||
private: | |||||
/** Union used to split a 16-bit unsigned integer into 2 8-bit unsigned integers or vice-versa */ | |||||
typedef union | |||||
{ | |||||
uint16 combined; | |||||
uint8 split[2]; | |||||
} ByteUnion; | |||||
/** Method used to zero the remaining bytes of the address array when creating IPv4 addresses */ | |||||
void zeroUnusedBytes() | |||||
{ | |||||
for (int i = 4; i < 16; ++i) | |||||
address[i] = 0; | |||||
} | |||||
}; | }; |