28 #include "../../idlib/precompiled.h"
36 static WSADATA winsockdata;
37 static bool winsockInitialized =
false;
38 static bool usingSocks =
false;
52 static struct sockaddr socksRelayAddr;
54 static SOCKET ip_socket;
55 static SOCKET socks_socket;
56 static char socksBuf[4096];
63 #define MAX_INTERFACES 32
78 code = WSAGetLastError();
80 case WSAEINTR:
return "WSAEINTR";
81 case WSAEBADF:
return "WSAEBADF";
82 case WSAEACCES:
return "WSAEACCES";
83 case WSAEDISCON:
return "WSAEDISCON";
84 case WSAEFAULT:
return "WSAEFAULT";
85 case WSAEINVAL:
return "WSAEINVAL";
86 case WSAEMFILE:
return "WSAEMFILE";
87 case WSAEWOULDBLOCK:
return "WSAEWOULDBLOCK";
88 case WSAEINPROGRESS:
return "WSAEINPROGRESS";
89 case WSAEALREADY:
return "WSAEALREADY";
90 case WSAENOTSOCK:
return "WSAENOTSOCK";
91 case WSAEDESTADDRREQ:
return "WSAEDESTADDRREQ";
92 case WSAEMSGSIZE:
return "WSAEMSGSIZE";
93 case WSAEPROTOTYPE:
return "WSAEPROTOTYPE";
94 case WSAENOPROTOOPT:
return "WSAENOPROTOOPT";
95 case WSAEPROTONOSUPPORT:
return "WSAEPROTONOSUPPORT";
96 case WSAESOCKTNOSUPPORT:
return "WSAESOCKTNOSUPPORT";
97 case WSAEOPNOTSUPP:
return "WSAEOPNOTSUPP";
98 case WSAEPFNOSUPPORT:
return "WSAEPFNOSUPPORT";
99 case WSAEAFNOSUPPORT:
return "WSAEAFNOSUPPORT";
100 case WSAEADDRINUSE:
return "WSAEADDRINUSE";
101 case WSAEADDRNOTAVAIL:
return "WSAEADDRNOTAVAIL";
102 case WSAENETDOWN:
return "WSAENETDOWN";
103 case WSAENETUNREACH:
return "WSAENETUNREACH";
104 case WSAENETRESET:
return "WSAENETRESET";
105 case WSAECONNABORTED:
return "WSWSAECONNABORTEDAEINTR";
106 case WSAECONNRESET:
return "WSAECONNRESET";
107 case WSAENOBUFS:
return "WSAENOBUFS";
108 case WSAEISCONN:
return "WSAEISCONN";
109 case WSAENOTCONN:
return "WSAENOTCONN";
110 case WSAESHUTDOWN:
return "WSAESHUTDOWN";
111 case WSAETOOMANYREFS:
return "WSAETOOMANYREFS";
112 case WSAETIMEDOUT:
return "WSAETIMEDOUT";
113 case WSAECONNREFUSED:
return "WSAECONNREFUSED";
114 case WSAELOOP:
return "WSAELOOP";
115 case WSAENAMETOOLONG:
return "WSAENAMETOOLONG";
116 case WSAEHOSTDOWN:
return "WSAEHOSTDOWN";
117 case WSASYSNOTREADY:
return "WSASYSNOTREADY";
118 case WSAVERNOTSUPPORTED:
return "WSAVERNOTSUPPORTED";
119 case WSANOTINITIALISED:
return "WSANOTINITIALISED";
120 case WSAHOST_NOT_FOUND:
return "WSAHOST_NOT_FOUND";
121 case WSATRY_AGAIN:
return "WSATRY_AGAIN";
122 case WSANO_RECOVERY:
return "WSANO_RECOVERY";
123 case WSANO_DATA:
return "WSANO_DATA";
124 default:
return "NO ERROR";
134 memset( s, 0,
sizeof(*s) );
137 ((
struct sockaddr_in *)s)->sin_family = AF_INET;
138 ((
struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
141 ((
struct sockaddr_in *)s)->sin_family = AF_INET;
142 ((
struct sockaddr_in *)s)->sin_addr.s_addr = *(
int *)&a->
ip;
145 ((
struct sockaddr_in *)s)->sin_port = htons( (
short)a->
port );
156 if (s->sa_family == AF_INET) {
157 ip = ((
struct sockaddr_in *)s)->sin_addr.s_addr;
158 *(
unsigned int *)&a->
ip = ip;
159 a->
port = htons( ((
struct sockaddr_in *)
s)->sin_port );
162 if ( ip == INADDR_LOOPBACK ) {
175 static bool Net_ExtractPort(
const char *
src,
char *buf,
int bufsize,
int *port ) {
177 strncpy( buf, src, bufsize );
178 p = buf; p +=
Min( bufsize - 1, (
int)strlen( src ) ); *p =
'\0';
179 p = strchr( buf,
':' );
184 *port = strtol( p+1,
NULL, 10 );
185 if ( errno == ERANGE ) {
196 static bool Net_StringToSockaddr(
const char *
s,
struct sockaddr *sadr,
bool doDNSResolve ) {
201 memset( sadr, 0,
sizeof( *sadr ) );
203 ((
struct sockaddr_in *)sadr)->sin_family = AF_INET;
204 ((
struct sockaddr_in *)sadr)->sin_port = 0;
206 if( s[0] >=
'0' && s[0] <=
'9' ) {
207 unsigned long ret = inet_addr(s);
208 if ( ret != INADDR_NONE ) {
209 *(
int *)&((
struct sockaddr_in *)sadr)->sin_addr = ret;
212 if ( !Net_ExtractPort( s, buf,
sizeof( buf ), &port ) ) {
215 ret = inet_addr( buf );
216 if ( ret == INADDR_NONE ) {
219 *(
int *)&((
struct sockaddr_in *)sadr)->sin_addr = ret;
220 ((
struct sockaddr_in *)sadr)->sin_port = htons( port );
222 }
else if ( doDNSResolve ) {
225 if ( Net_ExtractPort( s, buf,
sizeof( buf ), &port ) ) {
226 ((
struct sockaddr_in *)sadr)->sin_port = htons( port );
228 h = gethostbyname( buf );
232 *(
int *)&((
struct sockaddr_in *)sadr)->sin_addr = *(
int *)h->h_addr_list[0];
245 struct sockaddr_in address;
246 unsigned long _true = 1;
250 if( net_interface ) {
251 common->
DPrintf(
"Opening IP socket: %s:%i\n", net_interface, port );
253 common->
DPrintf(
"Opening IP socket: localhost:%i\n", port );
256 if( ( newsocket = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET ) {
257 err = WSAGetLastError();
258 if( err != WSAEAFNOSUPPORT ) {
265 if( ioctlsocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR ) {
271 if( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (
char *)&i,
sizeof(i) ) == SOCKET_ERROR ) {
276 if( !net_interface || !net_interface[0] || !
idStr::Icmp( net_interface,
"localhost" ) ) {
277 address.sin_addr.s_addr = INADDR_ANY;
280 Net_StringToSockaddr( net_interface, (
struct sockaddr *)&address,
true );
284 address.sin_port = 0;
287 address.sin_port = htons( (
short)port );
290 address.sin_family = AF_INET;
292 if( bind( newsocket, (
const struct sockaddr *)&address,
sizeof(address) ) == SOCKET_ERROR ) {
294 closesocket( newsocket );
302 getsockname( newsocket, (sockaddr *)&address, &len );
315 struct sockaddr_in address;
320 unsigned char buf[64];
324 common->
Printf(
"Opening connection to SOCKS server.\n" );
326 if ( ( socks_socket = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ) {
327 err = WSAGetLastError();
334 err = WSAGetLastError();
338 if ( h->h_addrtype != AF_INET ) {
339 common->
Printf(
"WARNING: NET_OpenSocks: gethostbyname: address type was not AF_INET\n" );
342 address.sin_family = AF_INET;
343 address.sin_addr.s_addr = *(
int *)h->h_addr_list[0];
346 if ( connect( socks_socket, (
struct sockaddr *)&address,
sizeof( address ) ) == SOCKET_ERROR ) {
347 err = WSAGetLastError();
374 if ( send( socks_socket, (
const char *)buf, len, 0 ) == SOCKET_ERROR ) {
375 err = WSAGetLastError();
381 len = recv( socks_socket, (
char *)buf, 64, 0 );
382 if ( len == SOCKET_ERROR ) {
383 err = WSAGetLastError();
387 if ( len != 2 || buf[0] != 5 ) {
415 buf[2 + ulen] = plen;
421 if ( send( socks_socket, (
const char *)buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR ) {
422 err = WSAGetLastError();
428 len = recv( socks_socket, (
char *)buf, 64, 0 );
429 if ( len == SOCKET_ERROR ) {
430 err = WSAGetLastError();
434 if ( len != 2 || buf[0] != 1 ) {
439 common->
Printf(
"NET_OpenSocks: authentication failed\n" );
449 *(
int *)&buf[4] = INADDR_ANY;
450 *(
short *)&buf[8] = htons( (
short)port );
451 if ( send( socks_socket, (
const char *)buf, 10, 0 ) == SOCKET_ERROR ) {
452 err = WSAGetLastError();
458 len = recv( socks_socket, (
char *)buf, 64, 0 );
459 if( len == SOCKET_ERROR ) {
460 err = WSAGetLastError();
464 if( len < 2 || buf[0] != 5 ) {
470 common->
Printf(
"NET_OpenSocks: request denied: %i\n", buf[1] );
474 common->
Printf(
"NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] );
477 ((
struct sockaddr_in *)&socksRelayAddr)->sin_family = AF_INET;
478 ((
struct sockaddr_in *)&socksRelayAddr)->sin_addr.s_addr = *(
int *)&buf[4];
479 ((
struct sockaddr_in *)&socksRelayAddr)->sin_port = *(
short *)&buf[8];
480 memset( ((
struct sockaddr_in *)&socksRelayAddr)->sin_zero, 0, 8 );
499 if ( timeout <= 0 ) {
504 FD_SET( netSocket, &set );
512 common->
DPrintf(
"Net_WaitForUPDPacket select(): %s\n", strerror( errno ) );
531 struct sockaddr from;
539 fromlen =
sizeof(from);
540 ret = recvfrom( netSocket, data, maxSize, 0, (
struct sockaddr *)&from, &fromlen );
541 if ( ret == SOCKET_ERROR ) {
542 err = WSAGetLastError();
544 if( err == WSAEWOULDBLOCK || err == WSAECONNRESET ) {
553 if ( netSocket == ip_socket ) {
554 memset( ((
struct sockaddr_in *)&from)->sin_zero, 0, 8 );
557 if ( usingSocks && netSocket == ip_socket && memcmp( &from, &socksRelayAddr, fromlen ) == 0 ) {
558 if ( ret < 10 || data[0] != 0 || data[1] != 0 || data[2] != 0 || data[3] != 1 ) {
562 net_from.
ip[0] = data[4];
563 net_from.
ip[1] = data[5];
564 net_from.
ip[2] = data[6];
565 net_from.
ip[3] = data[7];
566 net_from.
port = *(
short *)&data[8];
567 memmove( data, &data[10], ret - 10 );
572 if( ret == maxSize ) {
591 struct sockaddr addr;
604 *(
int *)&socksBuf[4] = ((
struct sockaddr_in *)&
addr)->sin_addr.s_addr;
605 *(
short *)&socksBuf[8] = ((
struct sockaddr_in *)&addr)->sin_port;
606 memcpy( &socksBuf[10], data, length );
607 ret = sendto( netSocket, socksBuf, length+10, 0, &socksRelayAddr,
sizeof(socksRelayAddr) );
609 ret = sendto( netSocket, (
const char *)data, length, 0, &addr,
sizeof(addr) );
611 if( ret == SOCKET_ERROR ) {
612 int err = WSAGetLastError();
615 if( err == WSAEWOULDBLOCK ) {
638 r = WSAStartup( MAKEWORD( 1, 1 ), &winsockdata );
640 common->
Printf(
"WARNING: Winsock initialization failed, returned %d\n", r );
644 winsockInitialized =
true;
647 PIP_ADAPTER_INFO pAdapterInfo;
648 PIP_ADAPTER_INFO pAdapter =
NULL;
650 PIP_ADDR_STRING pIPAddrString;
655 foundloopback =
false;
657 pAdapterInfo = (IP_ADAPTER_INFO *)malloc(
sizeof( IP_ADAPTER_INFO ) );
658 if( !pAdapterInfo ) {
659 common->
FatalError(
"Sys_InitNetworking: Couldn't malloc( %d )",
sizeof( IP_ADAPTER_INFO ) );
661 ulOutBufLen =
sizeof( IP_ADAPTER_INFO );
665 if( GetAdaptersInfo( pAdapterInfo, &ulOutBufLen ) == ERROR_BUFFER_OVERFLOW ) {
666 free( pAdapterInfo );
667 pAdapterInfo = (IP_ADAPTER_INFO *)malloc( ulOutBufLen );
668 if( !pAdapterInfo ) {
669 common->
FatalError(
"Sys_InitNetworking: Couldn't malloc( %ld )", ulOutBufLen );
673 if( ( dwRetVal = GetAdaptersInfo( pAdapterInfo, &ulOutBufLen) ) != NO_ERROR ) {
675 common->
Printf(
"Sys_InitNetworking: GetAdaptersInfo failed (%ld).\n", dwRetVal );
677 pAdapter = pAdapterInfo;
679 common->
Printf(
"Found interface: %s %s - ", pAdapter->AdapterName, pAdapter->Description );
680 pIPAddrString = &pAdapter->IpAddressList;
681 while( pIPAddrString ) {
682 unsigned long ip_a, ip_m;
683 if( !
idStr::Icmp(
"127.0.0.1", pIPAddrString->IpAddress.String ) ) {
684 foundloopback =
true;
686 ip_a = ntohl( inet_addr( pIPAddrString->IpAddress.String ) );
687 ip_m = ntohl( inet_addr( pIPAddrString->IpMask.String ) );
690 common->
Printf(
"%s NULL netmask - skipped\n", pIPAddrString->IpAddress.String );
691 pIPAddrString = pIPAddrString->Next;
694 common->
Printf(
"%s/%s\n", pIPAddrString->IpAddress.String, pIPAddrString->IpMask.String );
700 free( pAdapterInfo );
703 pIPAddrString = pIPAddrString->Next;
705 pAdapter = pAdapter->Next;
710 common->
Printf(
"Sys_InitNetworking: adding loopback interface\n" );
715 free( pAdapterInfo );
725 if ( !winsockInitialized ) {
729 winsockInitialized =
false;
738 struct sockaddr sadr;
740 if ( !Net_StringToSockaddr( s, &sadr, doDNSResolve ) ) {
754 static int index = 0;
755 static char buf[ 4 ][ 64 ];
759 index = (index + 1) & 3;
780 common->
Printf(
"Sys_IsLANAddress: ID_NOLANADDRESS\n" );
795 p_ip = (
unsigned long *)&adr.
ip[0];
799 if( ( netint[i].ip & netint[i].
mask ) == ( ip & netint[
i].
mask ) ) {
824 if ( a.
ip[0] == b.
ip[0] && a.
ip[1] == b.
ip[1] && a.
ip[2] == b.
ip[2] && a.
ip[3] == b.
ip[3] ) {
830 common->
Printf(
"Sys_CompareNetAdrBase: bad address type\n" );
837 #define MAX_UDP_MSG_SIZE 1400
894 int len =
sizeof(
struct sockaddr_in );
960 memcpy( msg->
data, data, size );
980 memcpy( data, msg->
data, msg->
size );
1006 if (
GetPacket( from, data, size, maxSize ) ) {
1022 common->
Warning(
"idPort::SendPacket: bad address type NA_BAD - ignored" );
1039 memcpy( msg->
data, data, size );
1092 bool idTCP::Init(
const char *host,
short port ) {
1093 unsigned long _true = 1;
1094 struct sockaddr sadr;
1097 common->
Printf(
"Couldn't resolve server name \"%s\"\n", host );
1104 common->
Printf(
"\"%s\" resolved to %i.%i.%i.%i:%i\n", host,
1112 if ( (
fd = socket( AF_INET, SOCK_STREAM, 0 ) ) == INVALID_SOCKET ) {
1118 if ( connect(
fd, &sadr,
sizeof(sadr)) == SOCKET_ERROR ) {
1126 if( ioctlsocket(
fd, FIONBIO, &_true ) == SOCKET_ERROR ) {
1162 if ( ( nbytes = recv(
fd, (
char *)data, size, 0 ) ) == SOCKET_ERROR ) {
1163 if ( WSAGetLastError() == WSAEWOULDBLOCK ) {
1172 if ( nbytes == 0 ) {
1173 common->
DPrintf(
"idTCP::Read: read 0 bytes - assume connection closed\n" );
1193 if ( ( nbytes = send(
fd, (
char *)data, size, 0 ) ) == SOCKET_ERROR ) {
bool Init(const char *host, short port)
static int snPrintf(char *dest, int size, const char *fmt,...) id_attribute((format(printf
int Write(void *data, int size)
assert(prefInfo.fullscreenBtn)
idCVar net_socksEnabled("net_socksEnabled","0", CVAR_SYSTEM|CVAR_ARCHIVE|CVAR_BOOL,"")
int NET_IPSocket(const char *net_interface, int port, netadr_t *bound_to)
idCVar net_port("net_port","0", CVAR_SYSTEM|CVAR_INTEGER,"local IP port number")
void Sys_ShutdownNetworking(void)
byte data[MAX_UDP_MSG_SIZE]
idCVar net_socksPassword("net_socksPassword","", CVAR_SYSTEM|CVAR_ARCHIVE,"")
int Sys_Milliseconds(void)
idCVar net_ip("net_ip","localhost", CVAR_SYSTEM,"local IP address")
net_interface netint[MAX_INTERFACES]
int Icmp(const char *text) const
bool Net_WaitForUDPPacket(int netSocket, int timeout)
bool Net_GetUDPPacket(int netSocket, netadr_t &net_from, char *data, int &size, int maxSize)
bool GetPacket(netadr_t &from, void *data, int &size, int maxSize)
idCVar net_socksServer("net_socksServer","", CVAR_SYSTEM|CVAR_ARCHIVE,"")
void SendPacket(const netadr_t to, const void *data, int size)
idCVar net_forceDrop("net_forceDrop","0", CVAR_SYSTEM|CVAR_INTEGER,"percentage packet loss")
GLsizei GLsizei GLenum GLenum const GLvoid * data
int GetInteger(void) const
virtual void virtual void FatalError(const char *fmt,...) id_attribute((format(printf
void Net_SockadrToNetadr(struct sockaddr *s, netadr_t *a)
idBlockAlloc< udpMsg_t, 64 > udpMsgAllocator
bool Sys_IsLANAddress(const netadr_t adr)
bool InitForPort(int portNumber)
void Sys_InitNetworking(void)
int Read(void *data, int size)
GLubyte GLubyte GLubyte a
virtual void Printf(const char *fmt,...) id_attribute((format(printf
GLenum const GLvoid * addr
void Net_SendUDPPacket(int netSocket, int length, const void *data, const netadr_t to)
const char * GetString(void) const
GLdouble GLdouble GLdouble r
static WindowRef ValidModeCallbackProc inCallback OSStatus err
void Net_NetadrToSockadr(const netadr_t *a, struct sockaddr *s)
void NET_OpenSocks(int port)
const char * Sys_NetAdrToString(const netadr_t a)
GLsizei const GLcharARB const GLint * length
bool Sys_CompareNetAdrBase(const netadr_t a, const netadr_t b)
bool Sys_StringToNetAdr(const char *s, netadr_t *a, bool doDNSResolve)
idUDPLag * udpPorts[65536]
bool GetPacketBlocking(netadr_t &from, void *data, int &size, int maxSize, int timeout)
idCVar net_socksUsername("net_socksUsername","", CVAR_SYSTEM|CVAR_ARCHIVE,"")
char * NET_ErrorString(void)
virtual void DPrintf(const char *fmt,...) id_attribute((format(printf
virtual void virtual void Warning(const char *fmt,...) id_attribute((format(printf
ID_INLINE T Min(T x, T y)
void OutputDebugString(const char *text)
int sprintf(idStr &string, const char *fmt,...)
idCVar net_forceLatency("net_forceLatency","0", CVAR_SYSTEM|CVAR_INTEGER,"milliseconds latency")
idCVar net_socksPort("net_socksPort","1080", CVAR_SYSTEM|CVAR_ARCHIVE|CVAR_INTEGER,"")