| @@ -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; | |||||
| } | |||||
| }; | }; | ||||