07 Jul 2008

This commit is contained in:
g-cont 2008-07-07 00:00:00 +04:00 committed by Alibek Omarov
parent bb1224b532
commit 9a4dd30714
33 changed files with 2719 additions and 2015 deletions

View File

@ -275,9 +275,12 @@ void Con_Print( const char *txt )
bool skipnotify = false;
int prev;
if( !con.initialized )
return;
// client not running
if(host.type == HOST_DEDICATED) return;
if(!con.initialized) return;
if( host.type == HOST_DEDICATED )
return;
if(!com.strncmp( txt, "[skipnotify]", 12 ))
{

View File

@ -22,6 +22,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "common.h"
#include "client.h"
void CL_PacketEvent( netadr_t from, sizebuf_t *msg )
{
}
/*
=========================================================================

File diff suppressed because it is too large Load Diff

View File

@ -1084,7 +1084,7 @@ CL_KeyEvent
Called by the system for both key up and key down events
===================
*/
void Key_Event(int key, bool down, uint time)
void Key_Event( int key, bool down, uint time )
{
char *kb;
char cmd[1024];

View File

@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "common.h"
#include "client.h"
cvar_t *freelook;
cvar_t *rcon_client_password;
cvar_t *rcon_address;
@ -37,11 +36,11 @@ cvar_t *cl_add_particles;
cvar_t *cl_add_lights;
cvar_t *cl_add_entities;
cvar_t *cl_add_blend;
cvar_t *cl_maxpackets;
cvar_t *cl_shownet;
cvar_t *cl_showmiss;
cvar_t *cl_showclamp;
cvar_t *cl_mouselook;
cvar_t *cl_paused;
cvar_t *lookspring;
@ -339,7 +338,7 @@ void CL_Rcon_f (void)
to.port = BigShort (PORT_SERVER);
}
NET_SendPacket (NS_CLIENT, strlen(message)+1, message, to);
NET_SendPacket( NS_CLIENT, strlen(message)+1, message, to);
}
@ -459,7 +458,7 @@ void CL_Packet_f (void)
}
*out = 0;
NET_SendPacket (NS_CLIENT, out-send, send, adr);
NET_SendPacket( NS_CLIENT, out-send, send, adr);
}
/*
@ -804,7 +803,7 @@ when they overflow
*/
void CL_DumpPackets (void)
{
while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
while (Sys_RecvPacket (&net_from, &net_message))
{
Msg ("dumnping a packet\n");
}
@ -812,7 +811,7 @@ void CL_DumpPackets (void)
void CL_ReadNetMessage( void )
{
while (NET_GetPacket (NS_CLIENT, &net_from, &net_message))
while (Sys_RecvPacket (&net_from, &net_message))
{
// remote command packet
if(*(int *)net_message.data == -1)
@ -1178,9 +1177,10 @@ void CL_InitLocal (void)
cl_yawspeed = Cvar_Get ("cl_yawspeed", "140", 0, "client yaw speed" );
cl_pitchspeed = Cvar_Get ("cl_pitchspeed", "150", 0, "client pitch speed" );
cl_anglespeedkey = Cvar_Get ("cl_anglespeedkey", "1.5", 0, "client anglespeed" );
cl_maxpackets = Cvar_Get( "cl_maxpackets", "30", CVAR_ARCHIVE, "number of usercmd packets" );
cl_run = Cvar_Get ("cl_run", "0", CVAR_ARCHIVE, "keep client for always run mode" );
freelook = Cvar_Get( "freelook", "1", CVAR_ARCHIVE, "enables mouse look" );
cl_mouselook = Cvar_Get( "cl_mouselook", "1", CVAR_ARCHIVE, "enables mouse look" );
lookspring = Cvar_Get ("lookspring", "0", CVAR_ARCHIVE, "allow look spring" );
lookstrafe = Cvar_Get ("lookstrafe", "0", CVAR_ARCHIVE, "allow look strafe" );
@ -1405,7 +1405,12 @@ void CL_Frame( dword time )
{
static dword extratime;
if( dedicated->integer ) return;
if( host.type == HOST_DEDICATED )
return;
// get server to client packets
Host_EventLoop();
Cbuf_Execute();
extratime += time;
@ -1414,9 +1419,6 @@ void CL_Frame( dword time )
if( extratime < 1000 / cl_maxfps->value)
return; // framerate is too high
// let the mouse activate or deactivate
CL_UpdateMouse();
// decide the simulation time
cl.time += extratime;
cls.realtime = Sys_Milliseconds();
@ -1473,7 +1475,8 @@ CL_Init
*/
void CL_Init( void )
{
if (dedicated->value) return; // nothing running on the client
if( host.type == HOST_DEDICATED )
return; // nothing running on the client
// all archived variables will now be loaded
scr_loading = Cvar_Get("scr_loading", "0", 0, "loading bar progress" );
@ -1490,6 +1493,7 @@ void CL_Init( void )
UI_Init();
SCR_Init();
CL_InitLocal();
host.cl_running = true;
}
@ -1511,6 +1515,7 @@ void CL_Shutdown(void)
UI_Shutdown();
S_Shutdown();
CL_ShutdownInput();
host.cl_running = false;
}

View File

@ -340,8 +340,8 @@ void PF_getmousepos( void )
if(!VM_ValidateArgs( "getmousepos", 0 ))
return;
PRVM_G_VECTOR(OFS_RETURN)[0] = mouse_x;
PRVM_G_VECTOR(OFS_RETURN)[1] = mouse_y;
PRVM_G_VECTOR(OFS_RETURN)[0] = cls.mouse_x;
PRVM_G_VECTOR(OFS_RETURN)[1] = cls.mouse_y;
PRVM_G_VECTOR(OFS_RETURN)[2] = 0;
}

View File

@ -67,7 +67,8 @@ typedef struct
extern char cl_weaponmodels[MAX_CLIENTWEAPONMODELS][MAX_QPATH];
extern int num_cl_weaponmodels;
#define CMD_BACKUP 64 // allow a lot of command backups for very fast systems
#define CMD_BACKUP 64 // allow a lot of command backups for very fast systems
#define CMD_MASK (CMD_BACKUP - 1)
//
// the client_t structure is wiped completely at every
@ -85,8 +86,8 @@ typedef struct
usercmd_t cmd;
usercmd_t cmds[CMD_BACKUP]; // each mesage will send several old cmds
dword cmd_time[CMD_BACKUP]; // time sent, for calculating pings
float predicted_origins[CMD_BACKUP][3]; // for debug comparing against server
int cmd_number;
float predicted_step; // for stair up smoothing
uint predicted_step_time;
@ -98,6 +99,13 @@ typedef struct
frame_t frame; // received from server
int surpressCount; // number of messages rate supressed
frame_t frames[UPDATE_BACKUP];
outpacket_t packets[PACKET_BACKUP]; // information about each packet we have sent out
// mouse current position
int mouse_x[2];
int mouse_y[2];
int mouse_step;
float mouse_sens;
// the client maintains its own idea of view angles, which are
// sent to the server each frame. It is cleared to 0 upon entering each level.
@ -230,6 +238,12 @@ typedef struct
serverinfo_t serverlist[MAX_SERVERS]; // servers to join
int numservers;
int pingtime; // servers timebase
int last_sent; // for retransmits
// cursor mouse pos for uimenu
int mouse_x;
int mouse_y;
} client_static_t;
extern client_static_t cls;
@ -298,7 +312,7 @@ extern cvar_t *cl_pitchspeed;
extern cvar_t *cl_run;
extern cvar_t *cl_anglespeedkey;
extern cvar_t *cl_maxpackets;
extern cvar_t *cl_shownet;
extern cvar_t *cl_showmiss;
extern cvar_t *cl_showclamp;
@ -310,11 +324,10 @@ extern cvar_t *ui_sensitivity;
extern cvar_t *m_pitch;
extern cvar_t *m_yaw;
extern cvar_t *m_forward;
extern cvar_t *m_side;
extern cvar_t *m_mouse;
extern cvar_t *m_forward;
extern cvar_t *cl_mouselook;
extern cvar_t *freelook;
extern cvar_t *cl_lightlevel; // FIXME HACK
@ -446,18 +459,6 @@ void CL_RequestNextDownload (void);
//
// cl_input
//
typedef struct
{
int down[2]; // key nums holding it down
unsigned downtime; // msec timestamp
unsigned msec; // msec down this frame
int state;
} kbutton_t;
extern kbutton_t in_mlook, in_klook;
extern kbutton_t in_strafe;
extern kbutton_t in_speed;
void CL_InitInput( void );
void CL_ShutdownInput( void );
void CL_UpdateMouse( void );
@ -473,9 +474,8 @@ void CL_WriteToServer (usercmd_t *cmd);
void CL_BaseMove (usercmd_t *cmd);
void IN_CenterView (void);
float CL_KeyState (kbutton_t *key);
void CL_CharEvent( int key );
void CL_MouseEvent( int dx, int dy, int time );
char *Key_KeynumToString (int keynum);
//

View File

@ -43,20 +43,6 @@ void Sys_Error( const char *error, ... )
com.error("%s", errorstring );
}
/*
================
Sys_SendKeyEvents
Send Key_Event calls
================
*/
void Sys_SendKeyEvents( void )
{
// grab frame time
host.sv_timer = Sys_GetKeyEvents();
host.cl_timer = Sys_Milliseconds();
}
/*
=======================================================================

View File

@ -26,6 +26,7 @@ extern vsound_exp_t *se;
#define MAX_ENTNUMBER 99999 // for server and client parsing
#define MAX_HEARTBEAT -99999 // connection time
#define HOST_FRAMETIME 100 // host.frametime in msecs (change with caution)
#define MAX_EVENTS 1024
//#define USE_COORD_FRAC
@ -48,6 +49,7 @@ INPUT
==============================================================
*/
#define WM_MOUSEWHEEL ( WM_MOUSELAST + 1 ) // message that will be supported by the OS
typedef enum e_keycodes
{
@ -133,15 +135,15 @@ static byte scan_to_key[128] =
0,0,0,K_F11,K_F12,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
};
// mouse support
void M_Activate( void );
void M_Event( int mstate );
#define WM_MOUSEWHEEL (WM_MOUSELAST + 1) // message that will be supported by the OS
extern int mouse_x, mouse_y, old_mouse_x, old_mouse_y, mx_accum, my_accum;
//
// input.c
//
void IN_Init( void );
void IN_Frame( void );
void IN_Shutdown( void );
void IN_MouseEvent( int mstate );
// cvars
extern cvar_t *dedicated;
extern cvar_t *host_serverstate;
extern cvar_t *host_frametime;
extern cvar_t *cm_paused;
@ -184,17 +186,23 @@ typedef struct host_parm_s
jmp_buf abortframe; // abort current frame
string finalmsg; // server shutdown final message
dword framecount; // global framecount
uint sv_timer; // SV_Input msg time
uint cl_timer; // CL_Input msg time
uint old_cl_timer; // save old msg time
HWND hWnd; // main window
int developer; // show all developer's message
bool paused; // freeze server
bool stuffcmdsrun; // sturtup script
dword framecount; // global framecount
dword frametime[2]; // second value is old frametime
int events_head;
int events_tail;
sys_event_t events[MAX_EVENTS];
file_t *journal; // journal file
// get rid of this
bool sv_running; // server is running ?
bool cl_running; // client is running ?
} host_parm_t;
extern host_parm_t host;
@ -206,6 +214,7 @@ void Host_SetServerState( int state );
int Host_ServerState( void );
float Host_FrameTime( void );
void Host_AbortCurrentFrame( void );
dword Host_EventLoop( void );
// message functions
void Host_Print(const char *txt);
@ -228,10 +237,12 @@ CLIENT / SERVER SYSTEMS
void CL_Init( void );
void CL_Shutdown( void );
void CL_Frame( dword time );
void CL_PacketEvent( netadr_t from, sizebuf_t *msg );
void SV_Init( void );
void SV_Shutdown( bool reconnect );
void SV_Frame( dword time );
void SV_PacketEvent( netadr_t from, sizebuf_t *msg );
/*
==============================================================
@ -423,7 +434,6 @@ bool Cmd_GetMusicList(const char *s, char *completedname, int length );
bool Cmd_GetSoundList(const char *s, char *completedname, int length );
bool Cmd_CheckMapsList( void );
void Sys_Error( const char *msg, ... );
void Sys_SendKeyEvents( void );
// get rid of this
float frand(void); // 0 to 1

View File

@ -22,6 +22,7 @@ launch_exp_t DLLEXPORT *CreateAPI( stdlib_api_t *input, void *unused )
Host.Free = Host_Free;
Host.Cmd = Cmd_ForwardToServer;
Host.CPrint = Host_Print;
Host.SZInit = SZ_Init;
return &Host;
}

View File

@ -190,6 +190,10 @@ SOURCE=.\host.c
# End Source File
# Begin Source File
SOURCE=.\input.c
# End Source File
# Begin Source File
SOURCE=.\network\net_chan.c
# End Source File
# Begin Source File
@ -198,10 +202,6 @@ SOURCE=.\network\net_msg.c
# End Source File
# Begin Source File
SOURCE=.\network\net_wins.c
# End Source File
# Begin Source File
SOURCE=.\server\sv_client.c
# End Source File
# Begin Source File

View File

@ -25,7 +25,7 @@ dll_info_t vprogs_dll = { "vprogs.dll", NULL, "CreateAPI", NULL, NULL, true, siz
dll_info_t vsound_dll = { "vsound.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(vsound_exp_t) };
cvar_t *timescale;
cvar_t *dedicated;
cvar_t *host_journal;
cvar_t *host_serverstate;
cvar_t *host_frametime;
cvar_t *host_cheats;
@ -35,6 +35,8 @@ cvar_t *r_xpos; // X coordinate of window position
cvar_t *r_ypos; // Y coordinate of window position
cvar_t *cm_paused;
cvar_t *host_maxfps;
/*
=======
Host_MapKey
@ -85,29 +87,6 @@ static int Host_MapKey( int key )
}
}
void Host_InitCommon( uint funcname, int argc, char **argv )
{
char dev_level[4];
newcom = com;
// overload some funcs
newcom.error = Host_Error;
// check developer mode
if(FS_GetParmFromCmdLine("-dev", dev_level ))
host.developer = com.atoi(dev_level);
// TODO: init basedir here
FS_LoadGameInfo("gameinfo.txt");
zonepool = Mem_AllocPool("Zone Engine");
}
void Host_FreeCommon( void )
{
Mem_FreePool( &zonepool );
}
void Host_InitPhysic( void )
{
static physic_imp_t pi;
@ -312,11 +291,308 @@ void VID_Init( void )
Host_InitSound();
}
/*
=================
Host_InitJournaling
=================
*/
void Host_InitJournaling( void )
{
host_journal = Cvar_Get( "host_journal", "0", CVAR_SYSTEMINFO, "journaling system events (1 = record, 2 = playback)" );
if( !host_journal->integer ) return;
if( host_journal->integer == 1 )
{
MsgDev( D_NOTE, "Host_InitJournaling: record mode\n" );
host.journal = FS_Open( "vprogs/events.dat", "wb" );
}
else if( host_journal->integer == 2 )
{
MsgDev( D_NOTE, "Host_InitJournaling: playback mode\n" );
host.journal = FS_Open( "vprogs/events.dat", "rb" );
}
}
/*
=================
Host_GetRealEvent
=================
*/
sys_event_t Host_GetRealEvent( void )
{
sys_event_t ev;
int r;
// either get an event from the system or the journal file
if( host_journal->integer == 2 )
{
r = FS_Read( host.journal, &ev, sizeof(ev) );
if( r != sizeof(ev))
{
Sys_Error( "Host_GetRealEvent: error reading from journal file\n" );
return ev;
}
if( ev.length )
{
ev.data = Z_Malloc( ev.length );
r = FS_Read( host.journal, ev.data, ev.length );
if( r != ev.length )
{
Sys_Error( "Host_GetRealEvent: error reading from journal file\n" );
return ev;
}
}
}
else
{
ev = Sys_GetEvent();
// write the journal value out if needed
if( host_journal->integer == 1 )
{
r = FS_Write( host.journal, &ev, sizeof(ev));
if( r != sizeof(ev) )
{
Sys_Error( "Host_GetRealEvent: error writing to journal file" );
return ev;
}
if( ev.length )
{
r = FS_Write( host.journal, ev.data, ev.length );
if( r != ev.length )
{
Sys_Error( "Host_GetRealEvent: error writing to journal file" );
return ev;
}
}
}
}
return ev;
}
/*
=================
Host_InitPushEvent
=================
*/
void Host_InitPushEvent( void )
{
memset( host.events, 0, sizeof(host.events));
host.events_head = 0;
host.events_tail = 0;
}
/*
=================
Host_PushEvent
=================
*/
void Host_PushEvent( sys_event_t *event )
{
sys_event_t *ev;
static bool overflow = false;
ev = &host.events[host.events_head & (MAX_EVENTS-1)];
if( host.events_head - host.events_tail >= MAX_EVENTS )
{
if( !overflow )
{
MsgDev( D_WARN, "Host_PushEvent overflow\n" );
overflow = true;
}
if( ev->data ) Mem_Free( ev->data );
host.events_tail++;
}
else overflow = false;
*ev = *event;
host.events_head++;
}
/*
=================
Host_GetEvent
=================
*/
sys_event_t Host_GetEvent( void )
{
if( host.events_head > host.events_tail )
{
host.events_tail++;
return host.events[(host.events_tail - 1)&(MAX_EVENTS-1)];
}
return Host_GetRealEvent();
}
/*
=================
Host_EventLoop
Returns last event time
=================
*/
dword Host_EventLoop( void )
{
sys_event_t ev;
netadr_t ev_from;
byte bufData[MAX_MSGLEN];
sizebuf_t buf;
SZ_Init( &buf, bufData, sizeof( bufData ));
while( 1 )
{
ev = Host_GetEvent();
// if no more events are available
if( ev.type == SE_NONE )
{
// manually send packet events for the loopback channel
while( NET_GetLoopPacket( NS_CLIENT, &ev_from, &buf ))
{
CL_PacketEvent( ev_from, &buf );
}
while( NET_GetLoopPacket( NS_SERVER, &ev_from, &buf ))
{
SV_PacketEvent( ev_from, &buf );
}
return ev.time;
}
switch ( ev.type )
{
case SE_NONE:
break;
case SE_KEY:
Key_Event( ev.value[0], ev.value[1], ev.time );
break;
case SE_CHAR:
CL_CharEvent( ev.value[0] );
break;
case SE_MOUSE:
CL_MouseEvent( ev.value[0], ev.value[1], ev.time );
break;
case SE_CONSOLE:
Cbuf_AddText( va( "%s\n", ev.data ));
break;
case SE_PACKET:
ev_from = *(netadr_t *)ev.data;
buf.cursize = ev.length - sizeof( ev_from );
// we must copy the contents of the message out, because
// the event buffers are only large enough to hold the
// exact payload, but channel messages need to be large
// enough to hold fragment reassembly
if((uint)buf.cursize > buf.maxsize )
{
MsgDev( D_WARN, "Host_EventLoop: oversize packet\n");
continue;
}
Mem_Copy( buf.data, (byte *)((netadr_t *)ev.data + 1), buf.cursize );
if ( host.sv_running ) SV_PacketEvent( ev_from, &buf );
else CL_PacketEvent( ev_from, &buf );
break;
default:
Host_Error( "Host_EventLoop: bad event type %i", ev.type );
break;
}
if( ev.data ) Mem_Free( ev.data );
}
return 0; // never reached
}
/*
================
Host_Milliseconds
Can be used for profiling, but will be journaled accurately
================
*/
int Host_Milliseconds( void )
{
sys_event_t ev;
// get events and push them until we get a null event with the current time
do {
ev = Host_GetRealEvent();
if( ev.type != SE_NONE )
Host_PushEvent( &ev );
} while( ev.type != SE_NONE );
return ev.time;
}
/*
================
Host_ModifyMsec
================
*/
int Host_ModifyTime( int msec )
{
int clamp_time;
// modify time for debugging values
if( timescale->value ) msec *= timescale->value;
if( msec < 1 && timescale->value ) msec = 1;
if( host.type == HOST_DEDICATED )
{
// dedicated servers don't want to clamp for a much longer
// period, because it would mess up all the client's views of time.
if( msec > 500 ) MsgDev( D_WARN, "Host_ModifyTimer: %i msec frame time\n", msec );
clamp_time = 5000;
}
else
{
// for local single player gaming
// we may want to clamp the time to prevent players from
// flying off edges when something hitches.
clamp_time = 200;
}
if( msec > clamp_time ) msec = clamp_time;
return msec;
}
/*
=================
Host_Frame
=================
*/
void Host_Frame( void )
{
dword time, min_time;
static int last_time;
if( setjmp(host.abortframe))
return;
rand(); // keep the random time dependent
// we may want to spin here if things are going too fast
if( host.type != HOST_DEDICATED && host_maxfps->integer > 0 )
min_time = 1000 / host_maxfps->integer;
else min_time = 1;
do {
host.frametime[0] = Host_EventLoop();
if( last_time > host.frametime[0] )
last_time = host.frametime[0];
time = host.frametime[0] - last_time;
} while( time < min_time );
Cbuf_Execute();
last_time = host.frametime[0];
time = Host_ModifyTime( time );
SV_Frame( time ); // server frame
CL_Frame( time ); // client frame
host.framecount++;
}
/*
void Host_Frame( dword time )
{
char *s;
@ -344,6 +620,7 @@ void Host_Frame( dword time )
host.framecount++;
}
*/
/*
====================
@ -361,13 +638,13 @@ long Host_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
case WM_MOUSEWHEEL:
if((short)HIWORD(wParam) > 0)
{
Key_Event( K_MWHEELUP, true, host.sv_timer );
Key_Event( K_MWHEELUP, false, host.sv_timer );
Sys_QueEvent( -1, SE_KEY, K_MWHEELUP, true, 0, NULL );
Sys_QueEvent( -1, SE_KEY, K_MWHEELUP, false, 0, NULL );
}
else
{
Key_Event( K_MWHEELDOWN, true, host.sv_timer );
Key_Event( K_MWHEELDOWN, false, host.sv_timer );
Sys_QueEvent( -1, SE_KEY, K_MWHEELDOWN, true, 0, NULL );
Sys_QueEvent( -1, SE_KEY, K_MWHEELDOWN, false, 0, NULL );
}
break;
case WM_CREATE:
@ -392,7 +669,6 @@ long Host_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
if( host.state == HOST_FRAME )
{
M_Activate();
SetForegroundWindow( hWnd );
ShowWindow( hWnd, SW_RESTORE );
}
@ -419,7 +695,6 @@ long Host_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
Cvar_SetValue( "r_ypos", yPos + r.top);
r_xpos->modified = false;
r_ypos->modified = false;
M_Activate();
}
break;
case WM_LBUTTONDOWN:
@ -432,27 +707,27 @@ long Host_WndProc( void *hWnd, uint uMsg, uint wParam, long lParam )
if(wParam & MK_LBUTTON) temp |= 1;
if(wParam & MK_RBUTTON) temp |= 2;
if(wParam & MK_MBUTTON) temp |= 4;
M_Event( temp );
IN_MouseEvent( temp );
break;
case WM_SYSCOMMAND:
if( wParam == SC_SCREENSAVE ) return 0;
break;
case WM_SYSKEYDOWN:
if( wParam == 13 && r_fullscreen)
if( wParam == 13 && r_fullscreen )
{
Cvar_SetValue( "fullscreen", !r_fullscreen->value );
return 0;
}
// intentional fallthrough
case WM_KEYDOWN:
Key_Event( Host_MapKey( lParam ), true, host.sv_timer);
Sys_QueEvent( -1, SE_KEY, Host_MapKey( lParam ), true, 0, NULL );
break;
case WM_SYSKEYUP:
case WM_KEYUP:
Key_Event( Host_MapKey( lParam ), false, host.sv_timer);
Sys_QueEvent( -1, SE_KEY, Host_MapKey( lParam ), false, 0, NULL );
break;
case WM_CHAR:
CL_CharEvent( wParam );
Sys_QueEvent( -1, SE_CHAR, wParam, 0, 0, NULL );
break;
}
return DefWindowProc( hWnd, uMsg, wParam, lParam );
@ -541,6 +816,35 @@ static void Host_Crash_f (void)
*(int *)0 = 0xffffffff;
}
void Host_InitCommon( uint funcname, int argc, char **argv )
{
char dev_level[4];
newcom = com;
// overload some funcs
newcom.error = Host_Error;
// check developer mode
if(FS_GetParmFromCmdLine("-dev", dev_level ))
host.developer = com.atoi(dev_level);
Host_InitPushEvent();
Host_InitJournaling();
// TODO: init basedir here
FS_LoadGameInfo("gameinfo.txt");
zonepool = Mem_AllocPool("Zone Engine");
IN_Init();
}
void Host_FreeCommon( void )
{
IN_Shutdown();
Mem_FreePool( &zonepool );
}
/*
=================
Host_Init
@ -575,18 +879,16 @@ void Host_Init (uint funcname, int argc, char **argv)
Cmd_AddCommand ("error", Host_Error_f, "just throw a fatal error to test shutdown procedures" );
Cmd_AddCommand ("crash", Host_Crash_f, "a way to force a bus error for development reasons");
}
host_maxfps = Cvar_Get( "host_maxfps", "100", CVAR_ARCHIVE, "host fps upper limit" );
cm_paused = Cvar_Get("cm_paused", "0", 0, "physics module pause" );
host_frametime = Cvar_Get ("host_frametime", "0.1", 0, "host frametime" );
host_serverstate = Cvar_Get ("host_serverstate", "0", 0, "displays current server state" );
timescale = Cvar_Get ("timescale", "1", 0, "physics world timescale" );
if(host.type == HOST_DEDICATED) dedicated = Cvar_Get ("dedicated", "1", CVAR_INIT, "currently server is in dedicated mode" );
else dedicated = Cvar_Get ("dedicated", "0", CVAR_INIT, "currently server is in shared mode" );
s = va("^1Xash %g ^3%s", GI->version, buildstring );
Cvar_Get( "version", s, CVAR_SERVERINFO|CVAR_INIT, "engine current version" );
if(dedicated->value) Cmd_AddCommand ("quit", Sys_Quit, "quit the game" );
if( host.type == HOST_DEDICATED ) Cmd_AddCommand ("quit", Sys_Quit, "quit the game" );
NET_Init();
Netchan_Init();
@ -595,6 +897,8 @@ void Host_Init (uint funcname, int argc, char **argv)
SV_Init();
CL_Init();
host.frametime[0] = Host_Milliseconds();
}
/*
@ -604,21 +908,11 @@ Host_Main
*/
void Host_Main( void )
{
static dword time, oldtime, newtime;
oldtime = Sys_Milliseconds(); // initialize timer
// main window message loop
while( host.type != HOST_OFFLINE )
{
do {
newtime = Sys_Milliseconds();
time = newtime - oldtime;
} while( time < 1 );
// engine frame
Host_Frame( time );
oldtime = newtime;
IN_Frame();
Host_Frame();
}
}

