mirror of
https://github.com/Mauler125/r5sdk.git
synced 2025-02-09 19:15:03 +01:00
* Fully rewritten protocol agnostic CNetAdr class * Fully rebuilded legacy CNetAdr class * Fully rebuilded dual-stack CSocketCreator class * New project "netconsole" added (lightweight netconsole for RCON) RCON is still work in progress
441 lines
11 KiB
C++
441 lines
11 KiB
C++
//===========================================================================//
|
|
//
|
|
// Purpose: implementation of the CNetAdr class.
|
|
// --------------------------------------------------------------------------
|
|
//
|
|
// NOTE: This implementation is considered deprecated. I rebuilded this
|
|
// not knowing that the engine supports IPv6 as well. I have fully rewritten
|
|
// this class in 'tier1/NetAdr2.cpp' in modern C++. Please use this instead.
|
|
// This class is for reference material only may some bits in the engine line
|
|
// up with this original 'CNetAdr' implementation.
|
|
//
|
|
//===========================================================================//
|
|
|
|
#include "core/stdafx.h"
|
|
#include "tier1/netadr.h"
|
|
#include "mathlib/swap.h"
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Constructors
|
|
//////////////////////////////////////////////////////////////////////
|
|
netadr_s::netadr_s(void)
|
|
{
|
|
SetIP(0);
|
|
SetPort(0);
|
|
SetType(netadrtype_t::NA_IP);
|
|
}
|
|
netadr_s::netadr_s(std::uint32_t unIP, std::uint16_t usPort)
|
|
{
|
|
SetIP(unIP);
|
|
SetPort(usPort);
|
|
SetType(netadrtype_t::NA_IP);
|
|
}
|
|
netadr_s::netadr_s(const char* pch)
|
|
{
|
|
SetFromString(pch);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
void netadr_t::SetFromSocket(int hSocket)
|
|
{
|
|
Clear();
|
|
type = netadrtype_t::NA_IP;
|
|
|
|
struct sockaddr address{};
|
|
socklen_t namelen = sizeof(address);
|
|
if (getsockname(hSocket, (struct sockaddr*)&address, &namelen) == 0)
|
|
{
|
|
SetFromSockadr(&address);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Compares IP for equality
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::CompareAdr(const netadr_t& a, bool onlyBase) const
|
|
{
|
|
if (a.type != type)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (type == netadrtype_t::NA_LOOPBACK)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (type == netadrtype_t::NA_BROADCAST)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (type == netadrtype_t::NA_IP)
|
|
{
|
|
if (!onlyBase && (port != a.port))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] && a.ip[3] == ip[3])
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Compares Class-B IP for equality
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::CompareClassBAdr(const netadr_t& a) const
|
|
{
|
|
if (a.type != type)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (type == netadrtype_t::NA_LOOPBACK)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (type == netadrtype_t::NA_IP)
|
|
{
|
|
if (a.ip[0] == ip[0] && a.ip[1] == ip[1])
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Compares Class-C IP for equality
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::CompareClassCAdr(const netadr_t& a) const
|
|
{
|
|
if (a.type != type)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (type == netadrtype_t::NA_LOOPBACK)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (type == netadrtype_t::NA_IP)
|
|
{
|
|
if (a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2])
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Convert address to string
|
|
//////////////////////////////////////////////////////////////////////
|
|
const char* netadr_t::ToString(bool onlyBase) const
|
|
{
|
|
// Select a static buffer.
|
|
static char s[4][64]{};
|
|
static int slot = 0;
|
|
int useSlot = (slot++) % 4;
|
|
|
|
// Render into it.
|
|
ToString(s[useSlot], sizeof(s[0]), onlyBase);
|
|
|
|
// Pray the caller uses it before it gets clobbered.
|
|
return s[useSlot];
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Convert address to string
|
|
//////////////////////////////////////////////////////////////////////
|
|
void netadr_t::ToString(char* pchBuffer, std::uint32_t unBufferSize, bool bOnlyBase) const
|
|
{
|
|
if (type == netadrtype_t::NA_LOOPBACK)
|
|
{
|
|
memmove(pchBuffer, "loopback", unBufferSize);
|
|
}
|
|
else if (type == netadrtype_t::NA_BROADCAST)
|
|
{
|
|
memmove(pchBuffer, "broadcast", unBufferSize);
|
|
}
|
|
else if (type == netadrtype_t::NA_IP)
|
|
{
|
|
if (bOnlyBase)
|
|
{
|
|
snprintf(pchBuffer, unBufferSize, "%i.%i.%i.%i", ip[0], ip[1], ip[2], ip[3]);
|
|
}
|
|
else
|
|
{
|
|
snprintf(pchBuffer, unBufferSize, "%i.%i.%i.%i:%i", ip[0], ip[1], ip[2], ip[3], ntohs(port));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
memmove(pchBuffer, "unknown", unBufferSize);
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Clears IP
|
|
//////////////////////////////////////////////////////////////////////
|
|
void netadr_t::Clear(void)
|
|
{
|
|
ip[0] = ip[1] = ip[2] = ip[3] = 0;
|
|
port = 0;
|
|
type = netadrtype_t::NA_NULL;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Sets IP
|
|
//////////////////////////////////////////////////////////////////////
|
|
void netadr_t::SetIP(std::uint8_t b1, std::uint8_t b2, std::uint8_t b3, std::uint8_t b4)
|
|
{
|
|
ip[0] = b1;
|
|
ip[1] = b2;
|
|
ip[2] = b3;
|
|
ip[3] = b4;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Sets IP
|
|
//////////////////////////////////////////////////////////////////////
|
|
void netadr_t::SetIP(std::uint32_t unIP)
|
|
{
|
|
*((std::uint32_t*)ip) = DWordSwapC(unIP);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Sets type
|
|
//////////////////////////////////////////////////////////////////////
|
|
void netadr_t::SetType(netadrtype_t newtype)
|
|
{
|
|
type = newtype;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
netadrtype_t netadr_t::GetType(void) const
|
|
{
|
|
return type;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
std::uint16_t netadr_t::GetPort(void) const
|
|
{
|
|
return WordSwapC(port);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
std::uint32_t netadr_t::GetIPNetworkByteOrder(void) const
|
|
{
|
|
return *(std::uint32_t*)&ip;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
std::uint32_t netadr_t::GetIPHostByteOrder(void) const
|
|
{
|
|
return DWordSwapC(GetIPNetworkByteOrder());
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
void netadr_t::ToSockadr(struct sockaddr* s) const
|
|
{
|
|
memset(s, 0, sizeof(struct sockaddr));
|
|
|
|
if (type == netadrtype_t::NA_BROADCAST)
|
|
{
|
|
((struct sockaddr_in*)s)->sin_family = AF_INET;
|
|
((struct sockaddr_in*)s)->sin_port = port;
|
|
((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_BROADCAST;
|
|
}
|
|
else if (type == netadrtype_t::NA_IP)
|
|
{
|
|
((struct sockaddr_in*)s)->sin_family = AF_INET;
|
|
((struct sockaddr_in*)s)->sin_addr.s_addr = *(int*)&ip;
|
|
((struct sockaddr_in*)s)->sin_port = port;
|
|
}
|
|
else if (type == netadrtype_t::NA_LOOPBACK)
|
|
{
|
|
((struct sockaddr_in*)s)->sin_family = AF_INET;
|
|
((struct sockaddr_in*)s)->sin_port = port;
|
|
((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_LOOPBACK;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::SetFromSockadr(const struct sockaddr* s)
|
|
{
|
|
if (s->sa_family == AF_INET)
|
|
{
|
|
type = netadrtype_t::NA_IP;
|
|
*(int*)&ip = ((struct sockaddr_in*)s)->sin_addr.s_addr;
|
|
port = ((struct sockaddr_in*)s)->sin_port;
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
Clear();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::IsValid(void) const
|
|
{
|
|
return ((port != 0) && (type != netadrtype_t::NA_NULL) &&
|
|
(ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::IsBaseAdrValid(void) const
|
|
{
|
|
return ((type != netadrtype_t::NA_NULL) &&
|
|
(ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0));
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Returns true if we are localhost
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::IsLocalhost(void) const
|
|
{
|
|
return (ip[0] == 127) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 1);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Returns true if we use the loopback buffers
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::IsLoopback(void) const
|
|
{
|
|
return type == netadrtype_t::NA_LOOPBACK;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Check if address is reserved and not routable.
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::IsReservedAdr(void) const
|
|
{
|
|
if (type == netadrtype_t::NA_LOOPBACK)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (type == netadrtype_t::NA_IP)
|
|
{
|
|
if ((ip[0] == 10) || // 10.x.x.x is reserved
|
|
(ip[0] == 127) || // 127.x.x.x
|
|
(ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || // 172.16.x.x - 172.31.x.x
|
|
(ip[0] == 192 && ip[1] >= 168)) // 192.168.x.x
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
void netadr_t::SetPort(std::uint16_t newport)
|
|
{
|
|
port = WordSwapC(newport);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::SetFromString(const char* szIpAdr, bool bUseDNS)
|
|
{
|
|
Clear();
|
|
|
|
if (!szIpAdr)
|
|
{
|
|
Assert(szIpAdr, "Invalid call: 'szIpAdr' was nullptr.");
|
|
return false;
|
|
}
|
|
|
|
type = netadrtype_t::NA_IP;
|
|
|
|
char szAddress[128]{};
|
|
strcpy_s(szAddress, szIpAdr);
|
|
|
|
if (!_strnicmp(szAddress, "loopback", 8))
|
|
{
|
|
char szNewAddress[128]{};
|
|
type = netadrtype_t::NA_LOOPBACK;
|
|
|
|
strcpy_s(szNewAddress, "127.0.0.1");
|
|
strcat_s(szNewAddress, szAddress + 8); // copy anything after "loopback"
|
|
|
|
strcpy_s(szAddress, szNewAddress);
|
|
}
|
|
|
|
if (!_strnicmp(szAddress, "localhost", 9))
|
|
{
|
|
memcpy(szAddress, "127.0.0.1", 9); // Note use of memcpy allows us to keep the colon and rest of string since localhost and 127.0.0.1 are both 9 characters.
|
|
}
|
|
|
|
// IPv4 starts with a number and has a dot.
|
|
if (szAddress[0] >= '0' && szAddress[0] <= '9' && strchr(szAddress, '.'))
|
|
{
|
|
int i0 = -1, i1 = -1, i2 = -1, i3 = -1, n0 = 0; // Initialize port as zero
|
|
int nRes = sscanf_s(szAddress, "%d.%d.%d.%d:%d", &i0, &i1, &i2, &i3, &n0);
|
|
if (
|
|
nRes < 4
|
|
|| i0 < 0 || i0 > 255
|
|
|| i1 < 0 || i1 > 255
|
|
|| i2 < 0 || i2 > 255
|
|
|| i3 < 0 || i3 > 255
|
|
|| n0 < 0 || n0 > 65535
|
|
)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
SetIP(i0, i1, i2, i3);
|
|
SetPort((std::uint16_t)n0);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
bool netadr_t::operator<(const netadr_t& netadr) const
|
|
{
|
|
if (*((std::uint32_t*)netadr.ip) < *((std::uint32_t*)ip))
|
|
{
|
|
return true;
|
|
}
|
|
else if (*((std::uint32_t*)netadr.ip) > *((std::uint32_t*)ip))
|
|
{
|
|
return false;
|
|
}
|
|
return (netadr.port < port);
|
|
}
|