//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include #include #ifdef _WIN32 #include "winsock.h" typedef int socklen_t; #elif POSIX #include #include #include #include #include #include #else #error "implement me" #endif #include "netapi.h" // memdbgon must be the last include file in a .cpp file!!! #include #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); } } }