Überarbeite den low leven network code

This commit is contained in:
Yamagi Burmeister 2010-10-18 06:31:35 +00:00
parent 785af02361
commit 4c14053424
3 changed files with 375 additions and 367 deletions

View File

@ -467,7 +467,6 @@ typedef struct
unsigned short port;
} netadr_t;
void NET_Init (void);
void NET_Shutdown (void);
void NET_Config (qboolean multiplayer);

View File

@ -247,7 +247,6 @@ void Qcommon_Init (int argc, char **argv)
Sys_Init ();
NET_Init ();
Netchan_Init ();
SV_Init ();

View File

@ -1,21 +1,27 @@
/*
Copyright (C) 1997-2001 Id Software, Inc.
This program 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.
This program 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 this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
* Copyright (C) 1997-2001 Id Software, Inc.
*
* This program 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.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* =======================================================================
*
* Low level network code, based upon the BSD socket api.
*
* =======================================================================
*/
#include "../common/header/common.h"
@ -34,7 +40,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
netadr_t net_local_adr;
#define LOOPBACK 0x7f000001
#define MAX_LOOPBACK 4
typedef struct
@ -56,9 +61,8 @@ int ipx_sockets[2];
int NET_Socket ( char *net_interface, int port );
char *NET_ErrorString ( void );
//=============================================================================
void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
void
NetadrToSockadr ( netadr_t *a, struct sockaddr_in *s )
{
memset( s, 0, sizeof ( *s ) );
@ -78,81 +82,88 @@ void NetadrToSockadr (netadr_t *a, struct sockaddr_in *s)
}
}
void SockadrToNetadr (struct sockaddr_in *s, netadr_t *a)
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;
}
qboolean NET_CompareAdr (netadr_t a, netadr_t b)
qboolean
NET_CompareAdr ( netadr_t a, netadr_t b )
{
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] && a.port == b.port)
return true;
return false;
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 ] ) && ( a.port == b.port ) )
{
return ( true );
}
return ( false );
}
/*
===================
NET_CompareBaseAdr
Compares without the port
===================
* Compares without the port
*/
qboolean NET_CompareBaseAdr (netadr_t a, netadr_t b)
qboolean
NET_CompareBaseAdr ( netadr_t a, netadr_t b )
{
if ( a.type != b.type )
return false;
{
return ( false );
}
if ( a.type == NA_LOOPBACK )
return true;
{
return ( true );
}
if ( a.type == NA_IP )
{
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])
return true;
return false;
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 ] ) )
{
return ( true );
}
return ( false );
}
if ( a.type == NA_IPX )
{
if ( ( memcmp( a.ipx, b.ipx, 10 ) == 0 ) )
return true;
return false;
}
return false;
{
return ( true );
}
char *NET_AdrToString (netadr_t a)
return ( false );
}
return ( false );
}
char *
NET_AdrToString ( netadr_t a )
{
static char s [ 64 ];
Com_sprintf( s, sizeof ( s ), "%i.%i.%i.%i:%i", a.ip [ 0 ], a.ip [ 1 ], a.ip [ 2 ], a.ip [ 3 ], ntohs( a.port ) );
return s;
return ( s );
}
char *NET_BaseAdrToString (netadr_t a)
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;
return ( s );
}
/*
=============
NET_StringToAdr
localhost
idnewt
idnewt:28000
192.246.40.70
192.246.40.70:28000
=============
*/
qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr)
qboolean
NET_StringToSockaddr ( char *s, struct sockaddr *sadr )
{
struct hostent *h;
char *colon;
@ -164,40 +175,36 @@ qboolean NET_StringToSockaddr (char *s, struct sockaddr *sadr)
( (struct sockaddr_in *) sadr )->sin_port = 0;
strcpy( copy, s );
// strip off a trailing :port if present
/* strip off a trailing :port if present */
for ( colon = copy; *colon; colon++ )
{
if ( *colon == ':' )
{
*colon = 0;
( (struct sockaddr_in *) sadr )->sin_port = htons( (short) atoi( colon + 1 ) );
}
}
if (copy[0] >= '0' && copy[0] <= '9')
if ( ( copy [ 0 ] >= '0' ) && ( copy [ 0 ] <= '9' ) )
{
*(int *) &( (struct sockaddr_in *) sadr )->sin_addr = inet_addr( copy );
}
else
{
if ( !( h = gethostbyname( copy ) ) )
return 0;
{
return ( 0 );
}
*(int *) &( (struct sockaddr_in *) sadr )->sin_addr = *(int *) h->h_addr_list [ 0 ];
}
return true;
return ( true );
}
/*
=============
NET_StringToAdr
localhost
idnewt
idnewt:28000
192.246.40.70
192.246.40.70:28000
=============
*/
qboolean NET_StringToAdr (char *s, netadr_t *a)
qboolean
NET_StringToAdr ( char *s, netadr_t *a )
{
struct sockaddr_in sadr;
@ -205,32 +212,27 @@ qboolean NET_StringToAdr (char *s, netadr_t *a)
{
memset( a, 0, sizeof ( *a ) );
a->type = NA_LOOPBACK;
return true;
return ( true );
}
if ( !NET_StringToSockaddr( s, (struct sockaddr *) &sadr ) )
return false;
{
return ( false );
}
SockadrToNetadr( &sadr, a );
return true;
return ( true );
}
qboolean NET_IsLocalAddress (netadr_t adr)
qboolean
NET_IsLocalAddress ( netadr_t adr )
{
return NET_CompareAdr (adr, net_local_adr);
return ( NET_CompareAdr( adr, net_local_adr ) );
}
/*
=============================================================================
LOOPBACK BUFFERS FOR LOCAL PLAYER
=============================================================================
*/
qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
qboolean
NET_GetLoopPacket ( netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message )
{
int i;
loopback_t *loop;
@ -238,10 +240,14 @@ qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_me
loop = &loopbacks [ sock ];
if ( loop->send - loop->get > MAX_LOOPBACK )
{
loop->get = loop->send - MAX_LOOPBACK;
}
if ( loop->get >= loop->send )
return false;
{
return ( false );
}
i = loop->get & ( MAX_LOOPBACK - 1 );
loop->get++;
@ -249,12 +255,11 @@ qboolean NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_me
memcpy( net_message->data, loop->msgs [ i ].data, loop->msgs [ i ].datalen );
net_message->cursize = loop->msgs [ i ].datalen;
*net_from = net_local_adr;
return true;
return ( true );
}
void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to)
void
NET_SendLoopPacket ( netsrc_t sock, int length, void *data, netadr_t to )
{
int i;
loopback_t *loop;
@ -268,9 +273,8 @@ void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to)
loop->msgs [ i ].datalen = length;
}
//=============================================================================
qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
qboolean
NET_GetPacket ( netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message )
{
int ret;
struct sockaddr_in from;
@ -280,21 +284,29 @@ qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_messag
int err;
if ( NET_GetLoopPacket( sock, net_from, net_message ) )
return true;
{
return ( true );
}
for ( protocol = 0; protocol < 2; protocol++ )
{
if ( protocol == 0 )
{
net_socket = ip_sockets [ sock ];
}
else
{
net_socket = ipx_sockets [ sock ];
}
if ( !net_socket )
{
continue;
}
fromlen = sizeof ( from );
ret = recvfrom (net_socket, net_message->data, net_message->maxsize
, 0, (struct sockaddr *)&from, &fromlen);
ret = recvfrom( net_socket, net_message->data, net_message->maxsize,
0, (struct sockaddr *) &from, &fromlen );
SockadrToNetadr( &from, net_from );
@ -302,8 +314,11 @@ qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_messag
{
err = errno;
if (err == EWOULDBLOCK || err == ECONNREFUSED)
if ( ( err == EWOULDBLOCK ) || ( err == ECONNREFUSED ) )
{
continue;
}
Com_Printf( "NET_GetPacket: %s from %s\n", NET_ErrorString(),
NET_AdrToString( *net_from ) );
continue;
@ -316,15 +331,14 @@ qboolean NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_messag
}
net_message->cursize = ret;
return true;
return ( true );
}
return false;
return ( false );
}
//=============================================================================
void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to)
void
NET_SendPacket ( netsrc_t sock, int length, void *data, netadr_t to )
{
int ret;
struct sockaddr_in addr;
@ -339,27 +353,39 @@ void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to)
if ( to.type == NA_BROADCAST )
{
net_socket = ip_sockets [ sock ];
if ( !net_socket )
{
return;
}
}
else if ( to.type == NA_IP )
{
net_socket = ip_sockets [ sock ];
if ( !net_socket )
{
return;
}
}
else if ( to.type == NA_IPX )
{
net_socket = ipx_sockets [ sock ];
if ( !net_socket )
{
return;
}
}
else if ( to.type == NA_BROADCAST_IPX )
{
net_socket = ipx_sockets [ sock ];
if ( !net_socket )
{
return;
}
}
else
{
Com_Error( ERR_FATAL, "NET_SendPacket: bad address type" );
@ -369,6 +395,7 @@ void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to)
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(),
@ -376,14 +403,8 @@ void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to)
}
}
//=============================================================================
/*
====================
NET_OpenIP
====================
*/
void NET_OpenIP (void)
void
NET_OpenIP ( void )
{
cvar_t *port, *ip;
@ -391,34 +412,26 @@ void NET_OpenIP (void)
ip = Cvar_Get( "ip", "localhost", CVAR_NOSET );
if ( !ip_sockets [ NS_SERVER ] )
{
ip_sockets [ NS_SERVER ] = NET_Socket( ip->string, port->value );
}
if ( !ip_sockets [ NS_CLIENT ] )
{
ip_sockets [ NS_CLIENT ] = NET_Socket( ip->string, PORT_ANY );
}
/*
====================
NET_OpenIPX
====================
*/
void NET_OpenIPX (void)
{
}
/*
====================
NET_Config
A single player game will only use the loopback code
====================
* A single player game will only use the loopback code
*/
void NET_Config (qboolean multiplayer)
void
NET_Config ( qboolean multiplayer )
{
int i;
if ( !multiplayer )
{ // shut down any existing sockets
{ /* shut down any existing sockets */
for ( i = 0; i < 2; i++ )
{
if ( ip_sockets [ i ] )
@ -426,6 +439,7 @@ void NET_Config (qboolean multiplayer)
close( ip_sockets [ i ] );
ip_sockets [ i ] = 0;
}
if ( ipx_sockets [ i ] )
{
close( ipx_sockets [ i ] );
@ -434,32 +448,21 @@ void NET_Config (qboolean multiplayer)
}
}
else
{ // open sockets
NET_OpenIP ();
NET_OpenIPX ();
}
}
//===================================================================
/*
====================
NET_Init
====================
*/
void NET_Init (void)
{
/* open sockets */
NET_OpenIP();
}
}
/* =================================================================== */
/*
====================
NET_Socket
====================
* ====================
* NET_Socket
* ====================
*/
int NET_Socket (char *net_interface, int port)
int
NET_Socket ( char *net_interface, int port )
{
int newsocket;
struct sockaddr_in address;
@ -469,32 +472,40 @@ int NET_Socket (char *net_interface, int port)
if ( ( newsocket = socket( PF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == -1 )
{
Com_Printf( "ERROR: UDP_OpenSocket: socket: %s", NET_ErrorString() );
return 0;
return ( 0 );
}
// make it non-blocking
/* make it non-blocking */
if ( ioctl( newsocket, FIONBIO, &_true ) == -1 )
{
Com_Printf( "ERROR: UDP_OpenSocket: ioctl FIONBIO:%s\n", NET_ErrorString() );
return 0;
return ( 0 );
}
// make it broadcast capable
/* make it broadcast capable */
if ( setsockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *) &i, sizeof ( i ) ) == -1 )
{
Com_Printf( "ERROR: UDP_OpenSocket: setsockopt SO_BROADCAST:%s\n", NET_ErrorString() );
return 0;
return ( 0 );
}
if ( !net_interface || !net_interface [ 0 ] || !strcasecmp( net_interface, "localhost" ) )
{
address.sin_addr.s_addr = INADDR_ANY;
}
else
{
NET_StringToSockaddr( net_interface, (struct sockaddr *) &address );
}
if ( port == PORT_ANY )
{
address.sin_port = 0;
}
else
{
address.sin_port = htons( (short) port );
}
address.sin_family = AF_INET;
@ -502,39 +513,32 @@ int NET_Socket (char *net_interface, int port)
{
Com_Printf( "ERROR: UDP_OpenSocket: bind: %s\n", NET_ErrorString() );
close( newsocket );
return 0;
return ( 0 );
}
return newsocket;
return ( newsocket );
}
/*
====================
NET_Shutdown
====================
*/
void NET_Shutdown (void)
void
NET_Shutdown ( void )
{
NET_Config (false); // close sockets
NET_Config( false ); /* close sockets */
}
/*
====================
NET_ErrorString
====================
*/
char *NET_ErrorString (void)
char *
NET_ErrorString ( void )
{
int code;
code = errno;
return strerror (code);
return ( strerror( code ) );
}
// sleeps msec or until net socket is ready
void NET_Sleep(int msec)
/*
* sleeps msec or until net socket is ready
*/
void
NET_Sleep ( int msec )
{
struct timeval timeout;
fd_set fdset;
@ -542,12 +546,18 @@ void NET_Sleep(int msec)
extern qboolean stdin_active;
if ( !ip_sockets [ NS_SERVER ] || ( dedicated && !dedicated->value ) )
return; // we're not a server, just run full speed
{
return; /* we're not a server, just run full speed */
}
FD_ZERO( &fdset );
if ( stdin_active )
FD_SET(0, &fdset); // stdin is processed too
FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket
{
FD_SET( 0, &fdset ); /* stdin is processed too */
}
FD_SET( ip_sockets [ NS_SERVER ], &fdset ); /* network socket */
timeout.tv_sec = msec / 1000;
timeout.tv_usec = ( msec % 1000 ) * 1000;
select( ip_sockets [ NS_SERVER ] + 1, &fdset, NULL, NULL, &timeout );