📄 unix_net.c
字号:
/*
===========================================================================
Copyright (C) 1999-2005 Id Software, Inc.
This file is part of Quake III Arena source code.
Quake III Arena source code is free software; you can redistribute it
and/or modify it under the terms of the GNU General Public License as
published by the Free Software Foundation; either version 2 of the License,
or (at your option) any later version.
Quake III Arena source code is distributed in the hope that it will be
useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Foobar; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
===========================================================================
*/
// unix_net.c
#include "../game/q_shared.h"
#include "../qcommon/qcommon.h"
#include <unistd.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h> // bk001204
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/uio.h>
#include <errno.h>
#ifdef MACOS_X
#import <sys/sockio.h>
#import <net/if.h>
#import <net/if_types.h>
#import <arpa/inet.h> // for inet_ntoa()
#import <net/if_dl.h> // for 'struct sockaddr_dl'
#endif
static cvar_t *noudp;
netadr_t net_local_adr;
int ip_socket;
int ipx_socket;
#define MAX_IPS 16
static int numIP;
static byte localIP[MAX_IPS][4];
int NET_Socket (char *net_interface, int port);
char *NET_ErrorString (void);
//=============================================================================
void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
{
memset (s, 0, sizeof(*s));
if (a->type == NA_BROADCAST)
{
s->sin_family = AF_INET;
s->sin_port = a->port;
*(int *)&s->sin_addr = -1;
}
else if (a->type == NA_IP)
{
s->sin_family = AF_INET;
*(int *)&s->sin_addr = *(int *)&a->ip;
s->sin_port = a->port;
}
}
void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
{
*(int *)&a->ip = *(int *)&s->sin_addr;
a->port = s->sin_port;
a->type = NA_IP;
}
char *NET_BaseAdrToString (netadr_t a)
{
static char s[64];
Com_sprintf (s, sizeof(s), "%i.%i.%i.%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3]);
return s;
}
/*
=============
Sys_StringToAdr
idnewt
192.246.40.70
=============
*/
qboolean Sys_StringToSockaddr (const char *s, struct sockaddr *sadr)
{
struct hostent *h;
//char *colon; // bk001204 - unused
memset (sadr, 0, sizeof(*sadr));
((struct sockaddr_in *)sadr)->sin_family = AF_INET;
((struct sockaddr_in *)sadr)->sin_port = 0;
if ( s[0] >= '0' && s[0] <= '9')
{
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = inet_addr(s);
}
else
{
if (! (h = gethostbyname(s)) )
return qfalse;
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
}
return qtrue;
}
/*
=============
Sys_StringToAdr
localhost
idnewt
idnewt:28000
192.246.40.70
192.246.40.70:28000
=============
*/
qboolean Sys_StringToAdr (const char *s, netadr_t *a)
{
struct sockaddr_in sadr;
if (!Sys_StringToSockaddr (s, (struct sockaddr *)&sadr))
return qfalse;
SockadrToNetadr (&sadr, a);
return qtrue;
}
//=============================================================================
qboolean Sys_GetPacket (netadr_t *net_from, msg_t *net_message)
{
int ret;
struct sockaddr_in from;
int fromlen;
int net_socket;
int protocol;
int err;
for (protocol = 0 ; protocol < 2 ; protocol++)
{
if (protocol == 0)
net_socket = ip_socket;
else
net_socket = ipx_socket;
if (!net_socket)
continue;
fromlen = sizeof(from);
ret = recvfrom (net_socket, net_message->data, net_message->maxsize
, 0, (struct sockaddr *)&from, &fromlen);
SockadrToNetadr (&from, net_from);
// bk000305: was missing
net_message->readcount = 0;
if (ret == -1)
{
err = errno;
if (err == EWOULDBLOCK || err == ECONNREFUSED)
continue;
Com_Printf ("NET_GetPacket: %s from %s\n", NET_ErrorString(),
NET_AdrToString(*net_from));
continue;
}
if (ret == net_message->maxsize)
{
Com_Printf ("Oversize packet from %s\n", NET_AdrToString (*net_from));
continue;
}
net_message->cursize = ret;
return qtrue;
}
return qfalse;
}
//=============================================================================
void Sys_SendPacket( int length, const void *data, netadr_t to )
{
int ret;
struct sockaddr_in addr;
int net_socket;
if (to.type == NA_BROADCAST)
{
net_socket = ip_socket;
}
else if (to.type == NA_IP)
{
net_socket = ip_socket;
}
else if (to.type == NA_IPX)
{
net_socket = ipx_socket;
}
else if (to.type == NA_BROADCAST_IPX)
{
net_socket = ipx_socket;
}
else {
Com_Error (ERR_FATAL, "NET_SendPacket: bad address type");
return;
}
if (!net_socket)
return;
NetadrToSockadr (&to, &addr);
ret = sendto (net_socket, data, length, 0, (struct sockaddr *)&addr, sizeof(addr) );
if (ret == -1)
{
Com_Printf ("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(),
NET_AdrToString (to));
}
}
//=============================================================================
/*
==================
Sys_IsLANAddress
LAN clients will have their rate var ignored
==================
*/
qboolean Sys_IsLANAddress (netadr_t adr) {
int i;
if( adr.type == NA_LOOPBACK ) {
return qtrue;
}
if( adr.type == NA_IPX ) {
return qtrue;
}
if( adr.type != NA_IP ) {
return qfalse;
}
// choose which comparison to use based on the class of the address being tested
// any local adresses of a different class than the address being tested will fail based on the first byte
// Class A
if( (adr.ip[0] & 0x80) == 0x00 ) {
for ( i = 0 ; i < numIP ; i++ ) {
if( adr.ip[0] == localIP[i][0] ) {
return qtrue;
}
}
// the RFC1918 class a block will pass the above test
return qfalse;
}
// Class B
if( (adr.ip[0] & 0xc0) == 0x80 ) {
for ( i = 0 ; i < numIP ; i++ ) {
if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] ) {
return qtrue;
}
// also check against the RFC1918 class b blocks
if( adr.ip[0] == 172 && localIP[i][0] == 172 && (adr.ip[1] & 0xf0) == 16 && (localIP[i][1] & 0xf0) == 16 ) {
return qtrue;
}
}
return qfalse;
}
// Class C
for ( i = 0 ; i < numIP ; i++ ) {
if( adr.ip[0] == localIP[i][0] && adr.ip[1] == localIP[i][1] && adr.ip[2] == localIP[i][2] ) {
return qtrue;
}
// also check against the RFC1918 class c blocks
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -