Team Fortress 2 Source Code as on 22/4/2020
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

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #ifdef _WIN32
  10. #include "winsock.h"
  11. typedef int socklen_t;
  12. #elif POSIX
  13. #include <sys/types.h>
  14. #include <sys/socket.h>
  15. #include <netinet/in.h>
  16. #include <arpa/inet.h>
  17. #include <netdb.h>
  18. #include <unistd.h>
  19. #else
  20. #error "implement me"
  21. #endif
  22. #include "netapi.h"
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include <tier0/memdbgon.h>
  25. #pragma warning(disable: 4706) // warning C4706: assignment within conditional expression
  26. //-----------------------------------------------------------------------------
  27. // Purpose: Implements INetAPI
  28. //-----------------------------------------------------------------------------
  29. class CNetAPI : public INetAPI
  30. {
  31. public:
  32. virtual void NetAdrToSockAddr( netadr_t *a, struct sockaddr *s );
  33. virtual void SockAddrToNetAdr( struct sockaddr *s, netadr_t *a );
  34. virtual char *AdrToString( netadr_t *a );
  35. virtual bool StringToAdr( const char *s, netadr_t *a );
  36. virtual void GetSocketAddress( int socket, netadr_t *a );
  37. virtual bool CompareAdr( netadr_t *a, netadr_t *b );
  38. virtual void GetLocalIP(netadr_t *a);
  39. };
  40. // Expose interface
  41. static CNetAPI g_NetAPI;
  42. INetAPI *net = ( INetAPI * )&g_NetAPI;
  43. //-----------------------------------------------------------------------------
  44. // Purpose:
  45. // Input : *a -
  46. // *s -
  47. //-----------------------------------------------------------------------------
  48. void CNetAPI::NetAdrToSockAddr (netadr_t *a, struct sockaddr *s)
  49. {
  50. memset (s, 0, sizeof(*s));
  51. if (a->type == NA_BROADCAST)
  52. {
  53. ((struct sockaddr_in *)s)->sin_family = AF_INET;
  54. ((struct sockaddr_in *)s)->sin_port = a->port;
  55. ((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
  56. }
  57. else if (a->type == NA_IP)
  58. {
  59. ((struct sockaddr_in *)s)->sin_family = AF_INET;
  60. ((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
  61. ((struct sockaddr_in *)s)->sin_port = a->port;
  62. }
  63. }
  64. //-----------------------------------------------------------------------------
  65. // Purpose:
  66. // Input : *s -
  67. // *a -
  68. //-----------------------------------------------------------------------------
  69. void CNetAPI::SockAddrToNetAdr( struct sockaddr *s, netadr_t *a )
  70. {
  71. if (s->sa_family == AF_INET)
  72. {
  73. a->type = NA_IP;
  74. *(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
  75. a->port = ((struct sockaddr_in *)s)->sin_port;
  76. }
  77. }
  78. //-----------------------------------------------------------------------------
  79. // Purpose:
  80. // Input : *a -
  81. // Output : char
  82. //-----------------------------------------------------------------------------
  83. char *CNetAPI::AdrToString( netadr_t *a )
  84. {
  85. static char s[64];
  86. memset(s, 0, 64);
  87. if ( a )
  88. {
  89. if ( a->type == NA_LOOPBACK )
  90. {
  91. sprintf (s, "loopback");
  92. }
  93. else if ( a->type == NA_IP )
  94. {
  95. sprintf(s, "%i.%i.%i.%i:%i", a->ip[0], a->ip[1], a->ip[2], a->ip[3], ntohs( a->port ) );
  96. }
  97. }
  98. return s;
  99. }
  100. //-----------------------------------------------------------------------------
  101. // Purpose:
  102. // Input : *s -
  103. // *sadr -
  104. // Output : static bool
  105. //-----------------------------------------------------------------------------
  106. static bool StringToSockaddr( const char *s, struct sockaddr *sadr )
  107. {
  108. struct hostent *h;
  109. char *colon;
  110. char copy[128];
  111. struct sockaddr_in *p;
  112. memset (sadr, 0, sizeof(*sadr));
  113. p = ( struct sockaddr_in * )sadr;
  114. p->sin_family = AF_INET;
  115. p->sin_port = 0;
  116. strcpy (copy, s);
  117. // strip off a trailing :port if present
  118. for ( colon = copy ; *colon ; colon++ )
  119. {
  120. if (*colon == ':')
  121. {
  122. // terminate
  123. *colon = 0;
  124. // Start at next character
  125. p->sin_port = htons( ( short )atoi( colon + 1 ) );
  126. }
  127. }
  128. // Numeric IP, no DNS
  129. if ( copy[0] >= '0' && copy[0] <= '9' && strstr( copy, "." ) )
  130. {
  131. *(int *)&p->sin_addr = inet_addr( copy );
  132. }
  133. else
  134. {
  135. // DNS it
  136. if ( !( h = gethostbyname( copy ) ) )
  137. {
  138. return false;
  139. }
  140. // Use first result
  141. *(int *)&p->sin_addr = *(int *)h->h_addr_list[0];
  142. }
  143. return true;
  144. }
  145. //-----------------------------------------------------------------------------
  146. // Purpose:
  147. // Input : *s -
  148. // *a -
  149. // Output : Returns true on success, false on failure.
  150. //-----------------------------------------------------------------------------
  151. bool CNetAPI::StringToAdr( const char *s, netadr_t *a )
  152. {
  153. struct sockaddr sadr;
  154. if ( !strcmp ( s, "localhost" ) )
  155. {
  156. memset ( a, 0, sizeof( *a ) );
  157. a->type = NA_LOOPBACK;
  158. return true;
  159. }
  160. if ( !StringToSockaddr (s, &sadr) )
  161. {
  162. return false;
  163. }
  164. SockAddrToNetAdr( &sadr, a );
  165. return true;
  166. }
  167. //-----------------------------------------------------------------------------
  168. // Purpose: Lookup the IP address for the specified IP socket
  169. // Input : socket -
  170. // *a -
  171. //-----------------------------------------------------------------------------
  172. void CNetAPI::GetSocketAddress( int socket, netadr_t *a )
  173. {
  174. char buff[512];
  175. struct sockaddr_in address;
  176. int namelen;
  177. // int net_error = 0;
  178. memset( a, 0, sizeof( *a ) );
  179. gethostname(buff, 512);
  180. // Ensure that it doesn't overrun the buffer
  181. buff[512-1] = 0;
  182. StringToAdr(buff, a );
  183. namelen = sizeof(address);
  184. if ( getsockname( socket, (struct sockaddr *)&address, (socklen_t *)&namelen) == 0 )
  185. {
  186. a->port = address.sin_port;
  187. }
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Purpose: Full IP address compare
  191. // Input : *a -
  192. // *b -
  193. // Output : Returns true on success, false on failure.
  194. //-----------------------------------------------------------------------------
  195. bool CNetAPI::CompareAdr( netadr_t *a, netadr_t *b )
  196. {
  197. if ( a->type != b->type )
  198. {
  199. return false;
  200. }
  201. if ( a->type == NA_LOOPBACK )
  202. {
  203. return true;
  204. }
  205. if ( a->type == NA_IP &&
  206. a->ip[0] == b->ip[0] &&
  207. a->ip[1] == b->ip[1] &&
  208. a->ip[2] == b->ip[2] &&
  209. a->ip[3] == b->ip[3] &&
  210. a->port == b->port )
  211. {
  212. return true;
  213. }
  214. return false;
  215. }
  216. //-----------------------------------------------------------------------------
  217. // Purpose: Full IP address compare
  218. // Input : *a -
  219. // *b -
  220. // Output : Returns true on success, false on failure.
  221. //-----------------------------------------------------------------------------
  222. void CNetAPI::GetLocalIP(netadr_t *a)
  223. {
  224. char s[64];
  225. if(!::gethostname(s,64))
  226. {
  227. struct hostent *localip = ::gethostbyname(s);
  228. if(localip)
  229. {
  230. a->type=NA_IP;
  231. a->port=0;
  232. memcpy(a->ip,localip->h_addr_list[0],4);
  233. }
  234. }
  235. }