200
engine/input.c Normal file
View File

@ -0,0 +1,200 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// input.c - win32 input devices
//=======================================================================
#include "common.h"
#include "client.h"
bool in_mouseactive; // false when not focus app
bool in_restore_spi;
bool in_mouseinitialized;
int in_originalmouseparms[3];
int in_newmouseparms[3] = { 0, 0, 1 };
bool in_mouseparmsvalid;
int in_mouse_buttons;
int in_mouse_oldbuttonstate;
int window_center_x, window_center_y;
RECT window_rect;
POINT cur_pos;
/*
===========
IN_StartupMouse
===========
*/
void IN_StartupMouse( void )
{
cvar_t *cv;
cv = Cvar_Get( "in_initmouse", "1", CVAR_SYSTEMINFO, "allow mouse device" );
if ( !cv->value ) return;
in_mouse_buttons = 3;
in_mouseparmsvalid = SystemParametersInfo( SPI_GETMOUSE, 0, in_originalmouseparms, 0 );
in_mouseinitialized = true;
}
/*
===========
IN_ActivateMouse
Called when the window gains focus or changes in some way
===========
*/
void IN_ActivateMouse( void )
{
int width, height;
if( !in_mouseinitialized )
return;
if( in_mouseactive ) return;
in_mouseactive = true;
if( in_mouseparmsvalid )
in_restore_spi = SystemParametersInfo( SPI_SETMOUSE, 0, in_newmouseparms, 0 );
width = GetSystemMetrics(SM_CXSCREEN);
height = GetSystemMetrics(SM_CYSCREEN);
GetWindowRect( host.hWnd, &window_rect);
if (window_rect.left < 0) window_rect.left = 0;
if (window_rect.top < 0) window_rect.top = 0;
if (window_rect.right >= width) window_rect.right = width - 1;
if (window_rect.bottom >= height-1) window_rect.bottom = height - 1;
window_center_x = (window_rect.right + window_rect.left)/2;
window_center_y = (window_rect.top + window_rect.bottom)/2;
SetCursorPos( window_center_x, window_center_y );
SetCapture( host.hWnd );
ClipCursor(&window_rect);
while( ShowCursor(false) >= 0 );
}
/*
===========
IN_DeactivateMouse
Called when the window loses focus
===========
*/
void IN_DeactivateMouse( void )
{
if( !in_mouseinitialized || !in_mouseactive )
return;
if( in_restore_spi )
SystemParametersInfo( SPI_SETMOUSE, 0, in_originalmouseparms, 0 );
in_mouseactive = false;
ClipCursor( NULL );
ReleaseCapture();
while( ShowCursor(true) < 0 );
}
/*
================
IN_Mouse
================
*/
void IN_MouseMove( void )
{
POINT current_pos;
int mx, my;
if( !in_mouseinitialized )
return;
// find mouse movement
GetCursorPos( &current_pos );
// force the mouse to the center, so there's room to move
SetCursorPos( window_center_x, window_center_y );
mx = current_pos.x - window_center_x;
my = current_pos.y - window_center_y;
if( !mx && !my ) return;
Sys_QueEvent( 0, SE_MOUSE, mx, my, 0, NULL );
}
/*
===========
IN_MouseEvent
===========
*/
void IN_MouseEvent( int mstate )
{
int i;
if( !in_mouseinitialized )
return;
// perform button actions
for( i = 0; i < in_mouse_buttons; i++ )
{
if((mstate & (1<<i)) && !(in_mouse_oldbuttonstate & (1<<i)) )
{
Sys_QueEvent( -1, SE_KEY, K_MOUSE1 + i, true, 0, NULL );
}
if ( !(mstate & (1<<i)) && (in_mouse_oldbuttonstate & (1<<i)) )
{
Sys_QueEvent( -1, SE_KEY, K_MOUSE1 + i, false, 0, NULL );
}
}
in_mouse_oldbuttonstate = mstate;
}
/*
===========
IN_Shutdown
===========
*/
void IN_Shutdown( void )
{
IN_DeactivateMouse();
}
/*
===========
IN_Init
===========
*/
void IN_Init( void )
{
IN_StartupMouse();
}
/*
==================
IN_Frame
Called every frame, even if not generating commands
==================
*/
void IN_Frame( void )
{
if( !in_mouseinitialized )
return;
if( host.state != HOST_FRAME )
{
IN_DeactivateMouse();
return;
}
// uimenu.dat using mouse
if((!cl.refresh_prepped && cls.key_dest != key_menu) || cls.key_dest == key_console )
{
if(!Cvar_VariableValue( "fullscreen"))
{
IN_DeactivateMouse();
return;
}
}
IN_ActivateMouse();
IN_MouseMove();
}

View File

