rtphone/src/libs/ice/ICEAddress.cpp

825 lines
19 KiB
C++

/* Copyright(C) 2007-2018 VoIP objects (voipobjects.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#if defined(__MINGW32__)
# include <w32api.h>
# define WINVER WindowsVista
# define _WIN32_WINDOWS WindowsVista
# define _WIN32_WINNT WindowsVista
#endif
#include "ICEPlatform.h"
#include "ICEAddress.h"
#include "ICEError.h"
#include <assert.h>
#include <stdio.h>
#if defined(TARGET_WIN)
# include <WinSock2.h>
# include <Windows.h>
# include <ws2tcpip.h>
#else
# include <netinet/in.h>
# if /*defined(TARGET_LINUX) || */ defined(TARGET_ANDROID)
# include <linux/in6.h>
# endif
#endif
std::ostream& operator << (std::ostream& s, const ice::NetworkAddress& addr)
{
s << addr.toStdString().c_str();
return s;
}
#ifdef TARGET_WIN
std::wostream& operator << (std::wostream& s, const ice::NetworkAddress& addr)
{
s << addr.toStdWString();
return s;
}
#endif
using namespace ice;
NetworkAddress NetworkAddress::LoopbackAddress4("127.0.0.1", 1000);
#ifdef TARGET_WIN
static in_addr6 la6 = {0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1 };
#else
static in6_addr la6 = { { { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1 } } };
#endif
NetworkAddress NetworkAddress::LoopbackAddress6(la6, 1000);
NetworkAddress NetworkAddress::parse(const std::string& s)
{
NetworkAddress result;
result.mInitialized = !s.empty();
if (result.mInitialized)
{
// Relayed or not
result.mRelayed = s.find("relayed ") != std::string::npos;
std::string::size_type ip4Pos = s.find("IPv4"), ip6Pos = s.find("IPv6");
if (ip4Pos == std::string::npos && ip6Pos == std::string::npos)
{
// Parse usual IP[:port] pair
std::string::size_type cp = s.find(":");
if (cp == std::string::npos)
result.setIp(cp);
else
{
result.setIp(s.substr(0, cp));
result.setPort(atoi(s.substr(cp + 1).c_str()));
}
}
else
{
// Family
result.mAddr4.sin_family = ip4Pos != std::string::npos ? AF_INET : AF_INET6;
// IP:port
std::string::size_type familyPos = ip4Pos != std::string::npos ? ip4Pos : ip6Pos;
std::string addr = s.substr(familyPos + 5);
// Find IP substring and port
std::string::size_type colonPos = addr.find_last_of(":");
if (colonPos != std::string::npos)
{
int port = atoi(addr.substr(colonPos+1).c_str());
result.setPort(port);
result.setIp(addr.substr(0, colonPos));
}
}
}
return result;
}
// NetworkAddress NetworkAddress::LoopbackAddress6("0:0:0:0:0:0:0:1", 1000);
NetworkAddress::NetworkAddress()
:mInitialized(false), mRelayed(false)
{
memset(&mAddr6, 0, sizeof(mAddr6));
mAddr4.sin_family = AF_INET;
}
NetworkAddress::NetworkAddress(int stunType)
:mInitialized(false), mRelayed(false)
{
memset(&mAddr6, 0, sizeof(mAddr6));
setStunType(stunType);
}
NetworkAddress::NetworkAddress(const in6_addr& addr6, unsigned short port)
:mInitialized(true), mRelayed(false)
{
memset(&mAddr6, 0, sizeof(mAddr6));
mAddr4.sin_family = AF_INET6;
mAddr6.sin6_addr = addr6;
mAddr6.sin6_port = htons(port);
}
NetworkAddress::NetworkAddress(const in_addr& addr4, unsigned short port)
:mInitialized(true), mRelayed(false)
{
memset(&mAddr6, 0, sizeof(mAddr6));
mAddr4.sin_family = AF_INET;
mAddr4.sin_addr = addr4;
mAddr4.sin_port = htons(port);
}
unsigned char NetworkAddress::stunType() const
{
assert(mInitialized);
switch (mAddr4.sin_family)
{
case AF_INET:
return 1;
case AF_INET6:
return 2;
default:
assert(0);
}
return -1;
}
void NetworkAddress::setStunType(unsigned char st)
{
switch (st)
{
case 1:
mAddr4.sin_family = AF_INET;
break;
case 2:
mAddr6.sin6_family = AF_INET6;
break;
default:
assert(0);
}
}
NetworkAddress::NetworkAddress(const std::string& ip, unsigned short port)
:mInitialized(true), mRelayed(false)
{
memset(&mAddr6, 0, sizeof(mAddr6));
setIp(ip);
if (mAddr4.sin_family == AF_INET || mAddr4.sin_family == AF_INET6)
setPort(port);
}
NetworkAddress::NetworkAddress(const char *ip, unsigned short port)
:mInitialized(true), mRelayed(false)
{
memset(&mAddr6, 0, sizeof(mAddr6));
setIp(ip);
if (mAddr4.sin_family == AF_INET || mAddr4.sin_family == AF_INET6)
setPort(port);
}
NetworkAddress::NetworkAddress(uint32_t ip_4, uint16_t port)
:mInitialized(true), mRelayed(false)
{
memset(&mAddr6, 0, sizeof(mAddr6));
mAddr4.sin_family = AF_INET;
mAddr4.sin_addr.s_addr = ip_4;
mAddr4.sin_port = port;
}
NetworkAddress::NetworkAddress(const uint8_t* ip_6, uint16_t port)
:mInitialized(true), mRelayed(false)
{
memset(&mAddr6, 0, sizeof(mAddr6));
mAddr6.sin6_family = AF_INET6;
memmove(&mAddr6.sin6_addr, ip_6, sizeof(mAddr6.sin6_addr));
mAddr6.sin6_port = port;
}
NetworkAddress::NetworkAddress(const sockaddr& addr, size_t addrLen)
:mInitialized(true), mRelayed(false)
{
switch (addr.sa_family)
{
case AF_INET6:
memset(&mAddr6, 0, sizeof(mAddr6));
memcpy(&mAddr6, &addr, addrLen);
break;
case AF_INET:
memset(&mAddr4, 0, sizeof(mAddr4));
memcpy(&mAddr4, &addr, addrLen);
break;
}
}
NetworkAddress::NetworkAddress(const NetworkAddress& src)
:mInitialized(src.mInitialized), mRelayed(src.mRelayed)
{
memset(&mAddr6, 0, sizeof(mAddr6));
if (src.mAddr4.sin_family == AF_INET)
memcpy(&mAddr4, &src.mAddr4, sizeof mAddr4);
else
memcpy(&mAddr6, &src.mAddr6, sizeof mAddr6);
}
NetworkAddress::~NetworkAddress()
{
}
int NetworkAddress::family() const
{
assert(mInitialized == true);
return this->mAddr4.sin_family;
}
sockaddr* NetworkAddress::genericsockaddr() const
{
assert(mInitialized == true);
switch (mAddr4.sin_family)
{
case AF_INET:
return (sockaddr*)&mAddr4;
case AF_INET6:
return (sockaddr*)&mAddr6;
default:
assert(0);
}
return NULL;
}
unsigned NetworkAddress::sockaddrLen() const
{
assert(mInitialized == true);
switch (mAddr4.sin_family)
{
case AF_INET:
return sizeof(mAddr4);
case AF_INET6:
return sizeof(mAddr6);
default:
assert(0);
}
return 0;
}
sockaddr_in* NetworkAddress::sockaddr4() const
{
assert(mInitialized == true);
switch (mAddr4.sin_family)
{
case AF_INET:
return (sockaddr_in*)&mAddr4;
default:
assert(0);
}
return NULL;
}
sockaddr_in6* NetworkAddress::sockaddr6() const
{
assert(mInitialized == true);
switch (mAddr4.sin_family)
{
case AF_INET6:
return (sockaddr_in6*)&mAddr6;
default:
assert(0);
}
return NULL;
}
void NetworkAddress::setIp(NetworkAddress ipOnly)
{
// Save port
mAddr4.sin_family = ipOnly.genericsockaddr()->sa_family;
switch (ipOnly.family())
{
case AF_INET:
memcpy(&mAddr4.sin_addr, &ipOnly.sockaddr4()->sin_addr, 4);
break;
case AF_INET6:
memcpy(&mAddr4.sin_addr, &ipOnly.sockaddr6()->sin6_addr, 16);
break;
default:
assert(0);
}
}
void NetworkAddress::setIp(const std::string& ip)
{
#ifdef TARGET_WIN
int addrSize = sizeof(mAddr6);
#endif
if (inet_addr(ip.c_str()) != INADDR_NONE)
{
mAddr4.sin_family = AF_INET;
mAddr4.sin_addr.s_addr = inet_addr(ip.c_str());
if (mAddr4.sin_port)
mInitialized = true;
}
else
{
mAddr6.sin6_family = AF_INET6;
#ifdef TARGET_WIN
if (WSAStringToAddressA((char*)ip.c_str(), AF_INET6, NULL, (sockaddr*)&mAddr6, &addrSize) != 0)
#else
std::string ip2;
if (ip.find('[') == 0 && ip.find(']') == ip.length()-1)
ip2 = ip.substr(1, ip.length()-2);
else
ip2 = ip;
if (!inet_pton(AF_INET6, ip2.c_str(), &mAddr6.sin6_addr))
#endif
{
mInitialized = false;
return;
}
mAddr6.sin6_family = AF_INET6;
if (mAddr6.sin6_port)
mInitialized = true;
}
}
void NetworkAddress::setIp(unsigned long ip)
{
mAddr4.sin_family = AF_INET;
mAddr4.sin_addr.s_addr = ip;
if (mAddr4.sin_port)
mInitialized = true;
}
void NetworkAddress::setIp(const in_addr& ip)
{
//memset(&mAddr4, 0, sizeof mAddr4);
mAddr4.sin_family = AF_INET;
mAddr4.sin_addr = ip;
}
void NetworkAddress::setIp(const in6_addr& ip)
{
mAddr6.sin6_family = AF_INET6;
mAddr6.sin6_addr = ip;
}
// 10.0.0.0 - 10.255.255.255
// 172.16.0.0 - 172.31.255.255
// 192.168.0.0 - 192.168.255.255
bool NetworkAddress::isSameLAN(const NetworkAddress& a1, const NetworkAddress& a2)
{
if (a1.family() != a2.family())
return false;
if (a1.family() == AF_INET)
{
sockaddr_in* s1 = a1.sockaddr4();
sockaddr_in* s2 = a2.sockaddr4();
#ifdef TARGET_WIN
unsigned b1_0 = (s1->sin_addr.S_un.S_addr >> 0) & 0xFF;
unsigned b1_1 = (s1->sin_addr.S_un.S_addr >> 8) & 0xFF;
unsigned b2_0 = (s2->sin_addr.S_un.S_addr >> 0) & 0xFF;
unsigned b2_1 = (s2->sin_addr.S_un.S_addr >> 8) & 0xFF;
#else
unsigned b1_0 = (s1->sin_addr.s_addr >> 0) & 0xFF;
unsigned b1_1 = (s1->sin_addr.s_addr >> 8) & 0xFF;
unsigned b2_0 = (s2->sin_addr.s_addr >> 0) & 0xFF;
unsigned b2_1 = (s2->sin_addr.s_addr >> 8) & 0xFF;
if (b1_0 == b2_0 && b1_0 == 192 &&
b1_1 == b2_1 && b1_1 == 168)
return true;
if (b1_0 == b2_0 && b1_0 == 10)
return true;
if (b1_0 == b2_0 && b1_0 == 172 &&
b1_1 == b2_1 && (b1_1 < 32))
return true;
#endif
}
return false;
}
void NetworkAddress::setPort(unsigned short port)
{
switch(mAddr4.sin_family)
{
case AF_INET:
mAddr4.sin_port = htons(port);
mInitialized = true;
break;
case AF_INET6:
mAddr6.sin6_port = htons(port);
mInitialized = true;
break;
default:
assert(0);
}
}
std::string NetworkAddress::ip() const
{
assert(mInitialized == true);
char resultbuf[159], ip6[161]; resultbuf[0] = 0;
#ifdef TARGET_WIN
DWORD resultsize = sizeof(resultbuf);
#endif
switch (mAddr4.sin_family)
{
case AF_INET:
return inet_ntoa(mAddr4.sin_addr);
case AF_INET6:
#if defined(TARGET_WIN)
InetNtopA(AF_INET6, (PVOID)&mAddr6.sin6_addr, resultbuf, sizeof(resultbuf));
#else
inet_ntop(AF_INET6, &mAddr6.sin6_addr, resultbuf, sizeof(resultbuf));
#endif
sprintf(ip6, "[%s]", resultbuf);
return ip6;
default:
return "";
}
return "";
}
unsigned char* NetworkAddress::ipBytes() const
{
switch (family())
{
case AF_INET:
#ifdef TARGET_WIN
return (unsigned char*)&mAddr4.sin_addr.S_un.S_un_b;
#else
return (unsigned char*)&mAddr4.sin_addr.s_addr;
#endif
case AF_INET6:
#ifdef TARGET_WIN
return (unsigned char*)mAddr6.sin6_addr.u.Byte;
#elif defined(TARGET_OSX) || defined(TARGET_IOS)
return (unsigned char*)&mAddr6.sin6_addr.__u6_addr.__u6_addr8;
#elif defined(TARGET_OPENWRT) || defined(TARGET_MUSL)
return (unsigned char*)&mAddr6.sin6_addr.__in6_union.__s6_addr;
#elif defined(TARGET_LINUX)
return (unsigned char*)&mAddr6.sin6_addr.__in6_u.__u6_addr8;
#elif defined(TARGET_ANDROID)
return (unsigned char*)&mAddr6.sin6_addr.in6_u.u6_addr8;
#endif
}
assert(0);
return nullptr; // to avoid compiler warning
}
unsigned short NetworkAddress::port() const
{
assert(mInitialized == true);
return ntohs(mAddr4.sin_port);
}
std::string NetworkAddress::toStdString() const
{
if (!mInitialized)
return "";
char temp[128];
sprintf(temp, "%s%s %s:%u", mRelayed ? "relayed " : "", this->mAddr4.sin_family == AF_INET ? "IPv4" : "IPv6", ip().c_str(), (unsigned int)port());
return temp;
}
std::string NetworkAddress::toBriefStdString() const
{
if (!mInitialized)
return "";
char temp[128];
sprintf(temp, "%s:%u", ip().c_str(), (unsigned int)port());
return temp;
}
#ifdef WIN32
std::wstring NetworkAddress::toStdWString() const
{
if (!mInitialized)
return L"";
wchar_t temp[128];
swprintf(temp, L"%s%s %S:%u", mRelayed ? L"relayed " : L"", this->mAddr4.sin_family == AF_INET ? L"IPv4" : L"IPv6", ip().c_str(), (unsigned int)port());
return temp;
}
#endif
static const unsigned char localhost6[] =
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 };
bool NetworkAddress::isLoopback() const
{
switch (mAddr4.sin_family)
{
case AF_INET:
return (mAddr4.sin_addr.s_addr == htonl(INADDR_LOOPBACK));
case AF_INET6:
return memcmp(localhost6, &mAddr6.sin6_addr, sizeof mAddr6.sin6_addr) == 0;
default:
assert(0);
}
return false;
}
bool NetworkAddress::isIp(const std::string& str)
{
if (inet_addr(str.c_str()) != INADDR_NONE)
return true;
const char* address = str.c_str();
std::string temp;
if (str.find('[') == 0 && str.find(']') == str.length()-1)
{
temp = str.substr(1, str.length()-2);
address = temp.c_str();
}
sockaddr_in6 addr6;
addr6.sin6_family = AF_INET6;
#ifdef _WIN32
int addrSize = sizeof(addr6);
if (WSAStringToAddressA((char*)address, AF_INET6, NULL, (sockaddr*)&addr6, &addrSize) != 0)
#else
if (!inet_pton(AF_INET6, address, &addr6))
#endif
return false;
return true;
}
bool NetworkAddress::isLAN() const
{
assert(mInitialized);
switch (mAddr4.sin_family)
{
case AF_INET:
{
unsigned char b1 = mAddr4.sin_addr.s_addr & 0xFF;
unsigned char b2 = (mAddr4.sin_addr.s_addr >> 8) & 0xFF;
if (b1 == 192 && b2 == 168)
return true;
if (b1 == 10)
return true;
if (b1 == 172 && (b2 >= 16 && b2 <= 31))
return true;
// Link local addresses are not routable so report them here
if (b1 == 169 && b2 == 254)
return true;
return false;
}
case AF_INET6:
return false;
default:
assert(0);
}
return false;
}
bool NetworkAddress::isLinkLocal() const
{
assert(mInitialized);
switch (mAddr4.sin_family)
{
case AF_INET:
{
unsigned char b1 = mAddr4.sin_addr.s_addr & 0xFF;
unsigned char b2 = (mAddr4.sin_addr.s_addr >> 8) & 0xFF;
// Link local addresses are not routable so report them here
if (b1 == 169 && b2 == 254)
return true;
//if (b1 == 100 && (b2 >= 64 && b2 <= 127))
// return true;
return false;
}
case AF_INET6:
#ifdef WIN32
return (mAddr6.sin6_addr.u.Byte[0] == 0xFE && mAddr6.sin6_addr.u.Byte[1] == 0x80);
#else
return IN6_IS_ADDR_LINKLOCAL(&mAddr6.sin6_addr);
#endif
default:
assert(0);
}
return false;
}
void NetworkAddress::clear()
{
memset(&mAddr6, 0, sizeof(mAddr6));
mInitialized = false;
}
bool NetworkAddress::isEmpty() const
{
return !mInitialized;
}
bool NetworkAddress::isZero() const
{
if (!mInitialized)
return false;
switch (mAddr4.sin_family)
{
case AF_INET:
return mAddr4.sin_addr.s_addr == 0;
case AF_INET6:
#ifdef WIN32
return !mAddr6.sin6_addr.u.Word[0] && !mAddr6.sin6_addr.u.Word[1] &&
!mAddr6.sin6_addr.u.Word[2] && !mAddr6.sin6_addr.u.Word[3] &&
!mAddr6.sin6_addr.u.Word[4] && !mAddr6.sin6_addr.u.Word[5] &&
!mAddr6.sin6_addr.u.Word[6] && !mAddr6.sin6_addr.u.Word[7];
#else
return IN6_IS_ADDR_UNSPECIFIED(&mAddr6.sin6_addr);
#endif
}
return false;
}
bool NetworkAddress::isV4() const
{
return family() == AF_INET;
}
bool NetworkAddress::isV6() const
{
return family() == AF_INET6;
}
bool NetworkAddress::operator == (const NetworkAddress& rhs) const
{
return NetworkAddress::isSame(*this, rhs);
}
bool NetworkAddress::operator != (const NetworkAddress& rhs) const
{
return !NetworkAddress::isSame(*this, rhs);
}
bool NetworkAddress::operator < (const NetworkAddress& rhs) const
{
if (family() != rhs.family())
return family() < rhs.family();
if (port() != rhs.port())
return port() < rhs.port();
switch (family())
{
case AF_INET:
return memcmp(sockaddr4(), rhs.sockaddr4(), sizeof(sockaddr_in)) < 0;
case AF_INET6:
return memcmp(sockaddr6(), rhs.sockaddr6(), sizeof(sockaddr_in6)) < 0;
}
return false;
}
bool NetworkAddress::operator > (const NetworkAddress& rhs) const
{
if (family() != rhs.family())
return family() > rhs.family();
if (port() != rhs.port())
return port() > rhs.port();
switch (family())
{
case AF_INET:
return memcmp(sockaddr4(), rhs.sockaddr4(), sizeof(sockaddr_in)) > 0;
case AF_INET6:
return memcmp(sockaddr6(), rhs.sockaddr6(), sizeof(sockaddr_in6)) > 0;
}
return false;
}
bool NetworkAddress::isPublic() const
{
return !isLAN() && !isLinkLocal() && !isLoopback() && !isEmpty();
}
void NetworkAddress::setRelayed(bool relayed)
{
mRelayed = relayed;
}
bool NetworkAddress::relayed() const
{
return mRelayed;
}
bool NetworkAddress::hasHost(const std::vector<NetworkAddress>& hosts)
{
for (unsigned i=0; i<hosts.size(); i++)
{
const NetworkAddress& a = hosts[i];
if (mAddr4.sin_family != a.mAddr4.sin_family)
continue;
switch (mAddr4.sin_family)
{
case AF_INET:
if (!memcmp(&mAddr4.sin_addr, &a.mAddr4.sin_addr, sizeof(mAddr4.sin_addr)))
return true;
break;
case AF_INET6:
if (!memcmp(&mAddr6.sin6_addr, &a.mAddr6.sin6_addr, sizeof(mAddr6.sin6_addr)))
return true;
break;
}
}
return false;
}
bool NetworkAddress::isSameHost(const NetworkAddress& a1, const NetworkAddress& a2)
{
return (a1.ip() == a2.ip());
}
bool NetworkAddress::isSame(const NetworkAddress& a1, const NetworkAddress& a2)
{
if (!a1.mInitialized || !a2.mInitialized)
return false;
// Compare address families
if (a1.mAddr4.sin_family != a2.mAddr4.sin_family)
return false;
if (a1.mRelayed != a2.mRelayed)
return false;
switch (a1.mAddr4.sin_family)
{
case AF_INET:
return a1.mAddr4.sin_addr.s_addr == a2.mAddr4.sin_addr.s_addr && a1.mAddr4.sin_port == a2.mAddr4.sin_port;
case AF_INET6:
return memcmp(&a1.mAddr6.sin6_addr, &a2.mAddr6.sin6_addr, sizeof(a1.mAddr6.sin6_addr)) == 0 &&
a1.mAddr6.sin6_port == a2.mAddr6.sin6_port;
default:
assert(0);
}
return false;
}
NetworkAddress& NetworkAddress::operator = (const NetworkAddress& src)
{
this->mInitialized = src.mInitialized;
this->mRelayed = src.mRelayed;
this->mAddr6 = src.mAddr6;
return *this;
}