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
120 lines
2.4 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: |
|
// |
|
//===========================================================================// |
|
|
|
#include <winsock.h> |
|
#include "udp_socket.h" |
|
#include "tier1/utlbuffer.h" |
|
#include "tier1/strtools.h" |
|
|
|
class CUDPSocket::CImpl |
|
{ |
|
public: |
|
struct sockaddr_in m_SocketIP; |
|
}; |
|
|
|
CUDPSocket::CUDPSocket( ) : |
|
m_socketIP(), |
|
m_Socket( INVALID_SOCKET ), |
|
m_Port( 0 ), |
|
m_pImpl( new CImpl ) |
|
{ |
|
Q_memset( &m_socketIP, 0, sizeof( m_socketIP ) ); |
|
} |
|
|
|
CUDPSocket::~CUDPSocket() |
|
{ |
|
delete m_pImpl; |
|
} |
|
|
|
bool CUDPSocket::Init( unsigned short nBindToPort ) |
|
{ |
|
m_Port = nBindToPort; |
|
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; |
|
address.sin_family = AF_INET; |
|
address.sin_port = htons( m_Port ); |
|
address.sin_addr.S_un.S_addr = INADDR_ANY; |
|
|
|
if ( SOCKET_ERROR == bind( m_Socket, ( struct sockaddr * )&address, sizeof( address ) ) ) |
|
{ |
|
return false; |
|
} |
|
|
|
// Set to non-blocking i/o |
|
unsigned long value = 1; |
|
if ( SOCKET_ERROR == ioctlsocket( m_Socket, FIONBIO, &value ) ) |
|
{ |
|
return false; |
|
} |
|
|
|
return true; |
|
} |
|
|
|
void CUDPSocket::Shutdown() |
|
{ |
|
if ( m_Socket != INVALID_SOCKET ) |
|
{ |
|
closesocket( static_cast<unsigned int>( m_Socket )); |
|
} |
|
} |
|
|
|
bool CUDPSocket::RecvFrom( netadr_t& packet_from, CUtlBuffer& data ) |
|
{ |
|
sockaddr from; |
|
int nFromLen = sizeof( from ); |
|
|
|
int nMaxBytesToRead = data.Size() - data.TellPut(); |
|
char *pBuffer = (char*)data.PeekPut(); |
|
|
|
int nBytesRead = recvfrom( m_Socket, pBuffer, nMaxBytesToRead, 0, &from, &nFromLen ); |
|
if ( nBytesRead == SOCKET_ERROR ) |
|
{ |
|
int nError = WSAGetLastError(); |
|
if ( nError != WSAEWOULDBLOCK ) |
|
{ |
|
Warning( "Socket error '%i'\n", nError ); |
|
} |
|
return false; |
|
} |
|
|
|
packet_from.SetFromSockadr( &from ); |
|
data.SeekPut( CUtlBuffer::SEEK_CURRENT, nBytesRead ); |
|
return true; |
|
} |
|
|
|
bool CUDPSocket::SendTo( const netadr_t &recipient, const CUtlBuffer& data ) |
|
{ |
|
return SendTo( recipient, (const byte *)data.Base(), (size_t)data.TellPut() ); |
|
} |
|
|
|
bool CUDPSocket::SendTo( const netadr_t &recipient, const byte *data, size_t datalength ) |
|
{ |
|
sockaddr dest; |
|
recipient.ToSockadr( &dest ); |
|
|
|
// Send data |
|
int bytesSent = sendto |
|
( |
|
m_Socket, |
|
(const char *)data, |
|
(int)datalength, |
|
0, |
|
reinterpret_cast< const sockaddr * >( &dest ), |
|
sizeof( dest ) |
|
); |
|
|
|
if ( SOCKET_ERROR == bytesSent ) |
|
{ |
|
return false; |
|
} |
|
|
|
return true; |
|
}
|
|
|