@ -23,7 +23,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
/*
packet header
packet header (quake2)
-------------
31 sequence
1 does this message contain a reliable payload
@ -31,35 +31,17 @@ packet header
1 acknowledge receipt of even/odd message
16 qport
The remote connection never knows if it missed a reliable message, the
local side detects that it has been dropped by seeing a sequence acknowledge
higher thatn the last reliable sequence, but without the correct evon/odd
bit for the reliable set.
packet header (quake3)
-------------
4 outgoing sequence. high bit will be set if this is a fragmented message
[2 qport (only for client to server)]
[2 fragment start byte]
[2 fragment length. if < FRAGMENT_SIZE, this is the last fragment]
If the sender notices that a reliable message has been dropped, it will be
retransmitted. It will not be retransmitted again until a message after
the retransmit has been acknowledged and the reliable still failed to get there.
if the sequence number is -1, the packet should be handled without a netcon
The reliable message can be added to at any time by doing
MSG_Write* (&netchan->message, <data>).
If the message buffer is overflowed, either by a single message, or by
multiple frames worth piling up while the last reliable transmit goes
unacknowledged, the netchan signals a fatal error.
Reliable messages are always placed first in a packet, then the unreliable
message is included if there is sufficient room.
To the receiver, there is no distinction between the reliable and unreliable
parts of the message, they are just processed out as a single larger message.
Illogical packet sequence numbers cause the packet to be dropped, but do
not kill the connection. This, combined with the tight window of valid
reliable acknowledgement numbers provides protection against malicious
address spoofing.
if the sequence number is -1, the packet should be handled as an out-of-band
message instead of as part of a netcon.
All fragments will have the same sequence numbers.
The qport field is a workaround for bad address translating routers that
sometimes remap the client's source port on a packet during gameplay.
@ -67,21 +49,40 @@ sometimes remap the client's source port on a packet during gameplay.
If the base part of the net address matches and the qport matches, then the
channel matches even if the IP port differs. The IP port should be updated
to the new value before sending out any replies.
If there is no information that needs to be transfered on a given frame,
such as during the connection stage while waiting for the client to load,
then a packet only needs to be delivered if there is something in the
unacknowledged reliable
*/
cvar_t *showpackets;
cvar_t *showdrop;
cvar_t *qport;
#define MAX_PACKETLEN 1400 // max size of a network packet
#define FRAGMENT_SIZE (MAX_PACKETLEN - 100)
#define PACKET_HEADER 10 // two ints and a short
#define MAX_LOOPBACK 16
#define FRAGMENT_BIT (1<<31)
netadr_t net_from;
sizebuf_t net_message;
byte net_message_buffer[MAX_MSGLEN];
cvar_t *showpackets;
cvar_t *showdrop;
cvar_t *qport;
static char *netsrcString[2] =
{
"client",
"server"
};
typedef struct
{
byte data[MAX_PACKETLEN];
int datalen;
} loopmsg_t;
typedef struct
{
loopmsg_t msgs[MAX_LOOPBACK];
int get, send;
} loopback_t;
loopback_t loopbacks[2];
netadr_t net_from;
sizebuf_t net_message;
byte net_message_buffer[MAX_MSGLEN];
/*
===============
@ -89,38 +90,266 @@ Netchan_Init
===============
*/
void Netchan_Init (void)
void Netchan_Init( void )
{
int port;
// pick a port value that should be nice and random
port = RANDOM_LONG(1, 65535);
int port = RANDOM_LONG( 1, 65535 );
showpackets = Cvar_Get ("showpackets", "0", 0, "show network packets" );
showdrop = Cvar_Get ("showdrop", "0", 0, "show packets that are dropped" );
qport = Cvar_Get( "qport", va("%i", port), CVAR_INIT, "current netport" );
showpackets = Cvar_Get ("net_showpackets", "0", CVAR_TEMP, "show network packets" );
showdrop = Cvar_Get ("net_showdrop", "0", CVAR_TEMP, "show packets that are dropped" );
qport = Cvar_Get ("net_qport", va("%i", port), CVAR_INIT, "current quake netport" );
}
/*
==============
Netchan_Setup
called to open a channel to a remote system
==============
*/
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport )
{
memset( chan, 0, sizeof(*chan));
chan->sock = sock;
chan->remote_address = adr;
chan->qport = qport;
chan->incoming_sequence = 0;
chan->outgoing_sequence = 1;
}
/*
=================
Netchan_TransmitNextFragment
Send one fragment of the current message
=================
*/
void Netchan_TransmitNextFragment( netchan_t *chan )
{
sizebuf_t send;
byte send_buf[MAX_PACKETLEN];
int fragment_length;
// write the packet header
SZ_Init( &send, send_buf, sizeof(send_buf));
MSG_WriteLong( &send, chan->outgoing_sequence | FRAGMENT_BIT );
// send the qport if we are a client
if( chan->sock == NS_CLIENT )
{
MSG_WriteShort( &send, qport->integer );
}
// copy the reliable message to the packet first
fragment_length = FRAGMENT_SIZE;
if( chan->unsent_fragment_start + fragment_length > chan->unsent_length )
{
fragment_length = chan->unsent_length - chan->unsent_fragment_start;
}
MSG_WriteShort( &send, chan->unsent_fragment_start );
MSG_WriteShort( &send, fragment_length );
MSG_WriteData( &send, chan->unsent_buffer + chan->unsent_fragment_start, fragment_length );
// send the datagram
NET_SendPacket( chan->sock, send.cursize, send.data, chan->remote_address );
if( showpackets->integer )
MsgDev( D_INFO, "%s send %4i : s=%i fragment=%i,%i\n", netsrcString[chan->sock], send.cursize, chan->outgoing_sequence, chan->unsent_fragment_start, fragment_length );
chan->unsent_fragment_start += fragment_length;
if ( chan->unsent_fragment_start == chan->unsent_length && fragment_length != FRAGMENT_SIZE )
{
chan->outgoing_sequence++;
chan->unsent_fragments = false;
}
}
/*
===============
Netchan_Transmit
Sends a message to a connection, fragmenting if necessary
A 0 length will still generate a packet.
================
*/
void Netchan_Transmit( netchan_t *chan, int length, const byte *data )
{
sizebuf_t send;
byte send_buf[MAX_PACKETLEN];
if( length > MAX_MSGLEN ) Host_Error( "Netchan_Transmit: %i > MAX_MSGLEN\n", length );
chan->unsent_fragment_start = 0;
// fragment large reliable messages
if( length >= FRAGMENT_SIZE )
{
chan->unsent_fragments = true;
chan->unsent_length = length;
Mem_Copy( chan->unsent_buffer, data, length );
// only send the first fragment now
Netchan_TransmitNextFragment( chan );
return;
}
// write the packet header
SZ_Init( &send, send_buf, sizeof(send_buf));
MSG_WriteLong( &send, chan->outgoing_sequence );
chan->outgoing_sequence++;
// send the qport if we are a client
if( chan->sock == NS_CLIENT )
MSG_WriteShort( &send, qport->integer );
MSG_WriteData( &send, data, length );
NET_SendPacket( chan->sock, send.cursize, send.data, chan->remote_address ); // send the datagram
if( showpackets->integer )
MsgDev( D_INFO, "%s send %4i : s=%i ack=%i\n", netsrcString[chan->sock], send.cursize, chan->outgoing_sequence - 1, chan->incoming_sequence );
}
/*
=================
Netchan_Process
Returns qfalse if the message should not be processed due to being
out of order or a fragment.
Msg must be large enough to hold MAX_MSGLEN, because if this is the
final fragment of a multi-part message, the entire thing will be
copied out.
=================
*/
bool Netchan_Process( netchan_t *chan, sizebuf_t *msg )
{
int sequence;
int qport;
int fragment_start = 0, fragment_length = 0;
bool fragmented = false;
// get sequence numbers
MSG_BeginReading( msg );
sequence = MSG_ReadLong( msg );
// check for fragment information
if( sequence & FRAGMENT_BIT )
{
sequence &= ~FRAGMENT_BIT;
fragmented = true;
}
// read the qport if we are a server
if( chan->sock == NS_SERVER )
qport = MSG_ReadShort( msg );
// read the fragment information
if( fragmented )
{
fragment_start = MSG_ReadShort( msg );
fragment_length = MSG_ReadShort( msg );
}
if( showpackets->integer )
{
if( fragmented )
MsgDev( D_INFO, "%s recv %4i : s=%i fragment=%i,%i\n", netsrcString[chan->sock], msg->cursize, sequence, fragment_start, fragment_length );
else MsgDev( D_INFO, "%s recv %4i : s=%i\n", netsrcString[chan->sock], msg->cursize, sequence );
}
// discard out of order or duplicated packets
if( sequence <= chan->incoming_sequence )
{
if( showdrop->integer || showpackets->integer )
MsgDev( D_INFO, "%s:Out of order packet %i at %i\n", NET_AdrToString(chan->remote_address), sequence, chan->incoming_sequence );
return false;
}
// dropped packets don't keep the message from being used
chan->dropped = sequence - (chan->incoming_sequence + 1);
if( chan->dropped > 0 )
{
if( showdrop->integer || showpackets->integer )
MsgDev( D_INFO, "%s:Dropped %i packets at %i\n", NET_AdrToString( chan->remote_address ), chan->dropped, sequence );
}
// if this is the final framgent of a reliable message, bump incoming_reliable_sequence
if( fragmented )
{
if( sequence != chan->fragment_sequence )
{
chan->fragment_sequence = sequence;
chan->fragment_length = 0;
}
// if we missed a fragment, dump the message
if( fragment_start != chan->fragment_length )
{
if( showdrop->integer || showpackets->integer )
MsgDev( D_INFO, "%s:Dropped a message fragment\n", NET_AdrToString( chan->remote_address ), sequence);
return false;
}
// copy the fragment to the fragment buffer
if( fragment_length < 0 || msg->readcount + fragment_length > msg->cursize || chan->fragment_length + fragment_length > sizeof( chan->fragment_buffer ))
{
if( showdrop->integer || showpackets->integer )
MsgDev( D_INFO, "%s:illegal fragment length\n", NET_AdrToString (chan->remote_address ));
return false;
}
Mem_Copy( chan->fragment_buffer + chan->fragment_length, msg->data + msg->readcount, fragment_length );
chan->fragment_length += fragment_length;
// if this wasn't the last fragment, don't process anything
if( fragment_length == FRAGMENT_SIZE )
return false;
if( chan->fragment_length > msg->maxsize )
{
MsgDev( D_INFO, "%s:fragmentLength %i > msg->maxsize\n", NET_AdrToString (chan->remote_address ), chan->fragment_length );
return false;
}
// copy the full message over the partial fragment
// make sure the sequence number is still there
*(int *)msg->data = LittleLong( sequence );
Mem_Copy( msg->data + 4, chan->fragment_buffer, chan->fragment_length );
msg->cursize = chan->fragment_length + 4;
chan->fragment_length = 0;
msg->readcount = 4; // past the sequence number
msg->bit = 32; // past the sequence number
// clients were not acking fragmented messages
chan->incoming_sequence = sequence;
return true;
}
// the message can now be read from the current message pointer
chan->incoming_sequence = sequence;
return true;
}
/*
===============
Netchan_OutOfBand
Sends an out-of-band datagram
Sends a data message in an out-of-band datagram (only used for "connect")
================
*/
void Netchan_OutOfBand (int net_socket, netadr_t adr, int length, byte *data)
void Netchan_OutOfBand( netsrc_t sock, netadr_t adr, int length, byte *data )
{
sizebuf_t send;
byte send_buf[MAX_MSGLEN];
byte send_buf[MAX_MSGLEN];
// write the packet header
SZ_Init (&send, send_buf, sizeof(send_buf));
MSG_WriteLong (&send, -1); // -1 sequence means out of band
SZ_Write(&send, data, length);
SZ_Init( &send, send_buf, sizeof(send_buf));
MSG_WriteLong( &send, 0xffffffff ); // -1 sequence means out of band
SZ_Write( &send, data, length );
// send the datagram
NET_SendPacket (net_socket, send.cursize, send.data, adr);
NET_SendPacket( sock, send.cursize, send.data, adr );
}
/*
@ -130,246 +359,184 @@ Netchan_OutOfBandPrint
Sends a text message in an out-of-band datagram
================
*/
void Netchan_OutOfBandPrint (int net_socket, netadr_t adr, char *format, ...)
void Netchan_OutOfBandPrint( netsrc_t sock, netadr_t adr, const char *format, ... )
{
va_list argptr;
static char string[MAX_MSGLEN - 4];
static char string[MAX_MSGLEN - 4];
va_start (argptr, format);
com.vsprintf (string, format,argptr);
va_end (argptr);
va_start( argptr, format );
com.vsprintf( string, format, argptr );
va_end( argptr );
Netchan_OutOfBand (net_socket, adr, strlen(string), (byte *)string);
Netchan_OutOfBand( sock, adr, com.strlen(string), (byte *)string );
}
/*
==============
Netchan_Setup
=============================================================================
called to open a channel to a remote system
==============
NET MISC HELPER FUNCTIONS
=============================================================================
*/
void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport)
{
memset (chan, 0, sizeof(*chan));
chan->sock = sock;
chan->remote_address = adr;
chan->qport = qport;
chan->last_received = Sys_Milliseconds();
chan->incoming_sequence = 0;
chan->outgoing_sequence = 1;
SZ_Init (&chan->message, chan->message_buf, sizeof(chan->message_buf));
}
/*
===============
Netchan_CanReliable
===================
NET_CompareBaseAdr
Returns true if the last reliable message has acked
================
Compares without the port
===================
*/
bool Netchan_CanReliable (netchan_t *chan)
bool NET_CompareBaseAdr( netadr_t a, netadr_t b )
{
if (chan->reliable_length)
return false; // waiting for ack
return true;
}
if( a.type != b.type )
return false;
if( a.type == NA_LOOPBACK )
return true;
bool Netchan_NeedReliable (netchan_t *chan)
{
bool send_reliable;
// if the remote side dropped the last reliable message, resend it
send_reliable = false;
if (chan->incoming_acknowledged > chan->last_reliable_sequence
&& chan->incoming_reliable_acknowledged != chan->reliable_sequence)
send_reliable = true;
// if the reliable transmit buffer is empty, copy the current message out
if (!chan->reliable_length && chan->message.cursize)
if( a.type == NA_IP )
{
send_reliable = true;
if(!memcmp(a.ip, b.ip, 4 ))
return true;
return false;
}
MsgDev( D_ERROR, "NET_CompareBaseAdr: bad address type\n" );
return false;
}
return send_reliable;
bool NET_CompareAdr( netadr_t a, netadr_t b )
{
if( a.type != b.type )
return false;
if( a.type == NA_LOOPBACK )
return true;
if( a.type == NA_IP )
{
if((memcmp(a.ip, b.ip, 4 ) == 0) && a.port == b.port)
return true;
return false;
}
MsgDev( D_ERROR, "NET_CompareAdr: bad address type\n" );
return false;
}
bool NET_IsLocalAddress( netadr_t adr )
{
return adr.type == NA_LOOPBACK;
}
/*
===============
Netchan_Transmit
=============================================================================
tries to send an unreliable message to a connection, and handles the
transmition / retransmition of the reliable messages.
LOOPBACK BUFFERS FOR LOCAL PLAYER
A 0 length will still generate a packet and deal with the reliable messages.
================
=============================================================================
*/
void Netchan_Transmit (netchan_t *chan, int length, byte *data)
bool NET_GetLoopPacket( netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message )
{
sizebuf_t send;
byte send_buf[MAX_MSGLEN];
bool send_reliable;
uint w1, w2;
int i;
loopback_t *loop;
// check for message overflow
if (chan->message.overflowed)
loop = &loopbacks[sock];
if( loop->send - loop->get > MAX_LOOPBACK )
loop->get = loop->send - MAX_LOOPBACK;
if( loop->get >= loop->send )
return false;
i = loop->get & (MAX_LOOPBACK-1);
loop->get++;
Mem_Copy( net_message->data, loop->msgs[i].data, loop->msgs[i].datalen );
net_message->cursize = loop->msgs[i].datalen;
memset( net_from, 0, sizeof(*net_from));
net_from->type = NA_LOOPBACK;
return true;
}
void NET_SendLoopPacket( netsrc_t sock, int length, const void *data, netadr_t to )
{
int i;
loopback_t *loop;
loop = &loopbacks[sock^1];
i = loop->send & (MAX_LOOPBACK-1);
loop->send++;
Mem_Copy( loop->msgs[i].data, data, length );
loop->msgs[i].datalen = length;
}
/*
=============================================================================
NETCHAN TRANSMIT UTILS
=============================================================================
*/
void NET_SendPacket( netsrc_t sock, int length, const void *data, netadr_t to )
{
// sequenced packets are shown in netchan, so just show oob
if( showpackets->integer && *(int *)data == -1 )
MsgDev( D_INFO, "send packet %4i\n", length);
if( to.type == NA_LOOPBACK )
{
chan->fatal_error = true;
Msg ("%s:Outgoing message overflow\n", NET_AdrToString (chan->remote_address));
NET_SendLoopPacket( sock, length, data, to );
return;
}
send_reliable = Netchan_NeedReliable (chan);
if (!chan->reliable_length && chan->message.cursize)
{
memcpy (chan->reliable_buf, chan->message_buf, chan->message.cursize);
chan->reliable_length = chan->message.cursize;
chan->message.cursize = 0;
chan->reliable_sequence ^= 1;
}
// write the packet header
SZ_Init (&send, send_buf, sizeof(send_buf));
w1 = ( chan->outgoing_sequence & ~(1<<31) ) | (send_reliable<<31);
w2 = ( chan->incoming_sequence & ~(1<<31) ) | (chan->incoming_reliable_sequence<<31);
chan->outgoing_sequence++;
chan->last_sent = Sys_Milliseconds();
MSG_WriteLong (&send, w1);
MSG_WriteLong (&send, w2);
// send the qport if we are a client
if (chan->sock == NS_CLIENT) MSG_WriteWord (&send, qport->value);
// copy the reliable message to the packet first
if (send_reliable)
{
SZ_Write (&send, chan->reliable_buf, chan->reliable_length);
chan->last_reliable_sequence = chan->outgoing_sequence;
}
// add the unreliable part if space is available
if (send.maxsize - send.cursize >= length)
SZ_Write (&send, data, length);
else MsgDev( D_WARN, "Netchan_Transmit: dumped unreliable\n");
// send the datagram
NET_SendPacket (chan->sock, send.cursize, send.data, chan->remote_address);
if (showpackets->value)
{
if (send_reliable)
Msg ("send %4i : s=%i reliable=%i ack=%i rack=%i\n"
, send.cursize
, chan->outgoing_sequence - 1
, chan->reliable_sequence
, chan->incoming_sequence
, chan->incoming_reliable_sequence);
else
Msg ("send %4i : s=%i ack=%i rack=%i\n"
, send.cursize
, chan->outgoing_sequence - 1
, chan->incoming_sequence
, chan->incoming_reliable_sequence);
}
if( to.type == NA_NONE ) return;
Sys_SendPacket( length, data, to );
}
/*
=================
Netchan_Process
=============
NET_StringToAdr
called when the current net_message is from remote_address
modifies net_message so that it points to the packet payload
=================
Traps "localhost" for loopback, passes everything else to system
=============
*/
bool Netchan_Process (netchan_t *chan, sizebuf_t *msg)
bool NET_StringToAdr( const char *s, netadr_t *a )
{
uint sequence, sequence_ack;
uint reliable_ack, reliable_message;
int qport;
bool r;
char *port, base[MAX_STRING_CHARS];
// get sequence numbers
MSG_BeginReading (msg);
sequence = MSG_ReadLong (msg);
sequence_ack = MSG_ReadLong (msg);
// read the qport if we are a server
if (chan->sock == NS_SERVER)
qport = MSG_ReadShort (msg);
reliable_message = sequence >> 31;
reliable_ack = sequence_ack >> 31;
sequence &= ~(1<<31);
sequence_ack &= ~(1<<31);
if (showpackets->value)
if(!com.strcmp( s, "localhost" ))
{
if (reliable_message)
Msg ("recv %4i : s=%i reliable=%i ack=%i rack=%i\n"
, msg->cursize
, sequence
, chan->incoming_reliable_sequence ^ 1
, sequence_ack
, reliable_ack);
else
Msg ("recv %4i : s=%i ack=%i rack=%i\n"
, msg->cursize
, sequence
, sequence_ack
, reliable_ack);
memset( a, 0, sizeof(*a));
a->type = NA_LOOPBACK;
return true;
}
// discard stale or duplicated packets
if (sequence <= chan->incoming_sequence)
// look for a port number
com.strncpy( base, s, sizeof( base ));
port = com.strstr( base, ":" );
if( port )
{
if (showdrop->value)
Msg ("%s:Out of order packet %i at %i\n"
, NET_AdrToString (chan->remote_address)
, sequence
, chan->incoming_sequence);
*port = 0;
port++;
}
r = Sys_StringToAdr( base, a );
if( !r )
{
a->type = NA_NONE;
return false;
}
// dropped packets don't keep the message from being used
chan->dropped = sequence - (chan->incoming_sequence+1);
if (chan->dropped > 0)
// inet_addr returns this if out of range
if( a->ip[0] == 255 && a->ip[1] == 255 && a->ip[2] == 255 && a->ip[3] == 255 )
{
if (showdrop->value)
Msg ("%s:Dropped %i packets at %i\n"
, NET_AdrToString (chan->remote_address)
, chan->dropped
, sequence);
a->type = NA_NONE;
return false;
}
//
// if the current outgoing reliable message has been acknowledged
// clear the buffer to make way for the next
//
if (reliable_ack == chan->reliable_sequence)
chan->reliable_length = 0; // it has been received
// if this message contains a reliable message, bump incoming_reliable_sequence
chan->incoming_sequence = sequence;
chan->incoming_acknowledged = sequence_ack;
chan->incoming_reliable_acknowledged = reliable_ack;
if (reliable_message)
{
chan->incoming_reliable_sequence ^= 1;
}
if( port ) a->port = BigShort((short)com.atoi( port ));
else a->port = BigShort( PORT_SERVER );
// the message can now be read from the current message pointer
chan->last_received = Sys_Milliseconds();
return true;
}
}

