Counter Strike : Global Offensive Source Code
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.

378 lines
8.1 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // NetAdr.cpp: implementation of the CNetAdr class.
  6. //
  7. //===========================================================================//
  8. #if defined( _WIN32 ) && !defined( _X360 )
  9. #include <windows.h>
  10. #endif
  11. #include "tier0/dbg.h"
  12. #include "netadr.h"
  13. #include "tier1/strtools.h"
  14. #if defined( _WIN32 ) && !defined( _X360 )
  15. #define WIN32_LEAN_AND_MEAN
  16. #include <winsock.h>
  17. typedef int socklen_t;
  18. #elif !defined( _X360 )
  19. #include <netinet/in.h> // ntohs()
  20. #include <netdb.h> // gethostbyname()
  21. #include <sys/socket.h> // getsockname()
  22. #endif
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. //////////////////////////////////////////////////////////////////////
  26. // Construction/Destruction
  27. //////////////////////////////////////////////////////////////////////
  28. bool netadr_t::CompareAdr (const netadr_t &a, bool onlyBase) const
  29. {
  30. if ( a.type != type )
  31. return false;
  32. if ( type == NA_LOOPBACK )
  33. return true;
  34. if ( type == NA_BROADCAST )
  35. return true;
  36. if ( type == NA_IP )
  37. {
  38. if ( !onlyBase && (port != a.port) )
  39. return false;
  40. if ( a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] && a.ip[3] == ip[3] )
  41. return true;
  42. }
  43. return false;
  44. }
  45. bool netadr_t::CompareClassBAdr (const netadr_t &a) const
  46. {
  47. if ( a.type != type )
  48. return false;
  49. if ( type == NA_LOOPBACK )
  50. return true;
  51. if ( type == NA_IP )
  52. {
  53. if (a.ip[0] == ip[0] && a.ip[1] == ip[1] )
  54. return true;
  55. }
  56. return false;
  57. }
  58. bool netadr_t::CompareClassCAdr (const netadr_t &a) const
  59. {
  60. if ( a.type != type )
  61. return false;
  62. if ( type == NA_LOOPBACK )
  63. return true;
  64. if ( type == NA_IP )
  65. {
  66. if (a.ip[0] == ip[0] && a.ip[1] == ip[1] && a.ip[2] == ip[2] )
  67. return true;
  68. }
  69. return false;
  70. }
  71. // reserved addresses are not routeable, so they can all be used in a LAN game
  72. bool netadr_t::IsReservedAdr () const
  73. {
  74. if ( type == NA_LOOPBACK )
  75. return true;
  76. if ( type == NA_IP )
  77. {
  78. if ( (ip[0] == 10) || // 10.x.x.x is reserved
  79. (ip[0] == 127) || // 127.x.x.x
  80. (ip[0] == 172 && ip[1] >= 16 && ip[1] <= 31) || // 172.16.x.x - 172.31.x.x
  81. (ip[0] == 192 && ip[1] >= 168) ) // 192.168.x.x
  82. return true;
  83. }
  84. return false;
  85. }
  86. const char * netadr_t::ToString( bool onlyBase ) const
  87. {
  88. // Select a static buffer
  89. static char s[4][64];
  90. static int slot = 0;
  91. int useSlot = ( slot++ ) % 4;
  92. // Render into it
  93. ToString( s[useSlot], sizeof(s[0]), onlyBase );
  94. // Pray the caller uses it before it gets clobbered
  95. return s[useSlot];
  96. }
  97. void netadr_t::ToString( char *pchBuffer, uint32 unBufferSize, bool onlyBase ) const
  98. {
  99. if (type == NA_LOOPBACK)
  100. {
  101. V_strncpy( pchBuffer, "loopback", unBufferSize );
  102. }
  103. else if (type == NA_BROADCAST)
  104. {
  105. V_strncpy( pchBuffer, "broadcast", unBufferSize );
  106. }
  107. else if (type == NA_IP)
  108. {
  109. if ( onlyBase )
  110. {
  111. V_snprintf( pchBuffer, unBufferSize, "%i.%i.%i.%i", ip[0], ip[1], ip[2], ip[3]);
  112. }
  113. else
  114. {
  115. V_snprintf( pchBuffer, unBufferSize, "%i.%i.%i.%i:%i", ip[0], ip[1], ip[2], ip[3], ntohs(port));
  116. }
  117. }
  118. else
  119. {
  120. V_strncpy( pchBuffer, "unknown", unBufferSize );
  121. }
  122. }
  123. bool netadr_t::IsLocalhost() const
  124. {
  125. // are we 127.0.0.1 ?
  126. return (ip[0] == 127) && (ip[1] == 0) && (ip[2] == 0) && (ip[3] == 1);
  127. }
  128. bool netadr_t::IsLoopback() const
  129. {
  130. // are we useding engine loopback buffers
  131. return type == NA_LOOPBACK;
  132. }
  133. void netadr_t::Clear()
  134. {
  135. ip[0] = ip[1] = ip[2] = ip[3] = 0;
  136. port = 0;
  137. type = NA_NULL;
  138. }
  139. void netadr_t::SetIP(uint8 b1, uint8 b2, uint8 b3, uint8 b4)
  140. {
  141. ip[0] = b1;
  142. ip[1] = b2;
  143. ip[2] = b3;
  144. ip[3] = b4;
  145. }
  146. void netadr_t::SetIP(uint unIP)
  147. {
  148. *((uint*)ip) = BigLong( unIP );
  149. }
  150. void netadr_t::SetType(netadrtype_t newtype)
  151. {
  152. type = newtype;
  153. }
  154. netadrtype_t netadr_t::GetType() const
  155. {
  156. return type;
  157. }
  158. unsigned short netadr_t::GetPort() const
  159. {
  160. return BigShort( port );
  161. }
  162. unsigned int netadr_t::GetIPNetworkByteOrder() const
  163. {
  164. return *(unsigned int *)&ip;
  165. }
  166. unsigned int netadr_t::GetIPHostByteOrder() const
  167. {
  168. return BigDWord( GetIPNetworkByteOrder() );
  169. }
  170. void netadr_t::ToSockadr (struct sockaddr * s) const
  171. {
  172. Q_memset ( s, 0, sizeof(struct sockaddr));
  173. if (type == NA_BROADCAST)
  174. {
  175. ((struct sockaddr_in*)s)->sin_family = AF_INET;
  176. ((struct sockaddr_in*)s)->sin_port = port;
  177. ((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_BROADCAST;
  178. }
  179. else if (type == NA_IP)
  180. {
  181. ((struct sockaddr_in*)s)->sin_family = AF_INET;
  182. ((struct sockaddr_in*)s)->sin_addr.s_addr = *(int *)&ip;
  183. ((struct sockaddr_in*)s)->sin_port = port;
  184. }
  185. else if (type == NA_LOOPBACK )
  186. {
  187. ((struct sockaddr_in*)s)->sin_family = AF_INET;
  188. ((struct sockaddr_in*)s)->sin_port = port;
  189. ((struct sockaddr_in*)s)->sin_addr.s_addr = INADDR_LOOPBACK ;
  190. }
  191. }
  192. bool netadr_t::SetFromSockadr(const struct sockaddr * s)
  193. {
  194. if (s->sa_family == AF_INET)
  195. {
  196. type = NA_IP;
  197. *(int *)&ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
  198. port = ((struct sockaddr_in *)s)->sin_port;
  199. return true;
  200. }
  201. else
  202. {
  203. Clear();
  204. return false;
  205. }
  206. }
  207. bool netadr_t::IsValid() const
  208. {
  209. return ( (port !=0 ) && (type != NA_NULL) &&
  210. ( ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0 ) );
  211. }
  212. bool netadr_t::IsBaseAdrValid() const
  213. {
  214. return ( (type != NA_NULL) &&
  215. ( ip[0] != 0 || ip[1] != 0 || ip[2] != 0 || ip[3] != 0 ) );
  216. }
  217. #ifdef _WIN32
  218. #undef SetPort // get around stupid WINSPOOL.H macro
  219. #endif
  220. void netadr_t::SetPort(unsigned short newport)
  221. {
  222. port = BigShort( newport );
  223. }
  224. bool netadr_t::SetFromString( const char *pch, bool bUseDNS )
  225. {
  226. Clear();
  227. type = NA_IP;
  228. Assert( pch ); // invalid to call this with NULL pointer; fix your code bug!
  229. if ( !pch ) // but let's not crash
  230. return false;
  231. char address[ 128 ];
  232. V_strcpy_safe( address, pch );
  233. if ( !V_strnicmp( address, "loopback", 8 ) )
  234. {
  235. char newaddress[ 128 ];
  236. type = NA_LOOPBACK;
  237. V_strcpy_safe( newaddress, "127.0.0.1" );
  238. V_strcat_safe( newaddress, address + 8 ); // copy anything after "loopback"
  239. V_strcpy_safe( address, newaddress );
  240. }
  241. if ( !V_strnicmp( address, "localhost", 9 ) )
  242. {
  243. V_memcpy( address, "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.
  244. }
  245. // Starts with a number and has a dot
  246. if ( address[0] >= '0' &&
  247. address[0] <= '9' &&
  248. strchr( address, '.' ) )
  249. {
  250. int n1 = -1, n2 = -1, n3 = -1, n4 = -1, n5 = 0; // set port to 0 if we don't parse one
  251. int nRes = sscanf( address, "%d.%d.%d.%d:%d", &n1, &n2, &n3, &n4, &n5 );
  252. if (
  253. nRes < 4
  254. || n1 < 0 || n1 > 255
  255. || n2 < 0 || n2 > 255
  256. || n3 < 0 || n3 > 255
  257. || n4 < 0 || n4 > 255
  258. || n5 < 0 || n5 > 65535
  259. )
  260. return false;
  261. SetIP( n1, n2, n3, n4 );
  262. SetPort( ( uint16 ) n5 );
  263. return true;
  264. }
  265. if ( bUseDNS )
  266. {
  267. // X360TBD:
  268. // dgoodenough - since this is skipped on X360, seems reasonable to skip as well on PS3
  269. // PS3_BUILDFIX
  270. // FIXME - Leap of faith, this works without asserting on X360, so I assume it will on PS3
  271. #if !defined( _X360 ) && !defined( _PS3 )
  272. // Null out the colon if there is one
  273. char *pchColon = strchr( address, ':' );
  274. if ( pchColon )
  275. {
  276. *pchColon = 0;
  277. }
  278. // DNS it base name
  279. struct hostent *h = gethostbyname( address );
  280. if ( !h )
  281. return false;
  282. SetIP( ntohl( *(int *)h->h_addr_list[0] ) );
  283. // Set Port to whatever was specified after the colon
  284. if ( pchColon )
  285. {
  286. SetPort( V_atoi( ++pchColon ) );
  287. }
  288. return true;
  289. #else
  290. Assert( 0 );
  291. return false;
  292. #endif
  293. }
  294. return false;
  295. }
  296. bool netadr_t::operator<(const netadr_t &netadr) const
  297. {
  298. if ( *((uint *)netadr.ip) < *((uint *)ip) )
  299. return true;
  300. else if ( *((uint *)netadr.ip) > *((uint *)ip) )
  301. return false;
  302. return ( netadr.port < port );
  303. }
  304. void netadr_t::SetFromSocket( int hSocket )
  305. {
  306. // dgoodenough - since this is skipped on X360, seems reasonable to skip as well on PS3
  307. // PS3_BUILDFIX
  308. // FIXME - Leap of faith, this works without asserting on X360, so I assume it will on PS3
  309. #if !defined( _X360 ) && !defined( _PS3 )
  310. Clear();
  311. type = NA_IP;
  312. struct sockaddr address;
  313. socklen_t namelen = sizeof(address);
  314. if ( getsockname( hSocket, (struct sockaddr *)&address, &namelen) == 0 )
  315. {
  316. SetFromSockadr( &address );
  317. }
  318. #else
  319. Assert(0);
  320. #endif
  321. }