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.

120 lines
2.4 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include <winsock.h>
  7. #include "udp_socket.h"
  8. #include "tier1/utlbuffer.h"
  9. #include "tier1/strtools.h"
  10. class CUDPSocket::CImpl
  11. {
  12. public:
  13. struct sockaddr_in m_SocketIP;
  14. };
  15. CUDPSocket::CUDPSocket( ) :
  16. m_socketIP(),
  17. m_Socket( INVALID_SOCKET ),
  18. m_Port( 0 ),
  19. m_pImpl( new CImpl )
  20. {
  21. Q_memset( &m_socketIP, 0, sizeof( m_socketIP ) );
  22. }
  23. CUDPSocket::~CUDPSocket()
  24. {
  25. delete m_pImpl;
  26. }
  27. bool CUDPSocket::Init( unsigned short nBindToPort )
  28. {
  29. m_Port = nBindToPort;
  30. struct sockaddr_in address;
  31. m_Socket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP );
  32. if ( m_Socket == INVALID_SOCKET )
  33. return false;
  34. address = m_pImpl->m_SocketIP;
  35. address.sin_family = AF_INET;
  36. address.sin_port = htons( m_Port );
  37. address.sin_addr.S_un.S_addr = INADDR_ANY;
  38. if ( SOCKET_ERROR == bind( m_Socket, ( struct sockaddr * )&address, sizeof( address ) ) )
  39. {
  40. return false;
  41. }
  42. // Set to non-blocking i/o
  43. unsigned long value = 1;
  44. if ( SOCKET_ERROR == ioctlsocket( m_Socket, FIONBIO, &value ) )
  45. {
  46. return false;
  47. }
  48. return true;
  49. }
  50. void CUDPSocket::Shutdown()
  51. {
  52. if ( m_Socket != INVALID_SOCKET )
  53. {
  54. closesocket( static_cast<unsigned int>( m_Socket ));
  55. }
  56. }
  57. bool CUDPSocket::RecvFrom( netadr_t& packet_from, CUtlBuffer& data )
  58. {
  59. sockaddr from;
  60. int nFromLen = sizeof( from );
  61. int nMaxBytesToRead = data.Size() - data.TellPut();
  62. char *pBuffer = (char*)data.PeekPut();
  63. int nBytesRead = recvfrom( m_Socket, pBuffer, nMaxBytesToRead, 0, &from, &nFromLen );
  64. if ( nBytesRead == SOCKET_ERROR )
  65. {
  66. int nError = WSAGetLastError();
  67. if ( nError != WSAEWOULDBLOCK )
  68. {
  69. Warning( "Socket error '%i'\n", nError );
  70. }
  71. return false;
  72. }
  73. packet_from.SetFromSockadr( &from );
  74. data.SeekPut( CUtlBuffer::SEEK_CURRENT, nBytesRead );
  75. return true;
  76. }
  77. bool CUDPSocket::SendTo( const netadr_t &recipient, const CUtlBuffer& data )
  78. {
  79. return SendTo( recipient, (const byte *)data.Base(), (size_t)data.TellPut() );
  80. }
  81. bool CUDPSocket::SendTo( const netadr_t &recipient, const byte *data, size_t datalength )
  82. {
  83. sockaddr dest;
  84. recipient.ToSockadr( &dest );
  85. // Send data
  86. int bytesSent = sendto
  87. (
  88. m_Socket,
  89. (const char *)data,
  90. (int)datalength,
  91. 0,
  92. reinterpret_cast< const sockaddr * >( &dest ),
  93. sizeof( dest )
  94. );
  95. if ( SOCKET_ERROR == bytesSent )
  96. {
  97. return false;
  98. }
  99. return true;
  100. }