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.

150 lines
3.0 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=============================================================================//
  6. #if defined(_WIN32) && !defined(_X360)
  7. #include <winsock.h>
  8. #elif POSIX
  9. #define INVALID_SOCKET -1
  10. #define SOCKET_ERROR -1
  11. #include <sys/types.h>
  12. #include <sys/socket.h>
  13. #include <netinet/in.h>
  14. #include <unistd.h>
  15. #define closesocket close
  16. #endif
  17. #include "blockingudpsocket.h"
  18. #include "tier0/vcrmode.h"
  19. class CBlockingUDPSocket::CImpl
  20. {
  21. public:
  22. struct sockaddr_in m_SocketIP;
  23. fd_set m_FDSet;
  24. };
  25. CBlockingUDPSocket::CBlockingUDPSocket() :
  26. m_cserIP(),
  27. m_Socket( 0 ),
  28. m_pImpl( new CImpl )
  29. {
  30. CreateSocket();
  31. }
  32. CBlockingUDPSocket::~CBlockingUDPSocket()
  33. {
  34. delete m_pImpl;
  35. closesocket( static_cast<unsigned int>( m_Socket ));
  36. }
  37. bool CBlockingUDPSocket::CreateSocket (void)
  38. {
  39. struct sockaddr_in address;
  40. m_Socket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  41. if ( m_Socket == INVALID_SOCKET )
  42. {
  43. return false;
  44. }
  45. address = m_pImpl->m_SocketIP;
  46. if ( SOCKET_ERROR == bind( m_Socket, ( struct sockaddr * )&address, sizeof( address ) ) )
  47. {
  48. return false;
  49. }
  50. #ifdef _WIN32
  51. if ( m_pImpl->m_SocketIP.sin_addr.S_un.S_addr == INADDR_ANY )
  52. {
  53. m_pImpl->m_SocketIP.sin_addr.S_un.S_addr = 0L;
  54. }
  55. #elif POSIX
  56. if ( m_pImpl->m_SocketIP.sin_addr.s_addr == INADDR_ANY )
  57. {
  58. m_pImpl->m_SocketIP.sin_addr.s_addr = 0L;
  59. }
  60. #endif
  61. return true;
  62. }
  63. bool CBlockingUDPSocket::WaitForMessage( float timeOutInSeconds )
  64. {
  65. struct timeval tv;
  66. FD_ZERO( &m_pImpl->m_FDSet );
  67. FD_SET( m_Socket, &m_pImpl->m_FDSet );//lint !e717
  68. tv.tv_sec = (int)timeOutInSeconds;
  69. float remainder = timeOutInSeconds - (int)timeOutInSeconds;
  70. tv.tv_usec = (int)( remainder * 1000000 + 0.5f ); /* micro seconds */
  71. if ( SOCKET_ERROR == select( ( int )m_Socket + 1, &m_pImpl->m_FDSet, NULL, NULL, &tv ) )
  72. {
  73. return false;
  74. }
  75. if ( FD_ISSET( m_Socket, &m_pImpl->m_FDSet) )
  76. {
  77. return true;
  78. }
  79. // Timed out
  80. return false;
  81. }
  82. unsigned int CBlockingUDPSocket::ReceiveSocketMessage( struct sockaddr_in *packet_from, unsigned char *buf, size_t bufsize )
  83. {
  84. memset( packet_from, 0, sizeof( *packet_from ) );
  85. struct sockaddr fromaddress;
  86. int fromlen = sizeof( fromaddress );
  87. int packet_length = VCRHook_recvfrom
  88. (
  89. m_Socket,
  90. (char *)buf,
  91. (int)bufsize,
  92. 0,
  93. &fromaddress,
  94. &fromlen
  95. );
  96. if ( SOCKET_ERROR == packet_length )
  97. {
  98. return 0;
  99. }
  100. // In case it's parsed as a string
  101. buf[ packet_length ] = 0;
  102. // Copy over the receive address
  103. *packet_from = *( struct sockaddr_in * )&fromaddress;
  104. return ( unsigned int )packet_length;
  105. }
  106. bool CBlockingUDPSocket::SendSocketMessage( const struct sockaddr_in & rRecipient, const unsigned char *buf, size_t bufsize )
  107. {
  108. // Send data
  109. int bytesSent = sendto
  110. (
  111. m_Socket,
  112. (const char *)buf,
  113. (int)bufsize,
  114. 0,
  115. reinterpret_cast< const sockaddr * >( &rRecipient ),
  116. sizeof( rRecipient )
  117. );
  118. if ( SOCKET_ERROR == bytesSent )
  119. {
  120. return false;
  121. }
  122. return true;
  123. }