//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //=============================================================================// #if defined(_WIN32) && !defined(_X360) #include #elif POSIX #define INVALID_SOCKET -1 #define SOCKET_ERROR -1 #include #include #include #include #define closesocket close #endif #include "blockingudpsocket.h" #include "tier0/vcrmode.h" class CBlockingUDPSocket::CImpl { public: struct sockaddr_in m_SocketIP; fd_set m_FDSet; }; CBlockingUDPSocket::CBlockingUDPSocket() : m_cserIP(), m_Socket( 0 ), m_pImpl( new CImpl ) { CreateSocket(); } CBlockingUDPSocket::~CBlockingUDPSocket() { delete m_pImpl; closesocket( static_cast( m_Socket )); } bool CBlockingUDPSocket::CreateSocket (void) { struct sockaddr_in address; m_Socket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ); if ( m_Socket == INVALID_SOCKET ) { return false; } address = m_pImpl->m_SocketIP; if ( SOCKET_ERROR == bind( m_Socket, ( struct sockaddr * )&address, sizeof( address ) ) ) { return false; } #ifdef _WIN32 if ( m_pImpl->m_SocketIP.sin_addr.S_un.S_addr == INADDR_ANY ) { m_pImpl->m_SocketIP.sin_addr.S_un.S_addr = 0L; } #elif POSIX if ( m_pImpl->m_SocketIP.sin_addr.s_addr == INADDR_ANY ) { m_pImpl->m_SocketIP.sin_addr.s_addr = 0L; } #endif return true; } bool CBlockingUDPSocket::WaitForMessage( float timeOutInSeconds ) { struct timeval tv; FD_ZERO( &m_pImpl->m_FDSet ); FD_SET( m_Socket, &m_pImpl->m_FDSet );//lint !e717 tv.tv_sec = (int)timeOutInSeconds; float remainder = timeOutInSeconds - (int)timeOutInSeconds; tv.tv_usec = (int)( remainder * 1000000 + 0.5f ); /* micro seconds */ if ( SOCKET_ERROR == select( ( int )m_Socket + 1, &m_pImpl->m_FDSet, NULL, NULL, &tv ) ) { return false; } if ( FD_ISSET( m_Socket, &m_pImpl->m_FDSet) ) { return true; } // Timed out return false; } unsigned int CBlockingUDPSocket::ReceiveSocketMessage( struct sockaddr_in *packet_from, unsigned char *buf, size_t bufsize ) { memset( packet_from, 0, sizeof( *packet_from ) ); struct sockaddr fromaddress; int fromlen = sizeof( fromaddress ); int packet_length = VCRHook_recvfrom ( m_Socket, (char *)buf, (int)bufsize, 0, &fromaddress, &fromlen ); if ( SOCKET_ERROR == packet_length ) { return 0; } // In case it's parsed as a string buf[ packet_length ] = 0; // Copy over the receive address *packet_from = *( struct sockaddr_in * )&fromaddress; return ( unsigned int )packet_length; } bool CBlockingUDPSocket::SendSocketMessage( const struct sockaddr_in & rRecipient, const unsigned char *buf, size_t bufsize ) { // Send data int bytesSent = sendto ( m_Socket, (const char *)buf, (int)bufsize, 0, reinterpret_cast< const sockaddr * >( &rRecipient ), sizeof( rRecipient ) ); if ( SOCKET_ERROR == bytesSent ) { return false; } return true; }