You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
272 lines
6.4 KiB
272 lines
6.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
// $NoKeywords: $ |
|
//=============================================================================// |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#ifdef _WIN32 |
|
#include "winsock.h" |
|
typedef int socklen_t; |
|
#elif POSIX |
|
#include <sys/types.h> |
|
#include <sys/socket.h> |
|
#include <netinet/in.h> |
|
#include <arpa/inet.h> |
|
#include <netdb.h> |
|
#include <unistd.h> |
|
|
|
#else |
|
#error "implement me" |
|
#endif |
|
|
|
#include "netapi.h" |
|
// memdbgon must be the last include file in a .cpp file!!! |
|
#include <tier0/memdbgon.h> |
|
#pragma warning(disable: 4706) // warning C4706: assignment within conditional expression |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Implements INetAPI |
|
//----------------------------------------------------------------------------- |
|
class CNetAPI : public INetAPI |
|
{ |
|
public: |
|
virtual void NetAdrToSockAddr( netadr_t *a, struct sockaddr *s ); |
|
virtual void SockAddrToNetAdr( struct sockaddr *s, netadr_t *a ); |
|
|
|
virtual char *AdrToString( netadr_t *a ); |
|
virtual bool StringToAdr( const char *s, netadr_t *a ); |
|
|
|
virtual void GetSocketAddress( int socket, netadr_t *a ); |
|
|
|
virtual bool CompareAdr( netadr_t *a, netadr_t *b ); |
|
|
|
virtual void GetLocalIP(netadr_t *a); |
|
}; |
|
|
|
// Expose interface |
|
static CNetAPI g_NetAPI; |
|
INetAPI *net = ( INetAPI * )&g_NetAPI; |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *a - |
|
// *s - |
|
//----------------------------------------------------------------------------- |
|
void CNetAPI::NetAdrToSockAddr (netadr_t *a, struct sockaddr *s) |
|
{ |
|
memset (s, 0, sizeof(*s)); |
|
|
|
if (a->type == NA_BROADCAST) |
|
{ |
|
((struct sockaddr_in *)s)->sin_family = AF_INET; |
|
((struct sockaddr_in *)s)->sin_port = a->port; |
|
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST; |
|
} |
|
else if (a->type == NA_IP) |
|
{ |
|
((struct sockaddr_in *)s)->sin_family = AF_INET; |
|
((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip; |
|
((struct sockaddr_in *)s)->sin_port = a->port; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *s - |
|
// *a - |
|
//----------------------------------------------------------------------------- |
|
void CNetAPI::SockAddrToNetAdr( struct sockaddr *s, netadr_t *a ) |
|
{ |
|
if (s->sa_family == AF_INET) |
|
{ |
|
a->type = NA_IP; |
|
*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr; |
|
a->port = ((struct sockaddr_in *)s)->sin_port; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *a - |
|
// Output : char |
|
//----------------------------------------------------------------------------- |
|
char *CNetAPI::AdrToString( netadr_t *a ) |
|
{ |
|
static char s[64]; |
|
|
|
memset(s, 0, 64); |
|
|
|
if ( a ) |
|
{ |
|
if ( a->type == NA_LOOPBACK ) |
|
{ |
|
sprintf (s, "loopback"); |
|
} |
|
else if ( a->type == NA_IP ) |
|
{ |
|
sprintf(s, "%i.%i.%i.%i:%i", a->ip[0], a->ip[1], a->ip[2], a->ip[3], ntohs( a->port ) ); |
|
} |
|
} |
|
return s; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *s - |
|
// *sadr - |
|
// Output : static bool |
|
//----------------------------------------------------------------------------- |
|
static bool StringToSockaddr( const char *s, struct sockaddr *sadr ) |
|
{ |
|
struct hostent *h; |
|
char *colon; |
|
char copy[128]; |
|
struct sockaddr_in *p; |
|
|
|
memset (sadr, 0, sizeof(*sadr)); |
|
|
|
p = ( struct sockaddr_in * )sadr; |
|
p->sin_family = AF_INET; |
|
p->sin_port = 0; |
|
|
|
strcpy (copy, s); |
|
|
|
// strip off a trailing :port if present |
|
for ( colon = copy ; *colon ; colon++ ) |
|
{ |
|
if (*colon == ':') |
|
{ |
|
// terminate |
|
*colon = 0; |
|
// Start at next character |
|
p->sin_port = htons( ( short )atoi( colon + 1 ) ); |
|
} |
|
} |
|
|
|
// Numeric IP, no DNS |
|
if ( copy[0] >= '0' && copy[0] <= '9' && strstr( copy, "." ) ) |
|
{ |
|
*(int *)&p->sin_addr = inet_addr( copy ); |
|
} |
|
else |
|
{ |
|
// DNS it |
|
if ( !( h = gethostbyname( copy ) ) ) |
|
{ |
|
return false; |
|
} |
|
// Use first result |
|
*(int *)&p->sin_addr = *(int *)h->h_addr_list[0]; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
// Input : *s - |
|
// *a - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CNetAPI::StringToAdr( const char *s, netadr_t *a ) |
|
{ |
|
struct sockaddr sadr; |
|
|
|
if ( !strcmp ( s, "localhost" ) ) |
|
{ |
|
memset ( a, 0, sizeof( *a ) ); |
|
a->type = NA_LOOPBACK; |
|
return true; |
|
} |
|
|
|
if ( !StringToSockaddr (s, &sadr) ) |
|
{ |
|
return false; |
|
} |
|
|
|
SockAddrToNetAdr( &sadr, a ); |
|
|
|
return true; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Lookup the IP address for the specified IP socket |
|
// Input : socket - |
|
// *a - |
|
//----------------------------------------------------------------------------- |
|
void CNetAPI::GetSocketAddress( int socket, netadr_t *a ) |
|
{ |
|
char buff[512]; |
|
struct sockaddr_in address; |
|
int namelen; |
|
// int net_error = 0; |
|
|
|
memset( a, 0, sizeof( *a ) ); |
|
gethostname(buff, 512); |
|
// Ensure that it doesn't overrun the buffer |
|
buff[512-1] = 0; |
|
|
|
StringToAdr(buff, a ); |
|
|
|
namelen = sizeof(address); |
|
if ( getsockname( socket, (struct sockaddr *)&address, (socklen_t *)&namelen) == 0 ) |
|
{ |
|
a->port = address.sin_port; |
|
} |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Full IP address compare |
|
// Input : *a - |
|
// *b - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
bool CNetAPI::CompareAdr( netadr_t *a, netadr_t *b ) |
|
{ |
|
if ( a->type != b->type ) |
|
{ |
|
return false; |
|
} |
|
|
|
if ( a->type == NA_LOOPBACK ) |
|
{ |
|
return true; |
|
} |
|
|
|
if ( a->type == NA_IP && |
|
a->ip[0] == b->ip[0] && |
|
a->ip[1] == b->ip[1] && |
|
a->ip[2] == b->ip[2] && |
|
a->ip[3] == b->ip[3] && |
|
a->port == b->port ) |
|
{ |
|
return true; |
|
} |
|
|
|
return false; |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Full IP address compare |
|
// Input : *a - |
|
// *b - |
|
// Output : Returns true on success, false on failure. |
|
//----------------------------------------------------------------------------- |
|
|
|
void CNetAPI::GetLocalIP(netadr_t *a) |
|
{ |
|
char s[64]; |
|
|
|
if(!::gethostname(s,64)) |
|
{ |
|
struct hostent *localip = ::gethostbyname(s); |
|
if(localip) |
|
{ |
|
a->type=NA_IP; |
|
a->port=0; |
|
memcpy(a->ip,localip->h_addr_list[0],4); |
|
} |
|
} |
|
}
|
|
|