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.

610 lines
12 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #pragma warning (disable:4127)
  9. #include <winsock2.h>
  10. #include <ws2tcpip.h>
  11. #pragma warning (default:4127)
  12. #include "iphelpers.h"
  13. #include "basetypes.h"
  14. #include <assert.h>
  15. #include "utllinkedlist.h"
  16. #include "utlvector.h"
  17. #include "tier1/strtools.h"
  18. // This automatically calls WSAStartup for the app at startup.
  19. class CIPStarter
  20. {
  21. public:
  22. CIPStarter()
  23. {
  24. WSADATA wsaData;
  25. WSAStartup( WINSOCK_VERSION, &wsaData );
  26. }
  27. };
  28. static CIPStarter g_Starter;
  29. unsigned long SampleMilliseconds()
  30. {
  31. CCycleCount cnt;
  32. cnt.Sample();
  33. return cnt.GetMilliseconds();
  34. }
  35. // ------------------------------------------------------------------------------------------ //
  36. // CChunkWalker.
  37. // ------------------------------------------------------------------------------------------ //
  38. CChunkWalker::CChunkWalker( void const * const *pChunks, const int *pChunkLengths, int nChunks )
  39. {
  40. m_TotalLength = 0;
  41. for ( int i=0; i < nChunks; i++ )
  42. m_TotalLength += pChunkLengths[i];
  43. m_iCurChunk = 0;
  44. m_iCurChunkPos = 0;
  45. m_pChunks = pChunks;
  46. m_pChunkLengths = pChunkLengths;
  47. m_nChunks = nChunks;
  48. }
  49. int CChunkWalker::GetTotalLength() const
  50. {
  51. return m_TotalLength;
  52. }
  53. void CChunkWalker::CopyTo( void *pOut, int nBytes )
  54. {
  55. unsigned char *pOutPos = (unsigned char*)pOut;
  56. int nBytesLeft = nBytes;
  57. while ( nBytesLeft > 0 )
  58. {
  59. int toCopy = nBytesLeft;
  60. int curChunkLen = m_pChunkLengths[m_iCurChunk];
  61. int amtLeft = curChunkLen - m_iCurChunkPos;
  62. if ( nBytesLeft > amtLeft )
  63. {
  64. toCopy = amtLeft;
  65. }
  66. unsigned char *pCurChunkData = (unsigned char*)m_pChunks[m_iCurChunk];
  67. memcpy( pOutPos, &pCurChunkData[m_iCurChunkPos], toCopy );
  68. nBytesLeft -= toCopy;
  69. pOutPos += toCopy;
  70. // Slide up to the next chunk if we're done with the one we're on.
  71. m_iCurChunkPos += toCopy;
  72. assert( m_iCurChunkPos <= curChunkLen );
  73. if ( m_iCurChunkPos == curChunkLen )
  74. {
  75. ++m_iCurChunk;
  76. m_iCurChunkPos = 0;
  77. if ( m_iCurChunk == m_nChunks )
  78. {
  79. assert( nBytesLeft == 0 );
  80. }
  81. }
  82. }
  83. }
  84. // ------------------------------------------------------------------------------------------ //
  85. // CWaitTimer
  86. // ------------------------------------------------------------------------------------------ //
  87. bool g_bForceWaitTimers = false;
  88. CWaitTimer::CWaitTimer( double flSeconds )
  89. {
  90. m_StartTime = SampleMilliseconds();
  91. m_WaitMS = (unsigned long)( flSeconds * 1000.0 );
  92. }
  93. bool CWaitTimer::ShouldKeepWaiting()
  94. {
  95. if ( m_WaitMS == 0 )
  96. {
  97. return false;
  98. }
  99. else
  100. {
  101. return ( SampleMilliseconds() - m_StartTime ) <= m_WaitMS || g_bForceWaitTimers;
  102. }
  103. }
  104. // ------------------------------------------------------------------------------------------ //
  105. // CIPAddr.
  106. // ------------------------------------------------------------------------------------------ //
  107. CIPAddr::CIPAddr()
  108. {
  109. Init( 0, 0, 0, 0, 0 );
  110. }
  111. CIPAddr::CIPAddr( const int inputIP[4], const int inputPort )
  112. {
  113. Init( inputIP[0], inputIP[1], inputIP[2], inputIP[3], inputPort );
  114. }
  115. CIPAddr::CIPAddr( int ip0, int ip1, int ip2, int ip3, int ipPort )
  116. {
  117. Init( ip0, ip1, ip2, ip3, ipPort );
  118. }
  119. void CIPAddr::Init( int ip0, int ip1, int ip2, int ip3, int ipPort )
  120. {
  121. ip[0] = (unsigned char)ip0;
  122. ip[1] = (unsigned char)ip1;
  123. ip[2] = (unsigned char)ip2;
  124. ip[3] = (unsigned char)ip3;
  125. port = (unsigned short)ipPort;
  126. }
  127. bool CIPAddr::operator==( const CIPAddr &o ) const
  128. {
  129. return ip[0] == o.ip[0] && ip[1] == o.ip[1] && ip[2] == o.ip[2] && ip[3] == o.ip[3] && port == o.port;
  130. }
  131. bool CIPAddr::operator!=( const CIPAddr &o ) const
  132. {
  133. return !( *this == o );
  134. }
  135. void CIPAddr::SetupLocal( int inPort )
  136. {
  137. ip[0] = 0x7f;
  138. ip[1] = 0;
  139. ip[2] = 0;
  140. ip[3] = 1;
  141. port = inPort;
  142. }
  143. // ------------------------------------------------------------------------------------------ //
  144. // Static helpers.
  145. // ------------------------------------------------------------------------------------------ //
  146. static double IP_FloatTime()
  147. {
  148. CCycleCount cnt;
  149. cnt.Sample();
  150. return cnt.GetSeconds();
  151. }
  152. TIMEVAL SetupTimeVal( double flTimeout )
  153. {
  154. TIMEVAL timeVal;
  155. timeVal.tv_sec = (long)flTimeout;
  156. timeVal.tv_usec = (long)( (flTimeout - (long)flTimeout) * 1000.0 );
  157. return timeVal;
  158. }
  159. // Convert a CIPAddr to a sockaddr_in.
  160. void IPAddrToInAddr( const CIPAddr *pIn, in_addr *pOut )
  161. {
  162. u_char *p = (u_char*)pOut;
  163. p[0] = pIn->ip[0];
  164. p[1] = pIn->ip[1];
  165. p[2] = pIn->ip[2];
  166. p[3] = pIn->ip[3];
  167. }
  168. // Convert a CIPAddr to a sockaddr_in.
  169. void IPAddrToSockAddr( const CIPAddr *pIn, struct sockaddr_in *pOut )
  170. {
  171. memset( pOut, 0, sizeof(*pOut) );
  172. pOut->sin_family = AF_INET;
  173. pOut->sin_port = htons( pIn->port );
  174. IPAddrToInAddr( pIn, &pOut->sin_addr );
  175. }
  176. // Convert a CIPAddr to a sockaddr_in.
  177. void SockAddrToIPAddr( const struct sockaddr_in *pIn, CIPAddr *pOut )
  178. {
  179. const u_char *p = (const u_char*)&pIn->sin_addr;
  180. pOut->ip[0] = p[0];
  181. pOut->ip[1] = p[1];
  182. pOut->ip[2] = p[2];
  183. pOut->ip[3] = p[3];
  184. pOut->port = ntohs( pIn->sin_port );
  185. }
  186. class CIPSocket : public ISocket
  187. {
  188. public:
  189. CIPSocket()
  190. {
  191. m_Socket = INVALID_SOCKET;
  192. m_bSetupToBroadcast = false;
  193. }
  194. virtual ~CIPSocket()
  195. {
  196. Term();
  197. }
  198. // ISocket implementation.
  199. public:
  200. virtual void Release()
  201. {
  202. delete this;
  203. }
  204. virtual bool CreateSocket()
  205. {
  206. // Clear any old socket we had around.
  207. Term();
  208. // Create a socket to send and receive through.
  209. SOCKET sock = socket( AF_INET, SOCK_DGRAM, IPPROTO_IP );
  210. if ( sock == INVALID_SOCKET )
  211. {
  212. Assert( false );
  213. return false;
  214. }
  215. // Nonblocking please..
  216. int status;
  217. DWORD val = 1;
  218. status = ioctlsocket( sock, FIONBIO, &val );
  219. if ( status != 0 )
  220. {
  221. assert( false );
  222. closesocket( sock );
  223. return false;
  224. }
  225. m_Socket = sock;
  226. return true;
  227. }
  228. // Called after we have a socket.
  229. virtual bool BindPart2( const CIPAddr *pAddr )
  230. {
  231. Assert( m_Socket != INVALID_SOCKET );
  232. // bind to it!
  233. sockaddr_in addr;
  234. IPAddrToSockAddr( pAddr, &addr );
  235. int status = bind( m_Socket, (sockaddr*)&addr, sizeof(addr) );
  236. if ( status == 0 )
  237. {
  238. return true;
  239. }
  240. else
  241. {
  242. Term();
  243. return false;
  244. }
  245. }
  246. virtual bool Bind( const CIPAddr *pAddr )
  247. {
  248. if ( !CreateSocket() )
  249. return false;
  250. return BindPart2( pAddr );
  251. }
  252. virtual bool BindToAny( const unsigned short port )
  253. {
  254. // (INADDR_ANY)
  255. CIPAddr addr;
  256. addr.ip[0] = addr.ip[1] = addr.ip[2] = addr.ip[3] = 0;
  257. addr.port = port;
  258. return Bind( &addr );
  259. }
  260. virtual bool ListenToMulticastStream( const CIPAddr &addr, const CIPAddr &localInterface )
  261. {
  262. ip_mreq mr;
  263. IPAddrToInAddr( &addr, &mr.imr_multiaddr );
  264. IPAddrToInAddr( &localInterface, &mr.imr_interface );
  265. // This helps a lot if the stream is sending really fast.
  266. int rcvBuf = 1024*1024*2;
  267. setsockopt( m_Socket, SOL_SOCKET, SO_RCVBUF, (char*)&rcvBuf, sizeof( rcvBuf ) );
  268. if ( setsockopt( m_Socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mr, sizeof( mr ) ) == 0 )
  269. {
  270. // Remember this so we do IP_DEL_MEMBERSHIP on shutdown.
  271. m_bMulticastGroupMembership = true;
  272. m_MulticastGroupMREQ = mr;
  273. return true;
  274. }
  275. else
  276. {
  277. return false;
  278. }
  279. }
  280. virtual bool Broadcast( const void *pData, const int len, const unsigned short port )
  281. {
  282. assert( m_Socket != INVALID_SOCKET );
  283. // Make sure we're setup to broadcast.
  284. if ( !m_bSetupToBroadcast )
  285. {
  286. BOOL bBroadcast = true;
  287. if ( setsockopt( m_Socket, SOL_SOCKET, SO_BROADCAST, (char*)&bBroadcast, sizeof( bBroadcast ) ) != 0 )
  288. {
  289. assert( false );
  290. return false;
  291. }
  292. m_bSetupToBroadcast = true;
  293. }
  294. CIPAddr addr;
  295. addr.ip[0] = addr.ip[1] = addr.ip[2] = addr.ip[3] = 0xFF;
  296. addr.port = port;
  297. return SendTo( &addr, pData, len );
  298. }
  299. virtual bool SendTo( const CIPAddr *pAddr, const void *pData, const int len )
  300. {
  301. return SendChunksTo( pAddr, &pData, &len, 1 );
  302. }
  303. virtual bool SendChunksTo( const CIPAddr *pAddr, void const * const *pChunks, const int *pChunkLengths, int nChunks )
  304. {
  305. WSABUF bufs[32];
  306. if ( nChunks > 32 )
  307. {
  308. Error( "CIPSocket::SendChunksTo: too many chunks (%d).", nChunks );
  309. }
  310. int nTotalBytes = 0;
  311. for ( int i=0; i < nChunks; i++ )
  312. {
  313. bufs[i].len = pChunkLengths[i];
  314. bufs[i].buf = (char*)pChunks[i];
  315. nTotalBytes += pChunkLengths[i];
  316. }
  317. assert( m_Socket != INVALID_SOCKET );
  318. // Translate the address.
  319. sockaddr_in addr;
  320. IPAddrToSockAddr( pAddr, &addr );
  321. DWORD dwNumBytesSent = 0;
  322. DWORD ret = WSASendTo(
  323. m_Socket,
  324. bufs,
  325. nChunks,
  326. &dwNumBytesSent,
  327. 0,
  328. (sockaddr*)&addr,
  329. sizeof( addr ),
  330. NULL,
  331. NULL
  332. );
  333. return ret == 0 && (int)dwNumBytesSent == nTotalBytes;
  334. }
  335. virtual int RecvFrom( void *pData, int maxDataLen, CIPAddr *pFrom )
  336. {
  337. assert( m_Socket != INVALID_SOCKET );
  338. fd_set readSet;
  339. readSet.fd_count = 1;
  340. readSet.fd_array[0] = m_Socket;
  341. TIMEVAL timeVal = SetupTimeVal( 0 );
  342. // See if it has a packet waiting.
  343. int status = select( 0, &readSet, NULL, NULL, &timeVal );
  344. if ( status == 0 || status == SOCKET_ERROR )
  345. return -1;
  346. // Get the data.
  347. sockaddr_in sender;
  348. int fromSize = sizeof( sockaddr_in );
  349. status = recvfrom( m_Socket, (char*)pData, maxDataLen, 0, (struct sockaddr*)&sender, &fromSize );
  350. if ( status == 0 || status == SOCKET_ERROR )
  351. {
  352. return -1;
  353. }
  354. else
  355. {
  356. if ( pFrom )
  357. {
  358. SockAddrToIPAddr( &sender, pFrom );
  359. }
  360. m_flLastRecvTime = IP_FloatTime();
  361. return status;
  362. }
  363. }
  364. virtual double GetRecvTimeout()
  365. {
  366. return IP_FloatTime() - m_flLastRecvTime;
  367. }
  368. private:
  369. void Term()
  370. {
  371. if ( m_Socket != INVALID_SOCKET )
  372. {
  373. if ( m_bMulticastGroupMembership )
  374. {
  375. // Undo our multicast group membership.
  376. setsockopt( m_Socket, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char*)&m_MulticastGroupMREQ, sizeof( m_MulticastGroupMREQ ) );
  377. }
  378. closesocket( m_Socket );
  379. m_Socket = INVALID_SOCKET;
  380. }
  381. m_bSetupToBroadcast = false;
  382. m_bMulticastGroupMembership = false;
  383. }
  384. private:
  385. SOCKET m_Socket;
  386. bool m_bMulticastGroupMembership; // Did we join a multicast group?
  387. ip_mreq m_MulticastGroupMREQ;
  388. bool m_bSetupToBroadcast;
  389. double m_flLastRecvTime;
  390. bool m_bListenSocket;
  391. };
  392. ISocket* CreateIPSocket()
  393. {
  394. return new CIPSocket;
  395. }
  396. ISocket* CreateMulticastListenSocket(
  397. const CIPAddr &addr,
  398. const CIPAddr &localInterface )
  399. {
  400. CIPSocket *pSocket = new CIPSocket;
  401. CIPAddr bindAddr = localInterface;
  402. bindAddr.port = addr.port;
  403. if ( pSocket->Bind( &bindAddr ) &&
  404. pSocket->ListenToMulticastStream( addr, localInterface )
  405. )
  406. {
  407. return pSocket;
  408. }
  409. else
  410. {
  411. pSocket->Release();
  412. return NULL;
  413. }
  414. }
  415. bool ConvertStringToIPAddr( const char *pStr, CIPAddr *pOut )
  416. {
  417. char ipStr[512];
  418. const char *pColon = strchr( pStr, ':' );
  419. if ( pColon )
  420. {
  421. int toCopy = pColon - pStr;
  422. if ( toCopy < 2 || toCopy > sizeof(ipStr)-1 )
  423. {
  424. assert( false );
  425. return false;
  426. }
  427. memcpy( ipStr, pStr, toCopy );
  428. ipStr[toCopy] = 0;
  429. pOut->port = (unsigned short)atoi( pColon+1 );
  430. }
  431. else
  432. {
  433. strncpy( ipStr, pStr, sizeof( ipStr ) );
  434. ipStr[ sizeof(ipStr)-1 ] = 0;
  435. }
  436. if ( ipStr[0] >= '0' && ipStr[0] <= '9' )
  437. {
  438. // It's numbers.
  439. int ip[4];
  440. sscanf( ipStr, "%d.%d.%d.%d", &ip[0], &ip[1], &ip[2], &ip[3] );
  441. pOut->ip[0] = (unsigned char)ip[0];
  442. pOut->ip[1] = (unsigned char)ip[1];
  443. pOut->ip[2] = (unsigned char)ip[2];
  444. pOut->ip[3] = (unsigned char)ip[3];
  445. }
  446. else
  447. {
  448. // It's a text string.
  449. struct hostent *pHost = gethostbyname( ipStr );
  450. if( !pHost )
  451. return false;
  452. pOut->ip[0] = pHost->h_addr_list[0][0];
  453. pOut->ip[1] = pHost->h_addr_list[0][1];
  454. pOut->ip[2] = pHost->h_addr_list[0][2];
  455. pOut->ip[3] = pHost->h_addr_list[0][3];
  456. }
  457. return true;
  458. }
  459. bool ConvertIPAddrToString( const CIPAddr *pIn, char *pOut, int outLen )
  460. {
  461. in_addr addr;
  462. addr.S_un.S_un_b.s_b1 = pIn->ip[0];
  463. addr.S_un.S_un_b.s_b2 = pIn->ip[1];
  464. addr.S_un.S_un_b.s_b3 = pIn->ip[2];
  465. addr.S_un.S_un_b.s_b4 = pIn->ip[3];
  466. HOSTENT *pEnt = gethostbyaddr( (char*)&addr, sizeof( addr ), AF_INET );
  467. if ( pEnt )
  468. {
  469. Q_strncpy( pOut, pEnt->h_name, outLen );
  470. return true;
  471. }
  472. else
  473. {
  474. return false;
  475. }
  476. }
  477. void IP_GetLastErrorString( char *pStr, int maxLen )
  478. {
  479. char *lpMsgBuf;
  480. FormatMessage(
  481. FORMAT_MESSAGE_ALLOCATE_BUFFER |
  482. FORMAT_MESSAGE_FROM_SYSTEM |
  483. FORMAT_MESSAGE_IGNORE_INSERTS,
  484. NULL,
  485. GetLastError(),
  486. MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
  487. (LPTSTR) &lpMsgBuf,
  488. 0,
  489. NULL
  490. );
  491. Q_strncpy( pStr, lpMsgBuf, maxLen );
  492. LocalFree( lpMsgBuf );
  493. }