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.

1035 lines
26 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================
  7. #if !defined( _X360 )
  8. #define FD_SETSIZE 1024
  9. #endif
  10. #include <assert.h>
  11. #include "winlite.h"
  12. #if !defined( _X360 )
  13. #include "winsock.h"
  14. #else
  15. #include "winsockx.h"
  16. #endif
  17. #include "msgbuffer.h"
  18. #include "socket.h"
  19. #include "inetapi.h"
  20. #include "tier0/vcrmode.h"
  21. #include <VGUI/IVGui.h>
  22. #if defined( _X360 )
  23. #include "xbox/xbox_win32stubs.h"
  24. #endif
  25. //-----------------------------------------------------------------------------
  26. // Purpose: All socket I/O occurs on a thread
  27. //-----------------------------------------------------------------------------
  28. class CSocketThread
  29. {
  30. public:
  31. typedef struct threadsocket_s
  32. {
  33. struct threadsocket_s *next;
  34. CSocket *socket;
  35. } threadsocket_t;
  36. // Construction
  37. CSocketThread( void );
  38. virtual ~CSocketThread( void );
  39. // Sockets add/remove themselves via their constructor
  40. virtual void AddSocketToThread( CSocket *socket );
  41. virtual void RemoveSocketFromThread( CSocket *socket );
  42. // Lock changes to socket list, etc.
  43. virtual void Lock( void );
  44. // Unlock socket list, etc.
  45. virtual void Unlock( void );
  46. // Retrieve handle to shutdown event
  47. virtual HANDLE GetShutdownHandle( void );
  48. // Get head of socket list
  49. virtual threadsocket_t *GetSocketList( void );
  50. // Sample clock for socket thread
  51. virtual float GetClock( void );
  52. private:
  53. // Initialize the clock
  54. void InitTimer( void );
  55. private:
  56. // Critical section used for synchronizing access to socket list
  57. CRITICAL_SECTION cs;
  58. // List of sockets we are listening on
  59. threadsocket_t *m_pSocketList;
  60. // Thread handle
  61. HANDLE m_hThread;
  62. // Thread id
  63. DWORD m_nThreadId;
  64. // Event to set when we want to tell the thread to shut itself down
  65. HANDLE m_hShutdown;
  66. // High performance clock frequency
  67. double m_dClockFrequency;
  68. // Current accumulated time
  69. double m_dCurrentTime;
  70. // How many bits to shift raw 64 bit sample count by
  71. int m_nTimeSampleShift;
  72. // Previous 32 bit sample count
  73. unsigned int m_uiPreviousTime;
  74. };
  75. // Singleton handler
  76. static CSocketThread *GetSocketThread()
  77. {
  78. static CSocketThread g_SocketThread;
  79. return &g_SocketThread;
  80. }
  81. //-----------------------------------------------------------------------------
  82. // Purpose: Main winsock processing thread
  83. // Input : threadobject -
  84. // Output : static DWORD WINAPI
  85. //-----------------------------------------------------------------------------
  86. static DWORD WINAPI SocketThreadFunc( LPVOID threadobject )
  87. {
  88. // Get pointer to CSocketThread object
  89. CSocketThread *socketthread = ( CSocketThread * )threadobject;
  90. assert( socketthread );
  91. if ( !socketthread )
  92. {
  93. return 0;
  94. }
  95. // Keep looking for data until shutdown event is triggered
  96. while ( 1 )
  97. {
  98. // List of sockets
  99. CSocketThread::threadsocket_t *sockets;
  100. // file descriptor set for sockets
  101. fd_set fdset;
  102. // number of sockets with messages ready
  103. int number;
  104. // number of sockets added to fd_set
  105. int count;
  106. // Check for shutdown event
  107. if ( WAIT_OBJECT_0 == VCRHook_WaitForSingleObject( socketthread->GetShutdownHandle(), 0 ) )
  108. {
  109. break;
  110. }
  111. // Clear the set
  112. FD_ZERO(&fdset);
  113. // No changes to list right now
  114. socketthread->Lock();
  115. // Add all active sockets to the fdset
  116. count = 0;
  117. for ( sockets = socketthread->GetSocketList(); sockets; sockets = sockets->next )
  118. {
  119. FD_SET( static_cast<u_int>( sockets->socket->GetSocketNumber() ), &fdset );
  120. count = max( count, sockets->socket->GetSocketNumber() );
  121. }
  122. // Done
  123. socketthread->Unlock();
  124. if ( count )
  125. {
  126. struct timeval tv;
  127. tv.tv_sec = 0;
  128. tv.tv_usec = 100000; // 100 millisecond == 100000 usec
  129. // Block for 100000 usec, or until a message is in the queue
  130. number = select( count + 1, &fdset, NULL, NULL, &tv );
  131. #if !defined( NO_VCR )
  132. VCRGenericValue( "", &number, sizeof( number ) );
  133. #endif
  134. if ( number > 0 )
  135. {
  136. // Iterate through socket list and see who has data waiting //
  137. // No changes to list right now
  138. socketthread->Lock();
  139. // Check FD_SET for incoming network messages
  140. for ( sockets = socketthread->GetSocketList(); sockets; sockets = sockets->next )
  141. {
  142. bool bSet = FD_ISSET( sockets->socket->GetSocketNumber(), &fdset );
  143. #if !defined( NO_VCR )
  144. VCRGenericValue( "", &bSet, sizeof( bSet ) );
  145. #endif
  146. if ( bSet )
  147. {
  148. // keep reading as long as there is data on the socket
  149. while (sockets->socket->ReceiveData())
  150. {
  151. }
  152. }
  153. }
  154. // Done
  155. socketthread->Unlock();
  156. }
  157. }
  158. // no need to sleep here, much better let it sleep in the select
  159. }
  160. ExitThread( 0 );
  161. return 0;
  162. }
  163. //-----------------------------------------------------------------------------
  164. // Purpose: Construction
  165. //-----------------------------------------------------------------------------
  166. CSocketThread::CSocketThread( void )
  167. {
  168. InitTimer();
  169. m_pSocketList = NULL;
  170. InitializeCriticalSection( &cs );
  171. m_hShutdown = CreateEvent( NULL, TRUE, FALSE, NULL );
  172. assert( m_hShutdown );
  173. m_hThread = 0;
  174. m_nThreadId = 0;
  175. }
  176. //-----------------------------------------------------------------------------
  177. // Purpose:
  178. //-----------------------------------------------------------------------------
  179. CSocketThread::~CSocketThread( void )
  180. {
  181. Lock();
  182. if ( m_hThread )
  183. {
  184. SetEvent( m_hShutdown );
  185. Sleep( 2 );
  186. TerminateThread( m_hThread, 0 );
  187. }
  188. Unlock();
  189. // Kill the socket
  190. //!! need to validate this line
  191. // assert( !m_pSocketList );
  192. if ( m_hThread )
  193. {
  194. CloseHandle( m_hThread );
  195. }
  196. CloseHandle( m_hShutdown );
  197. DeleteCriticalSection( &cs );
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Purpose: Initialize socket thread timer
  201. //-----------------------------------------------------------------------------
  202. void CSocketThread::InitTimer( void )
  203. {
  204. BOOL success;
  205. LARGE_INTEGER PerformanceFreq;
  206. unsigned int lowpart, highpart;
  207. // Start clock at zero
  208. m_dCurrentTime = 0.0;
  209. success = QueryPerformanceFrequency( &PerformanceFreq );
  210. assert( success );
  211. // get 32 out of the 64 time bits such that we have around
  212. // 1 microsecond resolution
  213. lowpart = (unsigned int)PerformanceFreq.LowPart;
  214. highpart = (unsigned int)PerformanceFreq.HighPart;
  215. m_nTimeSampleShift = 0;
  216. while ( highpart || ( lowpart > 2000000.0 ) )
  217. {
  218. m_nTimeSampleShift++;
  219. lowpart >>= 1;
  220. lowpart |= (highpart & 1) << 31;
  221. highpart >>= 1;
  222. }
  223. m_dClockFrequency = 1.0 / (double)lowpart;
  224. // Get initial sample
  225. unsigned int temp;
  226. LARGE_INTEGER PerformanceCount;
  227. QueryPerformanceCounter( &PerformanceCount );
  228. if ( !m_nTimeSampleShift )
  229. {
  230. temp = (unsigned int)PerformanceCount.LowPart;
  231. }
  232. else
  233. {
  234. // Rotate counter to right by m_nTimeSampleShift places
  235. temp = ((unsigned int)PerformanceCount.LowPart >> m_nTimeSampleShift) |
  236. ((unsigned int)PerformanceCount.HighPart << (32 - m_nTimeSampleShift));
  237. }
  238. // Set first time stamp
  239. m_uiPreviousTime = temp;
  240. }
  241. //-----------------------------------------------------------------------------
  242. // Purpose: Thread local timer function
  243. // Output : float
  244. //-----------------------------------------------------------------------------
  245. float CSocketThread::GetClock( void )
  246. {
  247. LARGE_INTEGER PerformanceCount;
  248. unsigned int temp, t2;
  249. double time;
  250. // Get sample counter
  251. QueryPerformanceCounter( &PerformanceCount );
  252. if ( !m_nTimeSampleShift )
  253. {
  254. temp = (unsigned int)PerformanceCount.LowPart;
  255. }
  256. else
  257. {
  258. // Rotate counter to right by m_nTimeSampleShift places
  259. temp = ((unsigned int)PerformanceCount.LowPart >> m_nTimeSampleShift) |
  260. ((unsigned int)PerformanceCount.HighPart << (32 - m_nTimeSampleShift));
  261. }
  262. // check for turnover or backward time
  263. if ( ( temp <= m_uiPreviousTime ) &&
  264. ( ( m_uiPreviousTime - temp ) < 0x10000000) )
  265. {
  266. m_uiPreviousTime = temp; // so we can't get stuck
  267. }
  268. else
  269. {
  270. // gap in performance clocks
  271. t2 = temp - m_uiPreviousTime;
  272. // Convert to time using frequencey of clock
  273. time = (double)t2 * m_dClockFrequency;
  274. // Remember old time
  275. m_uiPreviousTime = temp;
  276. // Increment clock
  277. m_dCurrentTime += time;
  278. }
  279. #if !defined( NO_VCR )
  280. VCRGenericValue( "", &m_dCurrentTime, sizeof( m_dCurrentTime ) );
  281. #endif
  282. // Convert to float
  283. return (float)m_dCurrentTime;
  284. }
  285. //-----------------------------------------------------------------------------
  286. // Purpose: Returns handle of shutdown event
  287. // Output : HANDLE
  288. //-----------------------------------------------------------------------------
  289. HANDLE CSocketThread::GetShutdownHandle( void )
  290. {
  291. return m_hShutdown;
  292. }
  293. //-----------------------------------------------------------------------------
  294. // Purpose: Returns head of socket list
  295. // Output : CSocketThread::threadsocket_t
  296. //-----------------------------------------------------------------------------
  297. CSocketThread::threadsocket_t *CSocketThread::GetSocketList( void )
  298. {
  299. return m_pSocketList;
  300. }
  301. int socketCount = 0;
  302. //-----------------------------------------------------------------------------
  303. // Purpose: Locks object and adds socket to thread
  304. //-----------------------------------------------------------------------------
  305. void CSocketThread::AddSocketToThread( CSocket *socket )
  306. {
  307. // create the thread if it isn't there
  308. if (!m_hThread)
  309. {
  310. m_hThread = VCRHook_CreateThread( NULL, 0, SocketThreadFunc, (void *)this, 0, &m_nThreadId );
  311. assert( m_hThread );
  312. }
  313. socketCount++;
  314. threadsocket_t *p = new threadsocket_t;
  315. p->socket = socket;
  316. Lock();
  317. p->next = m_pSocketList;
  318. m_pSocketList = p;
  319. Unlock();
  320. }
  321. //-----------------------------------------------------------------------------
  322. // Purpose: Locks list and removes specified socket from thread
  323. //-----------------------------------------------------------------------------
  324. void CSocketThread::RemoveSocketFromThread( CSocket *socket )
  325. {
  326. if (!m_hThread)
  327. return;
  328. socketCount--;
  329. Lock();
  330. if ( m_pSocketList )
  331. {
  332. threadsocket_t *p, *n;
  333. p = m_pSocketList;
  334. if ( p->socket == socket )
  335. {
  336. m_pSocketList = m_pSocketList->next;
  337. delete p;
  338. }
  339. else
  340. {
  341. while ( p->next )
  342. {
  343. n = p->next;
  344. if ( n->socket == socket )
  345. {
  346. p->next = n->next;
  347. delete n;
  348. break;
  349. }
  350. p = n;
  351. }
  352. }
  353. }
  354. Unlock();
  355. }
  356. //-----------------------------------------------------------------------------
  357. // Purpose:
  358. //-----------------------------------------------------------------------------
  359. void CSocketThread::Lock( void )
  360. {
  361. VCRHook_EnterCriticalSection( &cs );
  362. }
  363. //-----------------------------------------------------------------------------
  364. // Purpose:
  365. //-----------------------------------------------------------------------------
  366. void CSocketThread::Unlock( void )
  367. {
  368. LeaveCriticalSection( &cs );
  369. }
  370. //-----------------------------------------------------------------------------
  371. // Purpose: Constructs a message handler for incoming socket messages
  372. //-----------------------------------------------------------------------------
  373. CMsgHandler::CMsgHandler( HANDLERTYPE type, void *typeinfo /*=NULL*/ )
  374. {
  375. m_Type = type;
  376. m_pNext = NULL;
  377. // Assume no socket
  378. SetSocket( NULL );
  379. // Assume no special checking
  380. m_ByteCode = 0;
  381. m_szString[ 0 ] = 0;
  382. switch ( m_Type )
  383. {
  384. default:
  385. case MSGHANDLER_ALL:
  386. break;
  387. case MSGHANDLER_BYTECODE:
  388. m_ByteCode = *(unsigned char *)typeinfo;
  389. break;
  390. case MSGHANDLER_STRING:
  391. strcpy( m_szString, (char *)typeinfo );
  392. break;
  393. }
  394. }
  395. //-----------------------------------------------------------------------------
  396. // Purpose:
  397. //-----------------------------------------------------------------------------
  398. CMsgHandler::~CMsgHandler( void )
  399. {
  400. }
  401. //-----------------------------------------------------------------------------
  402. // Purpose: Default message handler for received messages
  403. // Output : Returns true on success, false on failure.
  404. //-----------------------------------------------------------------------------
  405. bool CMsgHandler::Process( netadr_t *from, CMsgBuffer *msg )
  406. {
  407. // Swallow message by default
  408. return true;
  409. }
  410. //-----------------------------------------------------------------------------
  411. // Purpose: Check for special handling
  412. // Input : *from -
  413. // *msg -
  414. // Output : Returns true on success, false on failure.
  415. //-----------------------------------------------------------------------------
  416. bool CMsgHandler::ProcessMessage( netadr_t *from, CMsgBuffer *msg )
  417. {
  418. bool bret = false;
  419. unsigned char ch;
  420. const char *str;
  421. // Crack bytecode or string code
  422. switch( m_Type )
  423. {
  424. case MSGHANDLER_BYTECODE:
  425. msg->Push();
  426. ch = (unsigned char)msg->ReadByte();
  427. msg->Pop();
  428. if ( ch == m_ByteCode )
  429. {
  430. bret = Process( from, msg );
  431. }
  432. break;
  433. case MSGHANDLER_STRING:
  434. msg->Push();
  435. str = msg->ReadString();
  436. msg->Pop();
  437. if ( str && str[ 0 ] && !stricmp( m_szString, str ) )
  438. {
  439. bret = Process( from, msg );
  440. }
  441. break;
  442. default:
  443. case MSGHANDLER_ALL:
  444. bret = Process( from, msg );
  445. break;
  446. }
  447. return bret;
  448. }
  449. //-----------------------------------------------------------------------------
  450. // Purpose: Get next in chain of handlers
  451. //-----------------------------------------------------------------------------
  452. CMsgHandler *CMsgHandler::GetNext( void ) const
  453. {
  454. return m_pNext;
  455. }
  456. //-----------------------------------------------------------------------------
  457. // Purpose: Set next in handler chain
  458. // Input : *next -
  459. //-----------------------------------------------------------------------------
  460. void CMsgHandler::SetNext( CMsgHandler *next )
  461. {
  462. m_pNext = next;
  463. }
  464. //-----------------------------------------------------------------------------
  465. // Purpose: Get underlying socket object
  466. // Output : CSocket
  467. //-----------------------------------------------------------------------------
  468. CSocket *CMsgHandler::GetSocket( void ) const
  469. {
  470. return m_pSocket;
  471. }
  472. //-----------------------------------------------------------------------------
  473. // Purpose: Set underlying socket object
  474. // Input : *socket -
  475. //-----------------------------------------------------------------------------
  476. void CMsgHandler::SetSocket( CSocket *socket )
  477. {
  478. m_pSocket = socket;
  479. }
  480. //-----------------------------------------------------------------------------
  481. // Purpose: Creates a non-blocking, broadcast capable, UDP socket. If port is
  482. // specified, binds it to listen on that port, otherwise, chooses a random port.
  483. //-----------------------------------------------------------------------------
  484. CSocket::CSocket( const char *socketname, int port /*= -1*/ ) : m_SendBuffer(socketname)
  485. {
  486. struct sockaddr_in address;
  487. unsigned long _true = 1;
  488. int i = 1;
  489. m_pSocketName = socketname;
  490. m_bValid = false;
  491. m_bResolved = false;
  492. m_pMessageHandlers = NULL;
  493. m_nUserData = 0;
  494. m_bBroadcastSend = false;
  495. m_iTotalPackets = 0;
  496. m_iCurrentPackets = 0;
  497. m_iRetries = 0;
  498. m_pBufferCS = new CRITICAL_SECTION;
  499. InitializeCriticalSection((CRITICAL_SECTION *)m_pBufferCS);
  500. // ensure the socketthread singleton has been created
  501. GetSocketThread();
  502. // Set up the socket
  503. m_Socket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  504. if ( m_Socket == -1 )
  505. {
  506. //int err = WSAGetLastError();
  507. // WSANOTINITIALISED
  508. return;
  509. }
  510. // Set it to non-blocking
  511. if ( ioctlsocket ( m_Socket, FIONBIO, &_true ) == -1 )
  512. {
  513. closesocket( m_Socket );
  514. m_Socket = 0;
  515. return;
  516. }
  517. // Allow broadcast packets
  518. if ( setsockopt( m_Socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == -1 )
  519. {
  520. closesocket( m_Socket );
  521. m_Socket = 0;
  522. return;
  523. }
  524. // LATER: Support specifying interface name
  525. //if (!net_interface || !net_interface[0] || !stricmp(net_interface, "localhost"))
  526. address.sin_addr.s_addr = INADDR_ANY;
  527. //else
  528. // NET_StringToSockaddr (net_interface, (struct sockaddr *)&address);
  529. if ( port == -1 )
  530. {
  531. address.sin_port = 0;
  532. }
  533. else
  534. {
  535. address.sin_port = htons( (short)port );
  536. }
  537. address.sin_family = AF_INET;
  538. // only bind if we're required to be on a certain port
  539. if ( address.sin_port > 0)
  540. {
  541. // Bind the socket to specified port
  542. if ( bind( m_Socket, (struct sockaddr *)&address, sizeof(address) ) == -1 )
  543. {
  544. closesocket (m_Socket);
  545. m_Socket = 0;
  546. return;
  547. }
  548. }
  549. // Mark as valid
  550. m_bValid = true;
  551. // Only add valid sockets to thread
  552. GetSocketThread()->AddSocketToThread( this );
  553. }
  554. //-----------------------------------------------------------------------------
  555. // Purpose:
  556. //-----------------------------------------------------------------------------
  557. CSocket::~CSocket( void )
  558. {
  559. DeleteCriticalSection((CRITICAL_SECTION *)m_pBufferCS);
  560. delete (CRITICAL_SECTION *)m_pBufferCS;
  561. // Try to remove socket from thread
  562. GetSocketThread()->RemoveSocketFromThread( this );
  563. // Ask message handlers to remove selves?
  564. if ( m_bValid )
  565. {
  566. ::shutdown(m_Socket, 0x01);
  567. ::shutdown(m_Socket, 0x02);
  568. closesocket( m_Socket );
  569. m_Socket = 0;
  570. }
  571. // Remove handlers
  572. CMsgHandler *handler = m_pMessageHandlers;
  573. while ( handler )
  574. {
  575. RemoveMessageHandler( handler );
  576. delete handler;
  577. handler = m_pMessageHandlers;
  578. }
  579. m_pMessageHandlers = NULL;
  580. }
  581. //-----------------------------------------------------------------------------
  582. // Purpose: Add hander to head of chain
  583. // Input : *handler -
  584. //-----------------------------------------------------------------------------
  585. void CSocket::AddMessageHandler( CMsgHandler *handler )
  586. {
  587. handler->SetNext( m_pMessageHandlers );
  588. m_pMessageHandlers = handler;
  589. // Set the socket pointer
  590. handler->SetSocket( this );
  591. }
  592. //-----------------------------------------------------------------------------
  593. // Purpose: Removed indicated handler
  594. // Input : *handler -
  595. //-----------------------------------------------------------------------------
  596. void CSocket::RemoveMessageHandler( CMsgHandler *handler )
  597. {
  598. if ( !handler )
  599. {
  600. return;
  601. }
  602. CMsgHandler *list = m_pMessageHandlers;
  603. if ( list == handler )
  604. {
  605. m_pMessageHandlers = m_pMessageHandlers->GetNext();
  606. return;
  607. }
  608. while ( list )
  609. {
  610. if ( list->GetNext() == handler )
  611. {
  612. list->SetNext( handler->GetNext() );
  613. handler->SetNext( NULL );
  614. return;
  615. }
  616. list = list->GetNext();
  617. }
  618. }
  619. //-----------------------------------------------------------------------------
  620. // Purpose: Send message to specified address
  621. // Input : *to -
  622. // Output : int - number of bytes sent
  623. //-----------------------------------------------------------------------------
  624. int CSocket::SendMessage( netadr_t *to, CMsgBuffer *msg /*= NULL*/ )
  625. {
  626. m_bBroadcastSend = false;
  627. m_ToAddress = *to;
  628. if ( !m_bValid )
  629. {
  630. return 0;
  631. }
  632. if ( !msg )
  633. {
  634. msg = GetSendBuffer();
  635. }
  636. struct sockaddr addr;
  637. net->NetAdrToSockAddr ( to, &addr );
  638. int bytessent = sendto( m_Socket, (const char *)msg->GetData(), msg->GetCurSize(), 0, &addr, sizeof( addr ) );
  639. if ( bytessent == msg->GetCurSize() )
  640. {
  641. return bytessent;
  642. }
  643. return 0;
  644. }
  645. //-----------------------------------------------------------------------------
  646. // Purpose: Send broadcast message on specified port
  647. // Input : port -
  648. // Output : int - number of bytes sent
  649. //-----------------------------------------------------------------------------
  650. int CSocket::Broadcast( int port, CMsgBuffer *msg /*= NULL*/ )
  651. {
  652. m_bBroadcastSend = true;
  653. memset( &m_ToAddress, 0, sizeof( m_ToAddress ) );
  654. if ( !m_bValid )
  655. {
  656. return 0;
  657. }
  658. if ( !msg )
  659. {
  660. msg = GetSendBuffer();
  661. }
  662. struct sockaddr addr;
  663. netadr_t to;
  664. to.port = (unsigned short)htons( (unsigned short)port );
  665. to.type = NA_BROADCAST;
  666. net->NetAdrToSockAddr ( &to, &addr );
  667. int bytessent = sendto( m_Socket, (const char *)msg->GetData(), msg->GetCurSize(), 0, &addr, sizeof( addr ) );
  668. if ( bytessent == msg->GetCurSize() )
  669. {
  670. return bytessent;
  671. }
  672. return 0;
  673. }
  674. //-----------------------------------------------------------------------------
  675. // Purpose: Retrieve internal message buffer
  676. // Output : CMsgBuffer
  677. //-----------------------------------------------------------------------------
  678. CMsgBuffer *CSocket::GetSendBuffer( void )
  679. {
  680. return &m_SendBuffer;
  681. }
  682. //-----------------------------------------------------------------------------
  683. // Purpose: Called once per frame (outside of the socket thread) to allow socket to receive incoming messages
  684. // and route them as appropriate
  685. //-----------------------------------------------------------------------------
  686. void CSocket::Frame( void )
  687. {
  688. // No data waiting
  689. if (!m_MsgBuffers.Size())
  690. return;
  691. VCRHook_EnterCriticalSection( (CRITICAL_SECTION *)m_pBufferCS );
  692. // pass up all the receive buffers
  693. for (int i = 0; i < m_MsgBuffers.Size(); i++)
  694. {
  695. // See if there's a handler for this message
  696. CMsgHandler *handler = m_pMessageHandlers;
  697. netadr_t addr = m_MsgBuffers[i].GetNetAddress();
  698. while ( handler )
  699. {
  700. // Swallow message?
  701. if ( handler->ProcessMessage( &addr, &m_MsgBuffers[i] ) )
  702. break;
  703. handler = handler->GetNext();
  704. }
  705. }
  706. // free the buffer list
  707. m_MsgBuffers.RemoveAll();
  708. LeaveCriticalSection((CRITICAL_SECTION *)m_pBufferCS);
  709. }
  710. //-----------------------------------------------------------------------------
  711. // Purpose: Is socket set up correctly
  712. // Output : Returns true on success, false on failure.
  713. //-----------------------------------------------------------------------------
  714. bool CSocket::IsValid( void ) const
  715. {
  716. return m_bValid;
  717. }
  718. //-----------------------------------------------------------------------------
  719. // Purpose:
  720. // Output : float
  721. //-----------------------------------------------------------------------------
  722. float CSocket::GetClock( void )
  723. {
  724. return GetSocketThread()->GetClock();
  725. }
  726. //-----------------------------------------------------------------------------
  727. // Purpose: Resolves the socket address
  728. // Output : const netadr_t
  729. //-----------------------------------------------------------------------------
  730. const netadr_t *CSocket::GetAddress( void )
  731. {
  732. assert( m_bValid );
  733. if ( !m_bResolved )
  734. {
  735. m_bResolved = true;
  736. // Determine resulting socket address
  737. net->GetSocketAddress( m_Socket, &m_Address );
  738. }
  739. return &m_Address;
  740. }
  741. //-----------------------------------------------------------------------------
  742. // Purpose: Let the user store/retrieve a 32 bit value
  743. // Input : userData -
  744. //-----------------------------------------------------------------------------
  745. void CSocket::SetUserData( unsigned int userData )
  746. {
  747. m_nUserData = userData;
  748. }
  749. //-----------------------------------------------------------------------------
  750. // Purpose: Let the user store/retrieve a 32 bit value
  751. // Output : unsigned int
  752. //-----------------------------------------------------------------------------
  753. unsigned int CSocket::GetUserData(void ) const
  754. {
  755. return m_nUserData;
  756. }
  757. //-----------------------------------------------------------------------------
  758. // Purpose: Returns the underlying socket id number for setting up the fd_set
  759. //-----------------------------------------------------------------------------
  760. int CSocket::GetSocketNumber( void ) const
  761. {
  762. return m_Socket;
  763. }
  764. //-----------------------------------------------------------------------------
  765. // Purpose: Called once FD_ISSET is detected
  766. //-----------------------------------------------------------------------------
  767. bool CSocket::ReceiveData( void )
  768. {
  769. // Check for data
  770. struct sockaddr from;
  771. int fromlen;
  772. int bytes;
  773. unsigned char buffer[ CMsgBuffer::NET_MAXMESSAGE ];
  774. fromlen = sizeof( from );
  775. bytes = VCRHook_recvfrom( m_Socket, (char *)buffer, CMsgBuffer::NET_MAXMESSAGE, 0, (struct sockaddr *)&from, &fromlen );
  776. //int port = ntohs( ((struct sockaddr_in *)&from)->sin_port);
  777. // Socket error
  778. if ( bytes == -1 )
  779. {
  780. return false;
  781. }
  782. // Too much data, ignore it
  783. if ( bytes >= CMsgBuffer::NET_MAXMESSAGE )
  784. {
  785. return false;
  786. }
  787. // Packets must have -1 tag
  788. if ( bytes < 4 )
  789. {
  790. return false;
  791. }
  792. // Mark the time no matter what since FD_SET said there was data and we should have it now
  793. float recvTime = GetClock();
  794. if( *(int *)&buffer[0] == -2 ) // its a split packet :)
  795. {
  796. int curPacket=0,offset=0;
  797. SPLITPACKET *pak =reinterpret_cast<SPLITPACKET *>(&buffer[0]);
  798. if(m_iTotalPackets==0) // this is the first in the series
  799. {
  800. m_iTotalPackets = (pak->packetID & 0x0f);
  801. m_iSeqNo = pak->sequenceNumber;
  802. m_iRetries=0;
  803. m_iCurrentPackets=1;// packet numbers start at zero, total is the total number (i.e =2 for packet 0,1)
  804. curPacket= (pak->packetID & 0xf0)>>4;
  805. }
  806. else if (m_iSeqNo == pak->sequenceNumber)
  807. {
  808. m_iCurrentPackets++;
  809. curPacket= (pak->packetID & 0xf0)>>4;
  810. }
  811. else
  812. {
  813. m_iRetries++;
  814. if(m_iRetries>MAX_RETRIES) // make sure we give up eventually on fragments
  815. {
  816. m_iTotalPackets=0;
  817. }
  818. return false; // TODO: add support for multiple fragments at one time?
  819. }
  820. if(curPacket==0)
  821. {
  822. offset=4; // strip the "-1" at the front of the first packet
  823. }
  824. if(curPacket<MAX_PACKETS) // just in case...
  825. {
  826. m_CurPacket[curPacket].Clear(); // new packet, clear the buffer out
  827. m_CurPacket[curPacket].WriteBuf(bytes-offset-sizeof(SPLITPACKET),&buffer[offset+sizeof(SPLITPACKET)]);
  828. }
  829. if(m_iCurrentPackets==m_iTotalPackets)
  830. {
  831. VCRHook_EnterCriticalSection((CRITICAL_SECTION *)m_pBufferCS);
  832. // Get from address
  833. netadr_t addr;
  834. net->SockAddrToNetAdr( &from, &addr );
  835. // append to the receive buffer
  836. int idx = m_MsgBuffers.AddToTail();
  837. CMsgBuffer &msgBuffer = m_MsgBuffers[idx];
  838. msgBuffer.Clear();
  839. // copy all our fragments together
  840. for(int i=0;i<m_iTotalPackets;i++)
  841. {
  842. // buffer must be big enough for us to use, that is where the data originally came from :)
  843. m_CurPacket[i].ReadBuf(m_CurPacket[i].GetCurSize(),buffer);
  844. msgBuffer.WriteBuf(m_CurPacket[i].GetCurSize(),buffer);
  845. }
  846. msgBuffer.SetTime(recvTime);
  847. msgBuffer.SetNetAddress(addr);
  848. LeaveCriticalSection((CRITICAL_SECTION *)m_pBufferCS);
  849. m_iTotalPackets = 0; // we have collected all the fragments for
  850. //this packet, we can start on a new one now
  851. }
  852. }
  853. else if ( *(int *)&buffer[0] == -1 ) // Must have 255,255,255,255 oob tag
  854. {
  855. /*
  856. // Fake packet loss
  857. if ( rand() % 1000 < 200 )
  858. return;
  859. */
  860. VCRHook_EnterCriticalSection((CRITICAL_SECTION *)m_pBufferCS);
  861. // Get from address
  862. netadr_t addr;
  863. net->SockAddrToNetAdr( &from, &addr );
  864. // append to the receive buffer
  865. int idx = m_MsgBuffers.AddToTail();
  866. CMsgBuffer &msgBuffer = m_MsgBuffers[idx];
  867. // Copy payload minus the -1 tag
  868. msgBuffer.Clear();
  869. msgBuffer.WriteBuf( bytes - 4, &buffer[ 4 ] );
  870. msgBuffer.SetTime(recvTime);
  871. msgBuffer.SetNetAddress(addr);
  872. LeaveCriticalSection((CRITICAL_SECTION *)m_pBufferCS);
  873. }
  874. return true;
  875. }