View File

@ -41,6 +41,16 @@ void _MSG_WriteByte (sizebuf_t *sb, int c, const char *filename, int fileline)
buf[0] = c;
}
void _MSG_WriteData( sizebuf_t *sb, const void *data, size_t length, const char *filename, int fileline )
{
int i;
for( i = 0; i < length; i++ )
{
_MSG_WriteByte( sb, ((byte *)data)[i], filename, fileline );
}
}
void _MSG_WriteShort (sizebuf_t *sb, int c, const char *filename, int fileline)
{
byte *buf;
@ -554,7 +564,7 @@ void MSG_ReadData (sizebuf_t *msg_read, void *data, int len)
=======================
*/
void SZ_Init (sizebuf_t *buf, byte *data, int length)
void SZ_Init( sizebuf_t *buf, byte *data, size_t length )
{
memset (buf, 0, sizeof(*buf));
buf->data = data;

View File

@ -5,6 +5,9 @@
#ifndef NET_MSG_H
#define NET_MSG_H
#define PACKET_BACKUP 32
#define PACKET_MASK ( PACKET_BACKUP - 1 )
// server to client
enum svc_ops_e
{
@ -29,6 +32,7 @@ enum svc_ops_e
svc_packetentities, // [...]
svc_deltapacketentities, // [...]
svc_frame, // server frame
svc_eof, // end of messages
};
// client to server
@ -38,7 +42,8 @@ enum clc_ops_e
clc_nop,
clc_move, // [[usercmd_t]
clc_userinfo, // [[userinfo string]
clc_stringcmd // [string] message
clc_stringcmd, // [string] message
clc_eof, // end of messages
};
typedef enum
@ -53,6 +58,13 @@ typedef enum
MSG_PVS_R,
} msgtype_t;
typedef struct
{
int cmdnumber; // cl.cmdnumber when packet was sent
int servertime; // usercmd->servertime when packet was sent
int realtime; // cls.realtime when packet was sent
} outpacket_t;
#define PS_M_TYPE (1<<0)
#define PS_M_ORIGIN (1<<1)
#define PS_M_VELOCITY (1<<2)
@ -229,8 +241,8 @@ typedef struct entity_state_s
*/
#define SZ_GetSpace(buf, len) _SZ_GetSpace(buf, len, __FILE__, __LINE__ )
#define SZ_Write(buf, data, len) _SZ_Write(buf, data, len, __FILE__, __LINE__ )
void SZ_Init (sizebuf_t *buf, byte *data, int length);
void SZ_Clear (sizebuf_t *buf);
void SZ_Init( sizebuf_t *buf, byte *data, size_t length );
void SZ_Clear( sizebuf_t *buf );
void *_SZ_GetSpace (sizebuf_t *buf, int length, const char *filename, int fileline);
void _SZ_Write (sizebuf_t *buf, const void *data, int length, const char *filename, int fileline);
void SZ_Print (sizebuf_t *buf, char *data); // strcats onto the sizebuf
@ -250,6 +262,7 @@ void _MSG_WriteAngle32(sizebuf_t *sb, float f, const char *filename, int filelin
void _MSG_WritePos16(sizebuf_t *sb, vec3_t pos, const char *filename, int fileline);
void _MSG_WritePos32(sizebuf_t *sb, vec3_t pos, const char *filename, int fileline);
void _MSG_WriteUnterminatedString (sizebuf_t *sb, const char *s, const char *filename, int fileline);
void _MSG_WriteData (sizebuf_t *sb, const void *data, size_t length, const char *filename, int fileline);
void _MSG_WriteDeltaUsercmd (sizebuf_t *sb, struct usercmd_s *from, struct usercmd_s *cmd, const char *filename, int fileline);
void _MSG_WriteDeltaEntity (struct entity_state_s *from, struct entity_state_s *to, sizebuf_t *msg, bool force, bool newentity, const char *filename, int fileline);
void _MSG_Send (msgtype_t to, vec3_t origin, edict_t *ent, const char *filename, int fileline);
@ -257,6 +270,7 @@ void _MSG_Send (msgtype_t to, vec3_t origin, edict_t *ent, const char *filename,
#define MSG_Begin( x ) _MSG_Begin( x, __FILE__, __LINE__);
#define MSG_WriteChar(x,y) _MSG_WriteChar (x, y, __FILE__, __LINE__);
#define MSG_WriteByte(x,y) _MSG_WriteByte (x, y, __FILE__, __LINE__);
#define MSG_WriteData(x,y,z) _MSG_WriteData (x, y, z,__FILE__, __LINE__);
#define MSG_WriteShort(x,y) _MSG_WriteShort (x, y, __FILE__, __LINE__);
#define MSG_WriteWord(x,y) _MSG_WriteWord (x, y, __FILE__, __LINE__);
#define MSG_WriteLong(x,y) _MSG_WriteLong (x, y, __FILE__, __LINE__);
@ -298,71 +312,45 @@ NET
==============================================================
*/
#define PORT_ANY -1
#define MAX_MSGLEN 1600 // max length of a message
#define PACKET_HEADER 10 // two ints and a short
typedef enum { NA_LOOPBACK, NA_BROADCAST, NA_IP, NA_IPX, NA_BROADCAST_IPX } netadrtype_t;
typedef enum { NS_CLIENT, NS_SERVER } netsrc_t;
typedef struct
{
netadrtype_t type;
byte ip[4];
byte ipx[10];
word port;
} netadr_t;
void NET_Init (void);
void NET_Shutdown (void);
void NET_Config (bool multiplayer);
bool NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message);
void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to);
bool NET_CompareAdr (netadr_t a, netadr_t b);
bool NET_CompareBaseAdr (netadr_t a, netadr_t b);
bool NET_IsLocalAddress (netadr_t adr);
char *NET_AdrToString (netadr_t a);
bool NET_StringToAdr (char *s, netadr_t *a);
void NET_Sleep(int msec);
void NET_SendPacket( netsrc_t sock, int length, const void *data, netadr_t to );
bool NET_GetLoopPacket( netsrc_t sock, netadr_t *net_from, sizebuf_t *message );
bool NET_StringToAdr( const char *s, netadr_t *a );
bool NET_CompareBaseAdr( netadr_t a, netadr_t b );
bool NET_CompareAdr( netadr_t a, netadr_t b );
bool NET_IsLocalAddress( netadr_t adr );
//============================================================================
#define OLD_AVG 0.99 // total = oldtotal*OLD_AVG + new*(1-OLD_AVG)
#define MAX_LATENT 32
typedef struct netchan_s
{
bool fatal_error;
netsrc_t sock;
netsrc_t sock;
int dropped; // between last packet and previous
int last_received; // for timeouts
int last_sent; // for retransmits
netadr_t remote_address;
int qport; // qport value to write when transmitting
netadr_t remote_address;
int qport; // qport value to write when transmitting
int dropped; // between last packet and previous
// sequencing variables
int incoming_sequence;
int incoming_acknowledged;
int incoming_reliable_acknowledged; // single bit
int incoming_sequence;
int outgoing_sequence;
int incoming_reliable_sequence; // single bit, maintained local
// incoming fragment assembly buffer
int fragment_sequence;
int fragment_length;
byte fragment_buffer[MAX_MSGLEN];
int outgoing_sequence;
int reliable_sequence; // single bit
int last_reliable_sequence; // sequence number of last send
// outgoing fragment buffer
// we need to space out the sending of large fragmented messages
bool unsent_fragments;
int unsent_fragment_start;
int unsent_length;
byte unsent_buffer[MAX_MSGLEN];
// legacy variables
// reliable staging and holding areas
sizebuf_t message; // writing buffer to send to server
byte message_buf[MAX_MSGLEN-16]; // leave space for header
// message is copied to this buffer when it is first transfered
int reliable_length;
byte reliable_buf[MAX_MSGLEN-16]; // unacked reliable message
sizebuf_t message; // writing buffer to send to server
byte message_buf[MAX_MSGLEN-16]; // leave space for header
int incoming_acknowledged;
int last_received; // for timeouts
int last_sent; // for retransmits
} netchan_t;
extern netadr_t net_from;
@ -376,13 +364,12 @@ extern byte net_message_buffer[MAX_MSGLEN];
#define UPDATE_BACKUP 64 // copies of entity_state_t to keep buffered, must be power of two
#define UPDATE_MASK (UPDATE_BACKUP - 1)
void Netchan_Init (void);
void Netchan_Setup (netsrc_t sock, netchan_t *chan, netadr_t adr, int qport);
bool Netchan_NeedReliable (netchan_t *chan);
void Netchan_Transmit (netchan_t *chan, int length, byte *data);
void Netchan_Init( void );
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport );
void Netchan_Transmit( netchan_t *chan, int length, const byte *data );
void Netchan_TransmitNextFragment( netchan_t *chan );
bool Netchan_Process( netchan_t *chan, sizebuf_t *msg );
void Netchan_OutOfBand (int net_socket, netadr_t adr, int length, byte *data);
void Netchan_OutOfBandPrint (int net_socket, netadr_t adr, char *format, ...);
bool Netchan_Process (netchan_t *chan, sizebuf_t *msg);
bool Netchan_CanReliable (netchan_t *chan);
void Netchan_OutOfBandPrint (int net_socket, netadr_t adr, const char *format, ...);
#endif//NET_MSG_H

View File

