1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
|
//========= 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;
}
|