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.
151 lines
3.0 KiB
151 lines
3.0 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose:
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#if defined(_WIN32) && !defined(_X360)
|
||
|
#include <winsock.h>
|
||
|
#elif POSIX
|
||
|
#define INVALID_SOCKET -1
|
||
|
#define SOCKET_ERROR -1
|
||
|
#include <sys/types.h>
|
||
|
#include <sys/socket.h>
|
||
|
#include <netinet/in.h>
|
||
|
#include <unistd.h>
|
||
|
#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<unsigned int>( 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;
|
||
|
}
|