@ -1,891 +0,0 @@
/*
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.
*/
// net_wins.c
#include "winsock.h"
#include "wsipx.h"
#include "common.h"
#define MAX_LOOPBACK 4
typedef struct
{
byte data[MAX_MSGLEN];
int datalen;
} loopmsg_t;
typedef struct
{
loopmsg_t msgs[MAX_LOOPBACK];
int get, send;
} loopback_t;
cvar_t *net_shownet;
static cvar_t *noudp;
static cvar_t *noipx;
loopback_t loopbacks[2];
int ip_sockets[2];
int ipx_sockets[2];
// wsock32.dll exports
static int (_stdcall *pWSACleanup)( void );
static word (_stdcall *pNtohs)( word netshort );
static int (_stdcall *pWSAGetLastError)( void );
static int (_stdcall *pCloseSocket)( SOCKET s );
static word (_stdcall *pHtons)( word hostshort );
static dword (_stdcall *pInet_Addr)( const char* cp );
static SOCKET (_stdcall *pSocket)( int af, int type, int protocol );
static struct hostent *(_stdcall *pGetHostByName)( const char* name );
static int (_stdcall *pIoctlSocket)( SOCKET s, long cmd, dword* argp );
static int (_stdcall *pWSAStartup)( word wVersionRequired, LPWSADATA lpWSAData );
static int (_stdcall *pBind)( SOCKET s, const struct sockaddr* addr, int namelen );
static int (_stdcall *pSetSockopt)( SOCKET s, int level, int optname, const char* optval, int optlen );
static int (_stdcall *pRecvFrom)( SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen );
static int (_stdcall *pSendTo)( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen );
static int (_stdcall *pSelect)( int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval* timeout );
static dllfunc_t winsock_funcs[] =
{
{"bind", (void **) &pBind },
{"ntohs", (void **) &pNtohs },
{"htons", (void **) &pHtons },
{"socket", (void **) &pSocket },
{"select", (void **) &pSelect },
{"sendto", (void **) &pSendTo },
{"recvfrom", (void **) &pRecvFrom },
{"inet_addr", (void **) &pInet_Addr },
{"WSAStartup", (void **) &pWSAStartup },
{"WSACleanup", (void **) &pWSACleanup },
{"setsockopt", (void **) &pSetSockopt },
{"ioctlsocket", (void **) &pIoctlSocket },
{"closesocket", (void **) &pCloseSocket },
{"gethostbyname", (void **) &pGetHostByName },
{"WSAGetLastError", (void **) &pWSAGetLastError },
{ NULL, NULL }
};
dll_info_t winsock_dll = { "wsock32.dll", winsock_funcs, NULL, NULL, NULL, true, 0 };
char *NET_ErrorString (void);
//=============================================================================
void NET_OpenWinSock( void )
{
Sys_LoadLibrary( &winsock_dll );
}
void NET_FreeWinSock( void )
{
Sys_FreeLibrary( &winsock_dll );
}
void NetadrToSockadr (netadr_t *a, struct sockaddr *s)
{
memset (s, 0, sizeof(*s));
if (a->type == NA_BROADCAST)
{
((struct sockaddr_in *)s)->sin_family = AF_INET;
((struct sockaddr_in *)s)->sin_port = a->port;
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
}
else if (a->type == NA_IP)
{
((struct sockaddr_in *)s)->sin_family = AF_INET;
((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
((struct sockaddr_in *)s)->sin_port = a->port;
}
else if (a->type == NA_IPX)
{
((struct sockaddr_ipx *)s)->sa_family = AF_IPX;
memcpy(((struct sockaddr_ipx *)s)->sa_netnum, &a->ipx[0], 4);
memcpy(((struct sockaddr_ipx *)s)->sa_nodenum, &a->ipx[4], 6);
((struct sockaddr_ipx *)s)->sa_socket = a->port;
}
else if (a->type == NA_BROADCAST_IPX)
{
((struct sockaddr_ipx *)s)->sa_family = AF_IPX;
memset(((struct sockaddr_ipx *)s)->sa_netnum, 0, 4);
memset(((struct sockaddr_ipx *)s)->sa_nodenum, 0xff, 6);
((struct sockaddr_ipx *)s)->sa_socket = a->port;
}
}
void SockadrToNetadr (struct sockaddr *s, netadr_t *a)
{
if (s->sa_family == AF_INET)
{
a->type = NA_IP;
*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
a->port = ((struct sockaddr_in *)s)->sin_port;
}
else if (s->sa_family == AF_IPX)
{
a->type = NA_IPX;
memcpy(&a->ipx[0], ((struct sockaddr_ipx *)s)->sa_netnum, 4);
memcpy(&a->ipx[4], ((struct sockaddr_ipx *)s)->sa_nodenum, 6);
a->port = ((struct sockaddr_ipx *)s)->sa_socket;
}
}
bool NET_CompareAdr (netadr_t a, netadr_t b)
{
if (a.type != b.type)
return false;
if (a.type == NA_LOOPBACK)
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] && a.port == b.port)
return true;
return false;
}
if (a.type == NA_IPX)
{
if ((memcmp(a.ipx, b.ipx, 10) == 0) && a.port == b.port)
return true;
return false;
}
return false;
}
/*
===================
NET_CompareBaseAdr
Compares without the port
===================
*/
bool NET_CompareBaseAdr (netadr_t a, netadr_t b)
{
if (a.type != b.type)
return false;
if (a.type == NA_LOOPBACK)
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.type == NA_IPX)
{
if ((memcmp(a.ipx, b.ipx, 10) == 0))
return true;
return false;
}
return false;
}
char *NET_AdrToString (netadr_t a)
{
static char s[64];
if (a.type == NA_LOOPBACK) com.sprintf (s, "loopback");
else if (a.type == NA_IP) com.sprintf (s, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], pNtohs(a.port));
else com.sprintf (s, "%02x%02x%02x%02x:%02x%02x%02x%02x%02x%02x:%i", a.ipx[0], a.ipx[1], a.ipx[2], a.ipx[3], a.ipx[4], a.ipx[5], a.ipx[6], a.ipx[7], a.ipx[8], a.ipx[9], pNtohs(a.port));
return s;
}
/*
=============
NET_StringToAdr
localhost
idnewt
idnewt:28000
192.246.40.70
192.246.40.70:28000
=============
*/
#define DO(src,dest) \
copy[0] = s[src]; \
copy[1] = s[src + 1]; \
sscanf (copy, "%x", &val); \
((struct sockaddr_ipx *)sadr)->dest = val
bool NET_StringToSockaddr (char *s, struct sockaddr *sadr)
{
struct hostent *h;
char *colon;
int val;
char copy[128];
memset (sadr, 0, sizeof(*sadr));
if ((strlen(s) >= 23) && (s[8] == ':') && (s[21] == ':')) // check for an IPX address
{
((struct sockaddr_ipx *)sadr)->sa_family = AF_IPX;
copy[2] = 0;
DO(0, sa_netnum[0]);
DO(2, sa_netnum[1]);
DO(4, sa_netnum[2]);
DO(6, sa_netnum[3]);
DO(9, sa_nodenum[0]);
DO(11, sa_nodenum[1]);
DO(13, sa_nodenum[2]);
DO(15, sa_nodenum[3]);
DO(17, sa_nodenum[4]);
DO(19, sa_nodenum[5]);
sscanf (&s[22], "%u", &val);
((struct sockaddr_ipx *)sadr)->sa_socket = pHtons((unsigned short)val);
}
else
{
((struct sockaddr_in *)sadr)->sin_family = AF_INET;
((struct sockaddr_in *)sadr)->sin_port = 0;
strcpy (copy, s);
// strip off a trailing :port if present
for (colon = copy ; *colon ; colon++)
if (*colon == ':')
{
*colon = 0;
((struct sockaddr_in *)sadr)->sin_port = pHtons((short)atoi(colon+1));
}
if (copy[0] >= '0' && copy[0] <= '9')
{
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = pInet_Addr(copy);
}
else
{
if (! (h = pGetHostByName(copy)) )
return 0;
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
}
}
return true;
}
#undef DO
/*
=============
NET_StringToAdr
localhost
idnewt
idnewt:28000
192.246.40.70
192.246.40.70:28000
=============
*/
bool NET_StringToAdr (char *s, netadr_t *a)
{
struct sockaddr sadr;
if (!strcmp (s, "localhost"))
{
memset (a, 0, sizeof(*a));
a->type = NA_LOOPBACK;
return true;
}
if (!NET_StringToSockaddr (s, &sadr))
return false;
SockadrToNetadr (&sadr, a);
return true;
}
bool NET_IsLocalAddress (netadr_t adr)
{
return adr.type == NA_LOOPBACK;
}
/*
=============================================================================
LOOPBACK BUFFERS FOR LOCAL PLAYER
=============================================================================
*/
bool NET_GetLoopPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
{
int i;
loopback_t *loop;
loop = &loopbacks[sock];
if (loop->send - loop->get > MAX_LOOPBACK)
loop->get = loop->send - MAX_LOOPBACK;
if (loop->get >= loop->send)
return false;
i = loop->get & (MAX_LOOPBACK-1);
loop->get++;
memcpy (net_message->data, loop->msgs[i].data, loop->msgs[i].datalen);
net_message->cursize = loop->msgs[i].datalen;
memset (net_from, 0, sizeof(*net_from));
net_from->type = NA_LOOPBACK;
return true;
}
void NET_SendLoopPacket (netsrc_t sock, int length, void *data, netadr_t to)
{
int i;
loopback_t *loop;
loop = &loopbacks[sock^1];
i = loop->send & (MAX_LOOPBACK-1);
loop->send++;
Mem_Copy(loop->msgs[i].data, data, length);
loop->msgs[i].datalen = length;
}
//=============================================================================
bool NET_GetPacket (netsrc_t sock, netadr_t *net_from, sizebuf_t *net_message)
{
int ret;
struct sockaddr from;
int fromlen;
int net_socket;
int protocol;
int err;
if (NET_GetLoopPacket (sock, net_from, net_message))
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 = pRecvFrom (net_socket, net_message->data, net_message->maxsize
, 0, (struct sockaddr *)&from, &fromlen);
SockadrToNetadr (&from, net_from);
if (ret == -1)
{
err = pWSAGetLastError();
if (err == WSAEWOULDBLOCK)
continue;
if (err == WSAEMSGSIZE)
{
MsgDev( D_ERROR, "NET_GetPacket: Oversize packet from %s\n", NET_AdrToString(*net_from));
continue;
}
if (dedicated->value) // let dedicated servers continue after errors
Msg ("NET_GetPacket: %s from %s\n", NET_ErrorString(), NET_AdrToString(*net_from));
else Host_Error("NET_GetPacket: %s from %s\n", NET_ErrorString(), NET_AdrToString(*net_from));
continue;
}
if (ret == net_message->maxsize)
{
Msg ("Oversize packet from %s\n", NET_AdrToString (*net_from));
continue;
}
net_message->cursize = ret;
return true;
}
return false;
}
//=============================================================================
void NET_SendPacket (netsrc_t sock, int length, void *data, netadr_t to)
{
int ret;
struct sockaddr addr;
int net_socket;
if ( to.type == NA_LOOPBACK )
{
NET_SendLoopPacket (sock, length, data, to);
return;
}
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
{
MsgDev( D_ERROR, "NET_SendPacket: bad address type\n");
return;
}
NetadrToSockadr (&to, &addr);
ret = pSendTo (net_socket, data, length, 0, &addr, sizeof(addr) );
if (ret == -1)
{
int err = pWSAGetLastError();
// wouldblock is silent
if (err == WSAEWOULDBLOCK)
return;
// some PPP links dont allow broadcasts
if ((err == WSAEADDRNOTAVAIL) && ((to.type == NA_BROADCAST) || (to.type == NA_BROADCAST_IPX)))
return;
if (dedicated->value) // let dedicated servers continue after errors
{
Msg ("NET_SendPacket ERROR: %s to %s\n", NET_ErrorString(), NET_AdrToString (to));
}
else
{
if (err == WSAEADDRNOTAVAIL)
{
MsgDev( D_ERROR, "NET_SendPacket: %s : %s\n", NET_ErrorString(), NET_AdrToString (to));
}
else
{
Host_Error("NET_SendPacket: %s to %s\n", NET_ErrorString(), NET_AdrToString(to));
}
}
}
}
//=============================================================================
/*
====================
NET_Socket
====================
*/
int NET_IPSocket (char *net_interface, int port)
{
int newsocket;
struct sockaddr_in address;
bool _true = true;
int i = 1;
int err;
if ((newsocket = pSocket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
err = pWSAGetLastError();
if (err != WSAEAFNOSUPPORT)
Msg ("WARNING: UDP_OpenSocket: socket: %s", NET_ErrorString());
return 0;
}
// make it non-blocking
if (pIoctlSocket (newsocket, FIONBIO, &_true) == -1)
{
Msg ("WARNING: UDP_OpenSocket: ioctl FIONBIO: %s\n", NET_ErrorString());
return 0;
}
// make it broadcast capable
if (pSetSockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) == -1)
{
Msg ("WARNING: UDP_OpenSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString());
return 0;
}
if (!net_interface || !net_interface[0] || !stricmp(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 = pHtons((short)port);
address.sin_family = AF_INET;
if( pBind (newsocket, (void *)&address, sizeof(address)) == -1)
{
Msg ("WARNING: UDP_OpenSocket: bind: %s\n", NET_ErrorString());
pCloseSocket (newsocket);
return 0;
}
return newsocket;
}
/*
====================
NET_OpenIP
====================
*/
void NET_OpenIP (void)
{
cvar_t *ip;
int port;
int dedicated;
ip = Cvar_Get ("ip", "localhost", CVAR_INIT, "network ip address" );
dedicated = Cvar_VariableValue ("dedicated");
if (!ip_sockets[NS_SERVER])
{
port = Cvar_Get("ip_hostport", "0", CVAR_INIT, "no description" )->value;
if (!port)
{
port = Cvar_Get("hostport", "0", CVAR_INIT, "no description" )->value;
if (!port)
{
port = Cvar_Get("port", va("%i", PORT_SERVER), CVAR_INIT, "no description" )->value;
}
}
ip_sockets[NS_SERVER] = NET_IPSocket (ip->string, port);
if (!ip_sockets[NS_SERVER] && dedicated) Sys_Error("Couldn't allocate dedicated server IP port");
}
// dedicated servers don't need client ports
if (dedicated) return;
if (!ip_sockets[NS_CLIENT])
{
port = Cvar_Get("ip_clientport", "0", CVAR_INIT, "no description" )->value;
if (!port)
{
port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_INIT, "no description" )->value;
if (!port)
port = PORT_ANY;
}
ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, port);
if (!ip_sockets[NS_CLIENT])
ip_sockets[NS_CLIENT] = NET_IPSocket (ip->string, PORT_ANY);
}
}
/*
====================
IPX_Socket
====================
*/
int NET_IPXSocket (int port)
{
int newsocket;
struct sockaddr_ipx address;
int _true = 1;
int err;
if ((newsocket = pSocket (PF_IPX, SOCK_DGRAM, NSPROTO_IPX)) == -1)
{
err = pWSAGetLastError();
if (err != WSAEAFNOSUPPORT)
Msg ("WARNING: IPX_Socket: socket: %s\n", NET_ErrorString());
return 0;
}
// make it non-blocking
if (pIoctlSocket (newsocket, FIONBIO, &_true) == -1)
{
Msg ("WARNING: IPX_Socket: ioctl FIONBIO: %s\n", NET_ErrorString());
return 0;
}
// make it broadcast capable
if (pSetSockopt(newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&_true, sizeof(_true)) == -1)
{
Msg ("WARNING: IPX_Socket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString());
return 0;
}
address.sa_family = AF_IPX;
memset (address.sa_netnum, 0, 4);
memset (address.sa_nodenum, 0, 6);
if (port == PORT_ANY)
address.sa_socket = 0;
else
address.sa_socket = pHtons((short)port);
if( pBind (newsocket, (void *)&address, sizeof(address)) == -1)
{
Msg ("WARNING: IPX_Socket: bind: %s\n", NET_ErrorString());
pCloseSocket (newsocket);
return 0;
}
return newsocket;
}
/*
====================
NET_OpenIPX
====================
*/
void NET_OpenIPX (void)
{
int port;
int dedicated;
dedicated = Cvar_VariableValue ("dedicated");
if (!ipx_sockets[NS_SERVER])
{
port = Cvar_Get("ipx_hostport", "0", CVAR_INIT, "no description" )->value;
if (!port)
{
port = Cvar_Get("hostport", "0", CVAR_INIT, "no description" )->value;
if (!port)
{
port = Cvar_Get("port", va("%i", PORT_SERVER ), CVAR_INIT, "no description" )->value;
}
}
ipx_sockets[NS_SERVER] = NET_IPXSocket (port);
}
// dedicated servers don't need client ports
if (dedicated)
return;
if (!ipx_sockets[NS_CLIENT])
{
port = Cvar_Get("ipx_clientport", "0", CVAR_INIT, "no description" )->value;
if (!port)
{
port = Cvar_Get("clientport", va("%i", PORT_CLIENT), CVAR_INIT, "no description" )->value;
if (!port)
port = PORT_ANY;
}
ipx_sockets[NS_CLIENT] = NET_IPXSocket (port);
if (!ipx_sockets[NS_CLIENT]) ipx_sockets[NS_CLIENT] = NET_IPXSocket (PORT_ANY);
}
}
/*
====================
NET_Config
A single player game will only use the loopback code
====================
*/
void NET_Config (bool multiplayer)
{
int i;
static bool old_config;
if (old_config == multiplayer)
return;
old_config = multiplayer;
if (!multiplayer)
{ // shut down any existing sockets
for (i=0 ; i<2 ; i++)
{
if (ip_sockets[i])
{
pCloseSocket (ip_sockets[i]);
ip_sockets[i] = 0;
}
if (ipx_sockets[i])
{
pCloseSocket (ipx_sockets[i]);
ipx_sockets[i] = 0;
}
}
}
else
{ // open sockets
if (! noudp->value)
NET_OpenIP ();
if (! noipx->value)
NET_OpenIPX ();
}
}
// sleeps msec or until net socket is ready
void NET_Sleep(int msec)
{
struct timeval timeout;
fd_set fdset;
extern cvar_t *dedicated;
int i;
if (!dedicated || !dedicated->value)
return; // we're not a server, just run full speed
FD_ZERO(&fdset);
i = 0;
if (ip_sockets[NS_SERVER]) {
FD_SET(ip_sockets[NS_SERVER], &fdset); // network socket
i = ip_sockets[NS_SERVER];
}
if (ipx_sockets[NS_SERVER]) {
FD_SET(ipx_sockets[NS_SERVER], &fdset); // network socket
if (ipx_sockets[NS_SERVER] > i)
i = ipx_sockets[NS_SERVER];
}
timeout.tv_sec = msec/1000;
timeout.tv_usec = (msec%1000)*1000;
pSelect(i+1, &fdset, NULL, NULL, &timeout);
}
//===================================================================
static WSADATA winsockdata;
/*
====================
NET_Init
====================
*/
void NET_Init (void)
{
WORD wVersionRequested;
int r;
wVersionRequested = MAKEWORD(1, 1);
NET_OpenWinSock(); // loading wsock32.dll
r = pWSAStartup (MAKEWORD(1, 1), &winsockdata);
if(r) Sys_Error("Winsock initialization failed.");
MsgDev(D_NOTE, "NET_Init()\n");
noudp = Cvar_Get ("noudp", "0", CVAR_INIT, "no description" );
noipx = Cvar_Get ("noipx", "0", CVAR_INIT, "no description" );
net_shownet = Cvar_Get ("net_shownet", "0", 0, "show network status" );
}
/*
====================
NET_Shutdown
====================
*/
void NET_Shutdown (void)
{
NET_Config (false); // close sockets
pWSACleanup ();
NET_FreeWinSock();
}
/*
====================
NET_ErrorString
====================
*/
char *NET_ErrorString (void)
{
int code;
code = pWSAGetLastError ();
switch (code)
{
case WSAEINTR: return "WSAEINTR";
case WSAEBADF: return "WSAEBADF";
case WSAEACCES: return "WSAEACCES";
case WSAEDISCON: return "WSAEDISCON";
case WSAEFAULT: return "WSAEFAULT";
case WSAEINVAL: return "WSAEINVAL";
case WSAEMFILE: return "WSAEMFILE";
case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
case WSAEINPROGRESS: return "WSAEINPROGRESS";
case WSAEALREADY: return "WSAEALREADY";
case WSAENOTSOCK: return "WSAENOTSOCK";
case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
case WSAEMSGSIZE: return "WSAEMSGSIZE";
case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
case WSAEADDRINUSE: return "WSAEADDRINUSE";
case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
case WSAENETDOWN: return "WSAENETDOWN";
case WSAENETUNREACH: return "WSAENETUNREACH";
case WSAENETRESET: return "WSAENETRESET";
case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
case WSAECONNRESET: return "WSAECONNRESET";
case WSAENOBUFS: return "WSAENOBUFS";
case WSAEISCONN: return "WSAEISCONN";
case WSAENOTCONN: return "WSAENOTCONN";
case WSAESHUTDOWN: return "WSAESHUTDOWN";
case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
case WSAETIMEDOUT: return "WSAETIMEDOUT";
case WSAECONNREFUSED: return "WSAECONNREFUSED";
case WSAELOOP: return "WSAELOOP";
case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
case WSASYSNOTREADY: return "WSASYSNOTREADY";
case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
case WSANOTINITIALISED: return "WSANOTINITIALISED";
case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
case WSATRY_AGAIN: return "WSATRY_AGAIN";
case WSANO_RECOVERY: return "WSANO_RECOVERY";
case WSANO_DATA: return "WSANO_DATA";
default: return "NO ERROR";
}
}

View File

@ -69,6 +69,7 @@ typedef struct server_s
sv_state_t state; // precache commands are only valid during load
bool loadgame; // client begins should reuse existing entity
bool autosaved;
float time; // always sv.framenum * 50 msec
float frametime;
@ -77,7 +78,7 @@ typedef struct server_s
char name[MAX_QPATH]; // map name, or cinematic name
cmodel_t *models[MAX_MODELS];
char configstrings[MAX_CONFIGSTRINGS][MAX_QPATH];
string configstrings[MAX_CONFIGSTRINGS];
entity_state_t baselines[MAX_EDICTS];
// the multicast buffer is used to send a message to a set of clients
@ -87,8 +88,6 @@ typedef struct server_s
int lastchecktime;
int lastcheck;
bool autosaved;
} server_t;
typedef struct

View File

@ -18,7 +18,7 @@ void SV_SetMaster_f( void )
int i, slot;
// only dedicated servers send heartbeats
if(!dedicated->value)
if( host.type == HOST_DEDICATED )
{
Msg("Only dedicated servers use masters.\n");
return;
@ -492,7 +492,7 @@ void SV_InitOperatorCommands( void )
Cmd_AddCommand("restart", SV_Restart_f, "restarting current level" );
Cmd_AddCommand("sectorlist", SV_SectorList_f, "display pvs sectors" );
if( dedicated->value )
if( host.type == HOST_DEDICATED )
{
Cmd_AddCommand ("say", SV_ConSay_f, "send a chat message to everyone on the server" );
Cmd_AddCommand("setmaster", SV_SetMaster_f, "set ip address for dedicated server" );
@ -518,7 +518,7 @@ void SV_KillOperatorCommands( void )
Cmd_RemoveCommand("restart");
Cmd_RemoveCommand("sectorlist");
if( dedicated->integer )
if( host.type == HOST_DEDICATED )
{
Cmd_RemoveCommand("say");
Cmd_RemoveCommand("setmaster");

View File

@ -21,6 +21,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "common.h"
#include "server.h"
void SV_PacketEvent( netadr_t from, sizebuf_t *msg )
{
}
/*
=============================================================================

View File

@ -273,7 +273,7 @@ void SV_InitGame (void)
// dedicated servers are can't be single player and are usually DM
// so unless they explicity set coop, force it to deathmatch
if (dedicated->value)
if( host.type == HOST_DEDICATED )
{
if (!Cvar_VariableValue ("coop"))
Cvar_FullSet ("deathmatch", "1", CVAR_SERVERINFO | CVAR_LATCH);

View File

@ -576,7 +576,7 @@ void SV_ReadPackets (void)
client_state_t *cl;
int qport;
while (NET_GetPacket (NS_SERVER, &net_from, &net_message))
while (Sys_RecvPacket(&net_from, &net_message))
{
// check for connectionless packet (0xffffffff) first
if (*(int *)net_message.data == -1)
@ -730,7 +730,7 @@ void SV_Frame( dword time )
svs.realtime = (sv.time * 1000 ) - HOST_FRAMETIME;
}
NET_Sleep((sv.time*1000) - svs.realtime);
//NET_Sleep((sv.time*1000) - svs.realtime);
SV_VM_End(); //end frame
return;
}
@ -770,9 +770,8 @@ void Master_Heartbeat (void)
char *string;
int i;
// pgm post3.19 change, cvar pointer not validated before dereferencing
if (!dedicated || !dedicated->value)
return; // only dedicated servers send heartbeats
if( host.type == HOST_DEDICATED )
return; // only dedicated servers send heartbeats
// pgm post3.19 change, cvar pointer not validated before dereferencing
if (!public_server || !public_server->value)
@ -811,9 +810,8 @@ void Master_Shutdown (void)
{
int i;
// pgm post3.19 change, cvar pointer not validated before dereferencing
if (!dedicated || !dedicated->value)
return; // only dedicated servers send heartbeats
if( host.type == HOST_DEDICATED )
return; // only dedicated servers send heartbeats
// pgm post3.19 change, cvar pointer not validated before dereferencing
if (!public_server || !public_server->value)
@ -929,6 +927,8 @@ void SV_Init (void)
sv_reconnect_limit = Cvar_Get ("sv_reconnect_limit", "3", CVAR_ARCHIVE, "max reconnect attempts" );
SZ_Init (&net_message, net_message_buffer, sizeof(net_message_buffer));
host.sv_running = true;
}
/*
@ -1000,5 +1000,6 @@ void SV_Shutdown( bool reconnect )
if (svs.clients) Mem_Free (svs.clients);
if (svs.client_entities) Mem_Free (svs.client_entities);
memset (&svs, 0, sizeof(svs));
host.sv_running = false;
}

View File

@ -99,7 +99,7 @@ void SV_BroadcastPrintf (int level, char *fmt, ...)
va_end (argptr);
// echo to console
if (dedicated->value)
if( host.type == HOST_DEDICATED )
{
char echo[1024];
int i;
@ -530,5 +530,4 @@ void SV_SendClientMessages (void)
Netchan_Transmit( &c->netchan, 0, NULL );
}
}
}
}

View File

@ -678,7 +678,7 @@ void Cmd_Say_f (edict_t *ent, bool team, bool arg0)
com.strcat(text, "\n");
if (dedicated->value)
if( host.type == HOST_DEDICATED )
PF_cprintf(NULL, PRINT_CHAT, "%s", text);
for (j = 1; j <= maxclients->value; j++)

View File

@ -1,30 +0,0 @@
//========= Copyright © 1996-2001, Valve LLC, All rights reserved. ============
//
// Purpose: Generalized 32-bit random number generator
// Range is 0x00000000 - 0x7FFFFFFF
//
// $NoKeywords: $
//=============================================================================
#ifndef RANDOM_H
#define RANDOM_H
#ifdef _WIN32
#pragma once
#endif
// the random number seeding is automatic
#define MAX_RANDOM_RANGE 0x7FFFFFFFUL
// restarts random generator
// setting lSeed to 0 causes the current time to be used as the seed
// random number generator will automatically seed itself on first use with current time if this is not called
extern void SeedRandomNumberGenerator(long lSeed = 0);
// returns a random integer of range [low, high]
extern long RandomLong( long lLow, long lHigh );
// returns a random float of range [low, high)
extern float RandomFloat( float flLow, float flHigh );
#endif // RANDOM_H

View File

@ -8,21 +8,21 @@
// Processor Information:
typedef struct cpuinfo_s
{
bool m_bRDTSC : 1; // Is RDTSC supported?
bool m_bCMOV : 1; // Is CMOV supported?
bool m_bFCMOV : 1; // Is FCMOV supported?
bool m_bSSE : 1; // Is SSE supported?
bool m_bSSE2 : 1; // Is SSE2 Supported?
bool m_b3DNow : 1; // Is 3DNow! Supported?
bool m_bMMX : 1; // Is MMX supported?
bool m_bHT : 1; // Is HyperThreading supported?
bool m_bRDTSC : 1; // Is RDTSC supported?
bool m_bCMOV : 1; // Is CMOV supported?
bool m_bFCMOV : 1; // Is FCMOV supported?
bool m_bSSE : 1; // Is SSE supported?
bool m_bSSE2 : 1; // Is SSE2 Supported?
bool m_b3DNow : 1; // Is 3DNow! Supported?
bool m_bMMX : 1; // Is MMX supported?
bool m_bHT : 1; // Is HyperThreading supported?
byte m_usNumLogicCore; // Number op logical processors.
byte m_usNumPhysCore; // Number of physical processors
byte m_usNumLogicCore; // Number op logical processors.
byte m_usNumPhysCore; // Number of physical processors
int64 m_speed; // In cycles per second.
int m_size; // structure size
char* m_szCPUID; // Processor vendor Identification.
int64 m_speed; // In cycles per second.
int m_size; // structure size
char* m_szCPUID; // Processor vendor Identification.
} cpuinfo_t;
typedef struct register_s
@ -34,7 +34,7 @@ typedef struct register_s
bool retval;
} register_t;
static register_t cpuid(uint function )
static register_t cpuid( uint function )
{
register_t local;
@ -65,7 +65,7 @@ static register_t cpuid(uint function )
return local;
}
bool CheckMMXTechnology(void)
bool CheckMMXTechnology( void )
{
register_t mmx = cpuid(1);
@ -73,7 +73,7 @@ bool CheckMMXTechnology(void)
return ( mmx.edx & 0x800000 ) != 0;
}
bool CheckSSETechnology(void)
bool CheckSSETechnology( void )
{
register_t sse = cpuid(1);
@ -81,7 +81,7 @@ bool CheckSSETechnology(void)
return ( sse.edx & 0x2000000L ) != 0;
}
bool CheckSSE2Technology(void)
bool CheckSSE2Technology( void )
{
register_t sse2 = cpuid(1);
@ -89,7 +89,7 @@ bool CheckSSE2Technology(void)
return ( sse2.edx & 0x04000000 ) != 0;
}
bool Check3DNowTechnology(void)
bool Check3DNowTechnology( void )
{
register_t amd = cpuid( 0x80000000 );
@ -103,7 +103,7 @@ bool Check3DNowTechnology(void)
return false;
}
bool CheckCMOVTechnology()
bool CheckCMOVTechnology( void )
{
register_t cmov = cpuid(1);
@ -111,7 +111,7 @@ bool CheckCMOVTechnology()
return ( cmov.edx & (1<<15) ) != 0;
}
bool CheckFCMOVTechnology(void)
bool CheckFCMOVTechnology( void )
{
register_t fcmov = cpuid(1);
@ -119,7 +119,7 @@ bool CheckFCMOVTechnology(void)
return ( fcmov.edx & (1<<16) ) != 0;
}
bool CheckRDTSCTechnology(void)
bool CheckRDTSCTechnology( void )
{
register_t rdtsc = cpuid(1);
@ -132,7 +132,7 @@ bool CheckRDTSCTechnology(void)
Return the Processor's vendor identification string, or "Generic_x86" if it doesn't exist on this CPU
================
*/
const char* GetProcessorVendorId()
const char* GetProcessorVendorId( void )
{
static char VendorID[13];
register_t vendor = cpuid(0);
@ -157,7 +157,7 @@ Returns non-zero if Hyper-Threading Technology is supported on the processors an
This does not mean that Hyper-Threading Technology is necessarily enabled.
================
*/
static bool HTSupported(void)
static bool HTSupported( void )
{
const uint HT_BIT = 0x10000000; // EDX[28] - Bit 28 set indicates Hyper-Threading Technology is supported in hardware.
const uint FAMILY_ID = 0x0f00; // EAX[11:8] - Bit 11 thru 8 contains family processor id
@ -182,7 +182,7 @@ static bool HTSupported(void)
Returns the number of logical processors per physical processors.
================
*/
static byte LogicalProcessorsPerPackage(void)
static byte LogicalProcessorsPerPackage( void )
{
const unsigned NUM_LOGICAL_BITS = 0x00FF0000; // EBX[23:16] indicate number of logical processors per package
register_t core = cpuid(1);
@ -213,7 +213,7 @@ Measure the processor clock speed by sampling the cycle count, waiting
for some fraction of a second, then measuring the elapsed number of cycles.
================
*/
static int64 CalculateClockSpeed()
static int64 CalculateClockSpeed( void )
{
LARGE_INTEGER waitTime, startCount, curCount;
int scale = 5; // Take 1/32 of a second for the measurement.
@ -309,10 +309,10 @@ void Sys_InitCPU( void )
if( cpu.m_bCMOV ) com_strcat(szFeatureString, "CMOV " );
if( cpu.m_bFCMOV ) com_strcat(szFeatureString, "FCMOV " );
// Remove the trailing space. There will always be one.
// remove the trailing space. There will always be one.
szFeatureString[com_strlen(szFeatureString)-1] = '\0';
// Dump CPU information:
// dump CPU information:
if( cpu.m_usNumLogicCore == 1 ) MsgDev( D_INFO, "CPU: %s [1 core]. Frequency: %.01f %s\n", cpu.m_szCPUID, fFrequency, szFrequencyDenomination );
else
{

870
launch/common/network.c Normal file
View File

@ -0,0 +1,870 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// network.c - network interface
//=======================================================================
#include <winsock.h>
#include "launch.h"
#define MAX_IPS 16
#define PORT_ANY -1
#define PORT_SERVER 27960
// wsock32.dll exports
static int (_stdcall *pWSACleanup)( void );
static word (_stdcall *pNtohs)( word netshort );
static int (_stdcall *pWSAGetLastError)( void );
static int (_stdcall *pCloseSocket)( SOCKET s );
static word (_stdcall *pHtons)( word hostshort );
static dword (_stdcall *pInet_Addr)( const char* cp );
static SOCKET (_stdcall *pSocket)( int af, int type, int protocol );
static struct hostent *(_stdcall *pGetHostByName)( const char* name );
static int (_stdcall *pIoctlSocket)( SOCKET s, long cmd, dword* argp );
static int (_stdcall *pWSAStartup)( word wVersionRequired, LPWSADATA lpWSAData );
static int (_stdcall *pBind)( SOCKET s, const struct sockaddr* addr, int namelen );
static int (_stdcall *pSetSockopt)( SOCKET s, int level, int optname, const char* optval, int optlen );
static int (_stdcall *pRecvFrom)( SOCKET s, char* buf, int len, int flags, struct sockaddr* from, int* fromlen );
static int (_stdcall *pSendTo)( SOCKET s, const char* buf, int len, int flags, const struct sockaddr* to, int tolen );
static int (_stdcall *pSelect)( int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval* timeout );
static int (_stdcall *pConnect)( SOCKET s, const struct sockaddr *name, int namelen );
static int (_stdcall *pSend)( SOCKET s, const char *buf, int len, int flags );
static int (_stdcall *pRecv)( SOCKET s, char *buf, int len, int flags );
static int (_stdcall *pGetHostName)( char *name, int namelen );
static dword (_stdcall *pNtohl)( dword netlong );
static dllfunc_t winsock_funcs[] =
{
{"bind", (void **) &pBind },
{"send", (void **) &pSend },
{"recv", (void **) &pRecv },
{"ntohs", (void **) &pNtohs },
{"htons", (void **) &pHtons },
{"ntohl", (void **) &pNtohl },
{"socket", (void **) &pSocket },
{"select", (void **) &pSelect },
{"sendto", (void **) &pSendTo },
{"connect", (void **) &pConnect },
{"recvfrom", (void **) &pRecvFrom },
{"inet_addr", (void **) &pInet_Addr },
{"WSAStartup", (void **) &pWSAStartup },
{"WSACleanup", (void **) &pWSACleanup },
{"setsockopt", (void **) &pSetSockopt },
{"ioctlsocket", (void **) &pIoctlSocket },
{"closesocket", (void **) &pCloseSocket },
{"gethostname", (void **) &pGetHostName },
{"gethostbyname", (void **) &pGetHostByName },
{"WSAGetLastError", (void **) &pWSAGetLastError },
{ NULL, NULL }
};
dll_info_t winsock_dll = { "wsock32.dll", winsock_funcs, NULL, NULL, NULL, true, 0 };
static WSADATA winsockdata;
static bool winsockInitialized = false;
static bool usingSocks = false;
static bool networkingEnabled = false;
static cvar_t *net_socks_enabled;
static cvar_t *net_socks_server;
static cvar_t *net_socks_port;
static cvar_t *net_socks_username;
static cvar_t *net_socks_password;
static struct sockaddr socksRelayAddr;
static SOCKET ip_socket;
static SOCKET socks_socket;
static char socksBuf[4096];
static byte localIP[MAX_IPS][4];
static int numIP;
void NET_OpenWinSock( void )
{
Sys_LoadLibrary( &winsock_dll );
}
void NET_FreeWinSock( void )
{
Sys_FreeLibrary( &winsock_dll );
}
/*
====================
NET_ErrorString
====================
*/
char *NET_ErrorString( void )
{
switch(pWSAGetLastError())
{
case WSAEINTR: return "WSAEINTR";
case WSAEBADF: return "WSAEBADF";
case WSAEACCES: return "WSAEACCES";
case WSAEDISCON: return "WSAEDISCON";
case WSAEFAULT: return "WSAEFAULT";
case WSAEINVAL: return "WSAEINVAL";
case WSAEMFILE: return "WSAEMFILE";
case WSAEWOULDBLOCK: return "WSAEWOULDBLOCK";
case WSAEINPROGRESS: return "WSAEINPROGRESS";
case WSAEALREADY: return "WSAEALREADY";
case WSAENOTSOCK: return "WSAENOTSOCK";
case WSAEDESTADDRREQ: return "WSAEDESTADDRREQ";
case WSAEMSGSIZE: return "WSAEMSGSIZE";
case WSAEPROTOTYPE: return "WSAEPROTOTYPE";
case WSAENOPROTOOPT: return "WSAENOPROTOOPT";
case WSAEPROTONOSUPPORT: return "WSAEPROTONOSUPPORT";
case WSAESOCKTNOSUPPORT: return "WSAESOCKTNOSUPPORT";
case WSAEOPNOTSUPP: return "WSAEOPNOTSUPP";
case WSAEPFNOSUPPORT: return "WSAEPFNOSUPPORT";
case WSAEAFNOSUPPORT: return "WSAEAFNOSUPPORT";
case WSAEADDRINUSE: return "WSAEADDRINUSE";
case WSAEADDRNOTAVAIL: return "WSAEADDRNOTAVAIL";
case WSAENETDOWN: return "WSAENETDOWN";
case WSAENETUNREACH: return "WSAENETUNREACH";
case WSAENETRESET: return "WSAENETRESET";
case WSAECONNABORTED: return "WSWSAECONNABORTEDAEINTR";
case WSAECONNRESET: return "WSAECONNRESET";
case WSAENOBUFS: return "WSAENOBUFS";
case WSAEISCONN: return "WSAEISCONN";
case WSAENOTCONN: return "WSAENOTCONN";
case WSAESHUTDOWN: return "WSAESHUTDOWN";
case WSAETOOMANYREFS: return "WSAETOOMANYREFS";
case WSAETIMEDOUT: return "WSAETIMEDOUT";
case WSAECONNREFUSED: return "WSAECONNREFUSED";
case WSAELOOP: return "WSAELOOP";
case WSAENAMETOOLONG: return "WSAENAMETOOLONG";
case WSAEHOSTDOWN: return "WSAEHOSTDOWN";
case WSASYSNOTREADY: return "WSASYSNOTREADY";
case WSAVERNOTSUPPORTED: return "WSAVERNOTSUPPORTED";
case WSANOTINITIALISED: return "WSANOTINITIALISED";
case WSAHOST_NOT_FOUND: return "WSAHOST_NOT_FOUND";
case WSATRY_AGAIN: return "WSATRY_AGAIN";
case WSANO_RECOVERY: return "WSANO_RECOVERY";
case WSANO_DATA: return "WSANO_DATA";
default: return "NO ERROR";
}
}
void NetadrToSockadr( netadr_t *a, struct sockaddr *s )
{
memset( s, 0, sizeof(*s));
if( a->type == NA_BROADCAST )
{
((struct sockaddr_in *)s)->sin_family = AF_INET;
((struct sockaddr_in *)s)->sin_port = a->port;
((struct sockaddr_in *)s)->sin_addr.s_addr = INADDR_BROADCAST;
}
else if( a->type == NA_IP )
{
((struct sockaddr_in *)s)->sin_family = AF_INET;
((struct sockaddr_in *)s)->sin_addr.s_addr = *(int *)&a->ip;
((struct sockaddr_in *)s)->sin_port = a->port;
}
}
void SockadrToNetadr( struct sockaddr *s, netadr_t *a )
{
if( s->sa_family == AF_INET )
{
a->type = NA_IP;
*(int *)&a->ip = ((struct sockaddr_in *)s)->sin_addr.s_addr;
a->port = ((struct sockaddr_in *)s)->sin_port;
}
else a->type = NA_NONE;
}
/*
=============
NET_StringToAdr
idnewt
192.246.40.70
=============
*/
bool NET_StringToSockaddr( const char *s, struct sockaddr *sadr )
{
struct hostent *h;
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 = pInet_Addr(s);
}
else
{
if(( h = pGetHostByName(s)) == 0 )
return 0;
*(int *)&((struct sockaddr_in *)sadr)->sin_addr = *(int *)h->h_addr_list[0];
}
return true;
}
char *NET_AdrToString( netadr_t a )
{
static char s[64];
if( a.type == NA_LOOPBACK ) com_sprintf (s, "loopback");
else if( a.type == NA_IP )
{
com_sprintf( s, "%i.%i.%i.%i:%i", a.ip[0], a.ip[1], a.ip[2], a.ip[3], pNtohs(a.port));
}
else memset( s, 0, sizeof(s));
return s;
}
/*
=============
NET_StringToAdr
idnewt
192.246.40.70
=============
*/
bool NET_StringToAdr( const char *s, netadr_t *a )
{
struct sockaddr sadr;
if( !NET_StringToSockaddr( s, &sadr ))
return false;
SockadrToNetadr( &sadr, a );
return true;
}
/*
==================
NET_GetPacket
Never called by the game logic, just the system event queing
==================
*/
bool NET_GetPacket( netadr_t *net_from, sizebuf_t *net_message )
{
int ret;
struct sockaddr from;
int fromlen;
int net_socket;
int err;
net_socket = ip_socket;
fromlen = sizeof(from);
ret = pRecvFrom( ip_socket, net_message->data, net_message->maxsize, 0, (struct sockaddr *)&from, &fromlen );
if( ret == SOCKET_ERROR )
{
err = pWSAGetLastError();
if( err == WSAEWOULDBLOCK || err == WSAECONNRESET )
return false;
MsgDev( D_ERROR, "NET_GetPacket: %s\n", NET_ErrorString());
return false;
}
memset(((struct sockaddr_in *)&from)->sin_zero, 0, 8 );
if( usingSocks && memcmp( &from, &socksRelayAddr, fromlen ) == 0 )
{
if( ret < 10 || net_message->data[0] != 0 || net_message->data[1] != 0 || net_message->data[2] != 0 || net_message->data[3] != 1 )
return false;
net_from->type = NA_IP;
net_from->ip[0] = net_message->data[4];
net_from->ip[1] = net_message->data[5];
net_from->ip[2] = net_message->data[6];
net_from->ip[3] = net_message->data[7];
net_from->port = *(short *)&net_message->data[8];
net_message->readcount = 10;
}
else
{
SockadrToNetadr( &from, net_from );
net_message->readcount = 0;
}
if( ret == net_message->maxsize )
{
MsgDev( D_ERROR, "NET_GetPacket: Oversize packet from %s\n", NET_AdrToString(*net_from));
return false;
}
net_message->cursize = ret;
return true;
}
/*
==================
NET_SendPacket
==================
*/
void NET_SendPacket( int length, const void *data, netadr_t to )
{
int ret;
struct sockaddr addr;
SOCKET net_socket;
switch( to.type )
{
case NA_IP:
case NA_BROADCAST:
net_socket = ip_socket;
default:
MsgDev( D_ERROR, "NET_SendPacket: bad address type\n");
return;
}
NetadrToSockadr( &to, &addr );
if( usingSocks && to.type == NA_IP )
{
socksBuf[0] = 0; // reserved
socksBuf[1] = 0; // reserved
socksBuf[2] = 0; // fragment ( not fragmented )
socksBuf[3] = 1; // address type: IPV4
*(int *)&socksBuf[4] = ((struct sockaddr_in *)&addr)->sin_addr.s_addr;
*(short *)&socksBuf[8] = ((struct sockaddr_in *)&addr)->sin_port;
Mem_Copy( &socksBuf[10], data, length );
ret = pSendTo( net_socket, socksBuf, length + 10, 0, &socksRelayAddr, sizeof(socksRelayAddr));
}
else ret = pSendTo( net_socket, data, length, 0, &addr, sizeof(addr));
if( ret == SOCKET_ERROR )
{
int err = pWSAGetLastError();
// wouldblock is silent
if( err == WSAEWOULDBLOCK ) return;
// some PPP links do not allow broadcasts and return an error
if( err == WSAEADDRNOTAVAIL && to.type == NA_BROADCAST )
return;
MsgDev( D_ERROR, "NET_SendPacket: %s\n", NET_ErrorString());
}
}
/*
==================
NET_IsLANAddress
LAN clients will have their rate var ignored
==================
*/
bool NET_IsLANAddress( netadr_t adr )
{
int i;
if( adr.type == NA_LOOPBACK )
return true;
if( adr.type != NA_IP )
return false;
// 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
if( adr.ip[0] == 127 && adr.ip[1] == 0 && adr.ip[2] == 0 && adr.ip[3] == 1 )
return true;
// class A
if(( adr.ip[0] & 0x80) == 0x00 )
{
for( i = 0; i < numIP; i++ )
{
if( adr.ip[0] == localIP[i][0] )
return true;
}
// the RFC1918 class a block will pass the above test
return false;
}
// 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 true;
// 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 true;
}
return false;
}
// 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 true;
// also check against the RFC1918 class c blocks
if( adr.ip[0] == 192 && localIP[i][0] == 192 && adr.ip[1] == 168 && localIP[i][1] == 168 )
return true;
}
return false;
}
/*
==================
NET_ShowIP
==================
*/
void NET_ShowIP( void )
{
int i;
for( i = 0; i < numIP; i++ )
{
Msg( "IP: %i.%i.%i.%i\n", localIP[i][0], localIP[i][1], localIP[i][2], localIP[i][3] );
}
}
/*
====================
NET_IPSocket
====================
*/
int NET_IPSocket( char *net_interface, int port )
{
SOCKET newsocket;
struct sockaddr_in address;
bool _true = true;
int i = 1;
int err;
if( net_interface ) MsgDev( D_INFO, "Opening IP socket: %s:%i\n", net_interface, port );
else MsgDev( D_INFO, "Opening IP socket: localhost:%i\n", port );
if(( newsocket = pSocket( AF_INET, SOCK_DGRAM, IPPROTO_UDP )) == INVALID_SOCKET )
{
err = pWSAGetLastError();
if( err != WSAEAFNOSUPPORT )
MsgDev( D_WARN, "NET_IPSocket: socket: %s\n", NET_ErrorString());
return 0;
}
// make it non-blocking
if( pIoctlSocket( newsocket, FIONBIO, &_true ) == SOCKET_ERROR )
{
MsgDev( D_WARN, "NET_IPSocket: ioctl FIONBIO: %s\n", NET_ErrorString());
return 0;
}
// make it broadcast capable
if( pSetSockopt( newsocket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i) ) == SOCKET_ERROR )
{
MsgDev( D_WARN, "NET_IPSocket: setsockopt SO_BROADCAST: %s\n", NET_ErrorString());
return 0;
}
if( !net_interface || !net_interface[0] || !com_stricmp( 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 = pHtons((short)port);
address.sin_family = AF_INET;
if( pBind( newsocket, (void *)&address, sizeof(address) ) == SOCKET_ERROR )
{
MsgDev( D_WARN, "UDP_OpenSocket: bind: %s\n", NET_ErrorString());
pCloseSocket( newsocket );
return 0;
}
return newsocket;
}
/*
====================
NET_OpenSocks
====================
*/
void NET_OpenSocks( int port )
{
struct sockaddr_in address;
bool rfc1929 = false;
int err;
struct hostent *h;
int len;
byte buf[64];
usingSocks = false;
MsgDev( D_INFO, "Opening connection to SOCKS server.\n" );
if(( socks_socket = pSocket( AF_INET, SOCK_STREAM, IPPROTO_TCP )) == INVALID_SOCKET )
{
err = pWSAGetLastError();
MsgDev( D_WARN, "NET_OpenSocks: socket: %s\n", NET_ErrorString());
return;
}
h = pGetHostByName( net_socks_server->string );
if( h == NULL )
{
err = pWSAGetLastError();
MsgDev( D_WARN, "NET_OpenSocks: gethostbyname: %s\n", NET_ErrorString());
return;
}
if( h->h_addrtype != AF_INET )
{
MsgDev( D_WARN, "NET_OpenSocks: gethostbyname: address type was not AF_INET\n");
return;
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = *(int *)h->h_addr_list[0];
address.sin_port = pHtons( (short)net_socks_port->integer );
if( pConnect( socks_socket, (struct sockaddr *)&address, sizeof( address )) == SOCKET_ERROR )
{
err = pWSAGetLastError();
MsgDev( D_WARN, "NET_OpenSocks: connect: %s\n", NET_ErrorString());
return;
}
// send socks authentication handshake
if( *net_socks_username->string || *net_socks_password->string )
rfc1929 = true;
buf[0] = 5; // SOCKS version
// method count
if( rfc1929 )
{
buf[1] = 2;
len = 4;
}
else
{
buf[1] = 1;
len = 3;
}
buf[2] = 0; // method #1 - method id #00: no authentication
if( rfc1929 ) buf[2] = 2; // method #2 - method id #02: username/password
if( pSend( socks_socket, buf, len, 0 ) == SOCKET_ERROR )
{
err = pWSAGetLastError();
MsgDev( D_WARN, "NET_OpenSocks: send: %s\n", NET_ErrorString());
return;
}
// get the response
len = pRecv( socks_socket, buf, 64, 0 );
if( len == SOCKET_ERROR )
{
err = pWSAGetLastError();
MsgDev( D_WARN, "NET_OpenSocks: recv: %s\n", NET_ErrorString());
return;
}
if( len != 2 || buf[0] != 5 )
{
MsgDev( D_WARN, "NET_OpenSocks: bad response\n" );
return;
}
switch( buf[1] )
{
case 0: // no authentication
case 2: // username/password authentication
break;
default:
MsgDev( D_WARN, "NET_OpenSocks: request denied\n" );
return;
}
// do username/password authentication if needed
if( buf[1] == 2 )
{
int ulen, plen;
// build the request
ulen = com_strlen( net_socks_username->string );
plen = com_strlen( net_socks_password->string );
buf[0] = 1; // username/password authentication version
buf[1] = ulen;
if( ulen ) Mem_Copy( &buf[2], net_socks_username->string, ulen );
buf[2 + ulen] = plen;
if( plen ) Mem_Copy( &buf[3 + ulen], net_socks_password->string, plen );
// send it
if( pSend( socks_socket, buf, 3 + ulen + plen, 0 ) == SOCKET_ERROR )
{
err = pWSAGetLastError();
MsgDev( D_WARN, "NET_OpenSocks: send: %s\n", NET_ErrorString());
return;
}
// get the response
len = pRecv( socks_socket, buf, 64, 0 );
if( len == SOCKET_ERROR )
{
err = pWSAGetLastError();
MsgDev( D_WARN, "NET_OpenSocks: recv: %s\n", NET_ErrorString());
return;
}
if( len != 2 || buf[0] != 1 )
{
MsgDev( D_WARN, "NET_OpenSocks: bad response\n" );
return;
}
if( buf[1] != 0 )
{
MsgDev( D_WARN, "NET_OpenSocks: authentication failed\n" );
return;
}
}
// send the UDP associate request
buf[0] = 5; // SOCKS version
buf[1] = 3; // command: UDP associate
buf[2] = 0; // reserved
buf[3] = 1; // address type: IPV4
*(int *)&buf[4] = INADDR_ANY;
*(short *)&buf[8] = pHtons((short)port); // port
if( pSend( socks_socket, buf, 10, 0 ) == SOCKET_ERROR )
{
err = pWSAGetLastError();
MsgDev( D_WARN, "NET_OpenSocks: send: %s\n", NET_ErrorString());
return;
}
// get the response
len = pRecv( socks_socket, buf, 64, 0 );
if( len == SOCKET_ERROR )
{
err = pWSAGetLastError();
MsgDev( D_WARN, "NET_OpenSocks: recv: %s\n", NET_ErrorString());
return;
}
if( len < 2 || buf[0] != 5 )
{
MsgDev( D_WARN, "NET_OpenSocks: bad response\n" );
return;
}
// check completion code
if( buf[1] != 0 )
{
MsgDev( D_WARN, "NET_OpenSocks: request denied: %i\n", buf[1] );
return;
}
if( buf[3] != 1 )
{
MsgDev( D_WARN, "NET_OpenSocks: relay address is not IPV4: %i\n", buf[3] );
return;
}
((struct sockaddr_in *)&socksRelayAddr)->sin_family = AF_INET;
((struct sockaddr_in *)&socksRelayAddr)->sin_addr.s_addr = *(int *)&buf[4];
((struct sockaddr_in *)&socksRelayAddr)->sin_port = *(short *)&buf[8];
memset(((struct sockaddr_in *)&socksRelayAddr)->sin_zero, 0, 8 );
usingSocks = true;
}
/*
=====================
NET_GetLocalAddress
=====================
*/
void NET_GetLocalAddress( void )
{
string hostname;
int error, ip, i = 0;
struct hostent *hostInfo;
char *p;
if( pGetHostName( hostname, MAX_STRING ) == SOCKET_ERROR )
{
error = pWSAGetLastError();
return;
}
hostInfo = pGetHostByName( hostname );
if( !hostInfo )
{
error = pWSAGetLastError();
return;
}
MsgDev( D_INFO, "Hostname: %s\n", hostInfo->h_name );
while(( p = hostInfo->h_aliases[i++] ) != NULL )
MsgDev( D_INFO, "Alias: %s\n", p );
if( hostInfo->h_addrtype != AF_INET )
return;
numIP = 0;
while(( p = hostInfo->h_addr_list[numIP] ) != NULL && numIP < MAX_IPS )
{
ip = pNtohl( *(int *)p);
localIP[ numIP ][0] = p[0];
localIP[ numIP ][1] = p[1];
localIP[ numIP ][2] = p[2];
localIP[ numIP ][3] = p[3];
MsgDev( D_INFO, "IP: %i.%i.%i.%i\n", (ip>>24) & 0xff, (ip>>16) & 0xff, (ip>>8) & 0xff, ip & 0xff );
numIP++;
}
}
/*
====================
NET_OpenIP
====================
*/
void NET_OpenIP( void )
{
cvar_t *ip;
int i, port;
ip = Cvar_Get( "net_ip", "localhost", CVAR_LATCH, "network ip address" );
port = Cvar_Get( "net_port", va( "%i", PORT_SERVER ), CVAR_LATCH, "network default port" )->integer;
// automatically scan for a valid port, so multiple
// dedicated servers can be started without requiring
// a different net_port for each one
for( i = 0; i < 10; i++ )
{
ip_socket = NET_IPSocket( ip->string, port + i );
if( ip_socket )
{
Cvar_SetValue( "net_port", port + i );
if( net_socks_enabled->integer )
NET_OpenSocks( port + i );
NET_GetLocalAddress();
return;
}
}
MsgDev( D_WARN, "Couldn't allocate IP port\n" );
}
/*
====================
NET_GetCvars
====================
*/
static bool NET_GetCvars( void )
{
bool modified = false;
if( net_socks_enabled && net_socks_enabled->modified )
modified = true;
net_socks_enabled = Cvar_Get( "net_socksenabled", "0", CVAR_LATCH|CVAR_ARCHIVE, "network using socks" );
if( net_socks_server && net_socks_server->modified )
modified = true;
net_socks_server = Cvar_Get( "net_socksserver", "", CVAR_LATCH|CVAR_ARCHIVE, "network server socket" );
if( net_socks_port && net_socks_port->modified )
modified = true;
net_socks_port = Cvar_Get( "net_socksport", "1080", CVAR_LATCH|CVAR_ARCHIVE, "using socks port" );
if( net_socks_username && net_socks_username->modified )
modified = true;
net_socks_username = Cvar_Get( "net_socksusername", "", CVAR_LATCH|CVAR_ARCHIVE, "autorization login" );
if( net_socks_password && net_socks_password->modified )
modified = true;
net_socks_password = Cvar_Get( "net_sockspassword", "", CVAR_LATCH|CVAR_ARCHIVE, "autorization password" );
return modified;
}
/*
====================
NET_Config
====================
*/
void NET_Config( bool net_enable )
{
bool modified, start, stop;
// get any latched changes to cvars
modified = NET_GetCvars();
// if enable state is the same and no cvars were modified, we have nothing to do
if( net_enable == networkingEnabled && !modified )
return;
if( net_enable == networkingEnabled )
{
if( net_enable )
{
stop = true;
start = true;
}
else
{
stop = false;
start = false;
}
}
else
{
if( net_enable )
{
stop = false;
start = true;
}
else
{
stop = true;
start = false;
}
networkingEnabled = net_enable;
}
if( stop )
{
if( ip_socket && ip_socket != INVALID_SOCKET )
{
pCloseSocket( ip_socket );
ip_socket = 0;
}
if( socks_socket && socks_socket != INVALID_SOCKET )
{
pCloseSocket( socks_socket );
socks_socket = 0;
}
}
if( start ) NET_OpenIP();
}
/*
====================
NET_Init
====================
*/
void NET_Init( void )
{
int r;
NET_OpenWinSock(); // loading wsock32.dll
r = pWSAStartup(MAKEWORD( 1, 1 ), &winsockdata );
if( r )
{
MsgDev( D_WARN, "NET_Init: winsock initialization failed: %d\n", r );
return;
}
winsockInitialized = true;
MsgDev( D_NOTE, "NET_Init: suceeded\n" );
NET_GetCvars(); // register cvars
NET_Config( true ); // FIXME: testing!
}
/*
====================
NET_Shutdown
====================
*/
void NET_Shutdown( void )
{
if( !winsockInitialized )
return;
NET_Config( false );
pWSACleanup();
NET_FreeWinSock();
winsockInitialized = false;
}

View File

@ -6,9 +6,14 @@
#include "launch.h"
#include "mathlib.h"
#define MAX_QUED_EVENTS 256
#define MASK_QUED_EVENTS (MAX_QUED_EVENTS - 1)
system_t Sys;
stdlib_api_t com;
launch_exp_t *Host; // callback to mainframe
sys_event_t event_que[MAX_QUED_EVENTS];
int event_head, event_tail;
FILE *logfile;
dll_info_t common_dll = { "common.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(launch_exp_t) };
@ -16,7 +21,7 @@ dll_info_t engine_dll = { "engine.dll", NULL, "CreateAPI", NULL, NULL, true, siz
dll_info_t viewer_dll = { "viewer.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(launch_exp_t) };
dll_info_t ripper_dll = { "ripper.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(launch_exp_t) };
static const char *show_credits = "\n\n\n\n\tCopyright XashXT Group 2007 ©\n\t\
static const char *show_credits = "\n\n\n\n\tCopyright XashXT Group 2008 ©\n\t\
All Rights Reserved\n\n\t Visit www.xash.ru\n";
// stubs
@ -39,6 +44,8 @@ void Sys_GetStdAPI( void )
com.input = Sys_Input;
com.sleep = Sys_Sleep;
com.clipboard = Sys_GetClipboardData;
com.queevent = Sys_QueEvent; // new system event
com.getevent = Sys_GetEvent; // get system events
com.keyevents = Sys_SendKeyEvents;
// crclib.c funcs
@ -66,6 +73,17 @@ void Sys_GetStdAPI( void )
com.getelement = _mem_get_array_element;
com.arraysize = _mem_array_size;
// network.c funcs
com.NET_Init = NET_Init;
com.NET_Shutdown = NET_Shutdown;
com.NET_ShowIP = NET_ShowIP;
com.NET_Config = NET_Config;
com.NET_AdrToString = NET_AdrToString;
com.NET_IsLANAddress = NET_IsLANAddress;
com.NET_StringToAdr = NET_StringToAdr;
com.NET_RecvPacket = NET_GetPacket;
com.NET_SendPacket = NET_SendPacket;
// common functions
com.Com_InitRootDir = FS_InitRootDir; // init custom rootdir
com.Com_LoadGameInfo = FS_LoadGameInfo; // gate game info from script file
@ -404,6 +422,7 @@ void Sys_CreateInstance( void )
Sys.Free = Host->Free;
Sys.CPrint = Host->CPrint;
Sys.Cmd = Host->Cmd;
Sys.SZ_Init = Host->SZInit;
break;
case HOST_CREDITS:
Sys_Break( show_credits );
@ -684,7 +703,7 @@ double Sys_DoubleTime( void )
if( firsttimegettime )
{
timeBeginPeriod (1);
timeBeginPeriod( 1 );
firsttimegettime = false;
}
newtime = ( double )timeGetTime() * 0.001;
@ -757,6 +776,25 @@ char *Sys_GetClipboardData( void )
return data;
}
/*
================
Sys_GetCurrentUser
returns username for current profile
================
*/
char *Sys_GetCurrentUser( void )
{
static string s_userName;
dword size = sizeof( s_userName );
if( !GetUserName( s_userName, &size ))
com_strcpy( s_userName, "player" );
if( !s_userName[0] )
com_strcpy( s_userName, "player" );
return s_userName;
}
/*
================
@ -1197,6 +1235,118 @@ void Sys_RunThreadsOn( int workcnt, bool showpacifier, void(*func)(int))
if( pacifier ) Msg(" Done [%.2f sec]\n", end - start);
}
/*
================
Sys_QueEvent
A time of 0 will get the current time
Ptr should either be null, or point to a block of data that can
be freed by the game later.
================
*/
void Sys_QueEvent( dword time, ev_type_t type, int value, int value2, int length, void *ptr )
{
sys_event_t *ev;
ev = &event_que[event_head & MASK_QUED_EVENTS];
if( event_head - event_tail >= MAX_QUED_EVENTS )
{
MsgDev( D_ERROR, "Sys_QueEvent: overflow\n");
// make sure what memory is allocated by engine
if(Mem_IsAllocated( ev->data )) Mem_Free( ev->data );
event_tail++;
}
event_head++;
// presets
if( time == 0 ) time = Sys_Milliseconds();
else if( time == -1 ) time = Sys.msg_time;
ev->time = time;
ev->type = type;
ev->value[0] = value;
ev->value[1] = value2;
ev->length = length;
ev->data = ptr;
}
/*
================
Sys_GetEvent
================
*/
sys_event_t Sys_GetEvent( void )
{
MSG msg;
sys_event_t ev;
char *s;
sizebuf_t netmsg;
netadr_t adr;
// return if we have data
if( event_head > event_tail )
{
event_tail++;
return event_que[(event_tail-1) & MASK_QUED_EVENTS];
}
// pump the message loop
while( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ))
{
if(!GetMessage( &msg, NULL, 0, 0))
{
Sys.error = true;
Sys_Exit();
}
Sys.msg_time = msg.time;
TranslateMessage(&msg );
DispatchMessage( &msg );
}
// check for console commands
s = Sys_Input();
if( s )
{
char *b;
int len;
len = com_strlen( s ) + 1;
b = Malloc( len );
com_strncpy( b, s, len - 1 );
Sys_QueEvent( 0, SE_CONSOLE, 0, 0, len, b );
}
// check for network packets
if( Sys.SZ_Init ) Sys.SZ_Init( &netmsg, Sys.packet_received, sizeof( Sys.packet_received ));
if( NET_GetPacket( &adr, &netmsg ))
{
netadr_t *buf;
int len;
// copy out to a seperate buffer for qeueing
// the readcount stepahead is for SOCKS support
len = sizeof(netadr_t) + netmsg.cursize - netmsg.readcount;
buf = Malloc( len );
*buf = adr;
Mem_Copy( buf + 1, &netmsg.data[netmsg.readcount], netmsg.cursize - netmsg.readcount );
Sys_QueEvent( 0, SE_PACKET, 0, 0, len, buf );
}
// return if we have data
if( event_head > event_tail )
{
event_tail++;
return event_que[(event_tail - 1) & MASK_QUED_EVENTS];
}
// create an empty event to return
memset( &ev, 0, sizeof(ev));
ev.time = timeGetTime();
return ev;
}
//=======================================================================
// REGISTRY COMMON TOOLS
//=======================================================================

View File

@ -144,6 +144,10 @@ SOURCE=.\common\memlib.c
# End Source File
# Begin Source File
SOURCE=.\common\network.c
# End Source File
# Begin Source File
SOURCE=.\common\parselib.c
# End Source File
# Begin Source File

View File

@ -45,6 +45,8 @@ typedef struct system_s
char log_path[MAX_SYSPATH];
bool hooked_out;
bool stuffcmdsrun;
byte packet_received[MAX_MSGLEN]; // network data
uint msg_time; // GetMessage time
HINSTANCE hInstance;
LPTOP_LEVEL_EXCEPTION_FILTER oldFilter;
@ -70,7 +72,8 @@ typedef struct system_s
void ( *Main ) ( void ); // host frame
void ( *Free ) ( void ); // close host
void ( *Cmd ) ( void ); // cmd forward to server
void (*CPrint)( const char *msg ); // console print
void (*CPrint) ( const char *msg ); // console print
void (*SZ_Init)( sizebuf_t *buf, byte *data, size_t length );
} system_t;
typedef struct cvar_s
@ -117,6 +120,7 @@ void Sys_LookupInstance( void );
double Sys_DoubleTime( void );
dword Sys_Milliseconds( void );
char *Sys_GetClipboardData( void );
char *Sys_GetCurrentUser( void );
void Sys_Sleep( int msec );
void Sys_Init( void );
void Sys_Exit( void );
@ -133,6 +137,8 @@ void Sys_PrintLog( const char *pMsg );
void Sys_Print(const char *pMsg);
void Sys_Msg( const char *pMsg, ... );
void Sys_MsgDev( int level, const char *pMsg, ... );
sys_event_t Sys_GetEvent( void );
void Sys_QueEvent( dword time, ev_type_t type, int value, int value2, int length, void *ptr );
int Sys_GetThreadWork( void );
void Sys_ThreadWorkerFunction (int threadnum);
void Sys_ThreadSetDefault (void);
@ -149,6 +155,19 @@ void Sys_RunThreadsOn (int workcnt, bool showpacifier, void(*func)(int));
bool REG_GetValue( HKEY hKey, const char *SubKey, const char *Value, char *pBuffer);
bool REG_SetValue( HKEY hKey, const char *SubKey, const char *Value, char *pBuffer);
//
// network.c
//
void NET_Init( void );
void NET_Shutdown( void );
void NET_ShowIP( void ); // just for debug
void NET_Config( bool net_enable );
char *NET_AdrToString( netadr_t a );
bool NET_IsLANAddress( netadr_t adr );
bool NET_StringToAdr( const char *s, netadr_t *a );
bool NET_GetPacket( netadr_t *net_from, sizebuf_t *net_message );
void NET_SendPacket( int length, const void *data, netadr_t to );
//
// stdlib.c
//

View File

@ -30,6 +30,7 @@
#define MAX_STRING_TOKENS 80
#define MAX_TOKEN_CHARS 128
#define MAX_STRING_CHARS 1024
#define MAX_MSGLEN 16384 // max length of a message, which may be fragmented into multiple packets
#define COLOR_BLACK '0'
#define COLOR_RED '1'
@ -162,6 +163,47 @@ enum host_state
HOST_NULL, // terminator
};
typedef enum
{
SE_NONE = 0, // ev.time is still valid
SE_KEY, // ev.value is a key code, ev.value2 is the down flag
SE_CHAR, // ev.value is an ascii char
SE_MOUSE, // ev.value and ev.value2 are reletive signed x / y moves
SE_CONSOLE, // ev.data is a char*
SE_PACKET // ev.data is a netadr_t followed by data bytes to ev.length
} ev_type_t;
typedef struct
{
dword time;
ev_type_t type;
int value[2];
void *data;
size_t length;
} sys_event_t;
typedef enum { NA_NONE, NA_LOOPBACK, NA_BROADCAST, NA_IP } netadrtype_t;
typedef enum { NS_CLIENT, NS_SERVER } netsrc_t;
typedef struct
{
netadrtype_t type;
byte ip[4];
word port;
} netadr_t;
typedef struct sizebuf_s
{
bool overflowed; // set to true if the buffer size failed
byte *data;
int maxsize;
int cursize;
int readcount;
int errorcount; // cause by errors
int bit; // for bitwise reads and writes
} sizebuf_t;
enum dev_level
{
D_INFO = 1, // "-dev 1", shows various system messages

View File

@ -60,9 +60,9 @@
// button bits
#define BUTTON_ATTACK 1
#define BUTTON_USE 2
#define BUTTON_ATTACK2 4
#define BUTTONS_ATTACK (BUTTON_ATTACK | BUTTON_ATTACK2)
#define BUTTON_ATTACK2 2
#define BUTTON_USE 4
#define BUTTON_WALKING 8
#define BUTTON_ANY 128 // any key whatsoever
#define PM_MAXTOUCH 32
@ -268,12 +268,17 @@ typedef struct player_state_s
// user_cmd_t communication
typedef struct usercmd_s
{
byte msec;
byte buttons;
short angles[3];
byte impulse; // remove?
int buttons;
int angles[3];
int servertime;
byte impulse;
signed char forwardmove;
signed char sidemove;
signed char upmove;
// get rid of this
byte lightlevel; // light level the player is standing on
short forwardmove, sidemove, upmove;
byte msec;
} usercmd_t;
typedef struct pmove_s
@ -299,16 +304,6 @@ typedef struct pmove_s
int (*pointcontents)( vec3_t point );
} pmove_t;
typedef struct sizebuf_s
{
bool overflowed; // set to true if the buffer size failed
byte *data;
int maxsize;
int cursize;
int readcount;
int errorcount; // cause by errors
} sizebuf_t;
/*
==============================================================================
@ -325,6 +320,7 @@ typedef struct launch_exp_s
void ( *Free ) ( void ); // close host
void ( *Cmd ) ( void ); // forward cmd to server
void (*CPrint) ( const char *msg ); // host print
void (*SZInit)( sizebuf_t *buf, byte *data, size_t length );// init sizebuf from events
} launch_exp_t;
/*

View File

@ -28,7 +28,9 @@ typedef struct stdilib_api_s
char *(*input)( void ); // system console input
void (*sleep)( int msec ); // sleep for some msec
char *(*clipboard)( void ); // get clipboard data
uint (*keyevents)( void ); // peek windows message
void (*queevent)( dword time, ev_type_t type, int value, int value2, int length, void *ptr );
sys_event_t (*getevent)( void ); // get system events
uint (*keyevents)( void ); // peek windows message (remove this)
// crclib.c funcs
void (*crc_init)(word *crcvalue); // set initial crc value
@ -59,6 +61,17 @@ typedef struct stdilib_api_s
void *(*getelement)( byte *array, size_t index );
size_t (*arraysize)( byte *arrayptr );
// network.c funcs
void (*NET_Init)( void );
void (*NET_Shutdown)( void );
void (*NET_ShowIP)( void );
void (*NET_Config)( bool net_enable );
char *(*NET_AdrToString)( netadr_t a );
bool (*NET_IsLANAddress)( netadr_t adr );
bool (*NET_StringToAdr)( const char *s, netadr_t *a );
bool (*NET_RecvPacket)( netadr_t *net_from, sizebuf_t *net_message );
void (*NET_SendPacket)( int length, const void *data, netadr_t to );
// common functions
void (*Com_InitRootDir)( char *path ); // init custom rootdir
void (*Com_LoadGameInfo)( const char *filename ); // gate game info from script file
@ -278,6 +291,21 @@ filesystem manager
#define FS_CheckParm com.Com_CheckParm
#define FS_GetParmFromCmdLine com.Com_GetParm
/*
===========================================
network messages
===========================================
*/
#define NET_Init com.NET_Init
#define NET_Shutdown com.NET_Shutdown
#define NET_ShowIP com.NET_ShowIP
#define NET_Config com.NET_Config
#define NET_AdrToString com.NET_AdrToString
#define NET_IsLANAddress com.NET_IsLANAddress
#define Sys_StringToAdr com.NET_StringToAdr
#define Sys_RecvPacket com.NET_RecvPacket
#define Sys_SendPacket com.NET_SendPacket
/*
===========================================
console variables
@ -357,6 +385,8 @@ misc utils
#define Sys_Sleep com.sleep
#define Sys_Print com.print
#define Sys_ConsoleInput com.input
#define Sys_GetEvent com.getevent
#define Sys_QueEvent com.queevent
#define Sys_GetKeyEvents com.keyevents
#define Sys_GetClipboardData com.clipboard
#define Sys_Quit com.exit