Revert protocol 69 pending further discussion (#4962)

This commit is contained in:
Thilo Schulz 2011-04-27 20:17:45 +00:00
parent 88693f9abd
commit d34c6b7e0b
12 changed files with 247 additions and 508 deletions

382
README
View file

@ -214,15 +214,9 @@ New cvars
ipv6 servers on the local network
net_mcastiface - outgoing interface to use for scan
oldprotocol - when encountering a server/client that
only supports the version configured in
this cvar, ioquake3 will use the old and
less secure protocol from quake3 1.32c.
protocol - Allow changing protocol version
(startup only)
protocol - Allow changing protocol version that is
sent to the server (startup only)
r_allowResize - make window resizable (SDL only)
r_ext_texture_filter_anisotropic - anisotropic texture filtering
r_zProj - distance of observer camera to projection
@ -283,8 +277,7 @@ New commands
which <filename/path> - print out the path on disk to a loaded item
--------------------------------------------------------- README for Users -----
------------------------------------------------------------ Miscellaneous -----
Using shared libraries instead of qvm
To force Q3 to use shared libraries instead of qvms run it with the following
@ -312,6 +305,175 @@ Help! Ioquake3 won't give me an fps of X anymore when setting com_maxfps!
In this case you can always revert back to the old behaviour by setting the
cvar com_busyWait to 1.
QuakeLive mouse acceleration (patch and this text written by TTimo from id)
I've been using an experimental mouse acceleration code for a while, and
decided to make it available to everyone. Don't be too worried if you don't
understand the explanations below, this is mostly intended for advanced
players:
To enable it, set cl_mouseAccelStyle 1 (0 is the default/legacy behavior)
New style is controlled with 3 cvars:
sensitivity
cl_mouseAccel
cl_mouseAccelOffset
The old code (cl_mouseAccelStyle 0) can be difficult to calibrate because if
you have a base sensitivity setup, as soon as you set a non zero acceleration
your base sensitivity at low speeds will change as well. The other problem
with style 0 is that you are stuck on a square (power of two) acceleration
curve.
The new code tries to solve both problems:
Once you setup your sensitivity to feel comfortable and accurate enough for
low mouse deltas with no acceleration (cl_mouseAccel 0), you can start
increasing cl_mouseAccel and tweaking cl_mouseAccelOffset to get the
amplification you want for high deltas with little effect on low mouse deltas.
cl_mouseAccel is a power value. Should be >= 1, 2 will be the same power curve
as style 0. The higher the value, the faster the amplification grows with the
mouse delta.
cl_mouseAccelOffset sets how much base mouse delta will be doubled by
acceleration. The closer to zero you bring it, the more acceleration will
happen at low speeds. This is also very useful if you are changing to a new
mouse with higher dpi, if you go from 500 to 1000 dpi, you can divide your
cl_mouseAccelOffset by two to keep the same overall 'feel' (you will likely
gain in precision when you do that, but that is not related to mouse
acceleration).
Mouse acceleration is tricky to configure, and when you do you'll have to
re-learn your aiming. But you will find that it's very much forth it in the
long run.
If you try the new acceleration code and start using it, I'd be very
interested by your feedback.
64bit mods
If you wish to compile external mods as shared libraries on a 64bit platform,
and the mod source is derived from the id Q3 SDK, you will need to modify the
interface code a little. Open the files ending in _syscalls.c and change
every instance of int to intptr_t in the declaration of the syscall function
pointer and the dllEntry function. Also find the vmMain function for each
module (usually in cg_main.c g_main.c etc.) and similarly replace the return
value in the prototype with intptr_t (arg0, arg1, ...stay int).
Add the following code snippet to q_shared.h:
#ifdef Q3_VM
typedef int intptr_t;
#else
#include <stdint.h>
#endif
Note if you simply wish to run mods on a 64bit platform you do not need to
recompile anything since by default Q3 uses a virtual machine system.
Creating mods compatible with Q3 1.32b
If you're using this package to create mods for the last official release of
Q3, it is necessary to pass the commandline option '-vq3' to your invocation
of q3asm. This is because by default q3asm outputs an updated qvm format that
is necessary to fix a bug involving the optimizing pass of the x86 vm JIT
compiler.
Creating standalone games
Have you finished the daunting task of removing all dependencies on the Q3
game data? You probably now want to give your users the opportunity to play
the game without owning a copy of Q3, which consequently means removing cd-key
and authentication server checks. In addition to being a straightforward Q3
client, ioquake3 also purports to be a reliable and stable code base on which
to base your game project.
However, before you start compiling your own version of ioquake3, you have to
ask yourself: Have we changed or will we need to change anything of importance
in the engine?
If your answer to this question is "no", it probably makes no sense to build
your own binaries. Instead, you can just use the pre-built binaries on the
website. Just make sure the game is called with:
+set com_basegame <yournewbase>
in any links/scripts you install for your users to start the game. The
binary must not detect any original quake3 game pak files. If this
condition is met, the game will set com_standalone to 1 and is then running
in stand alone mode.
If you want the engine to use a different directory in your homepath than
e.g. "Quake3" on Windows or ".q3a" on Linux, then set a new name at startup
by adding
+set com_homepath <homedirname>
to the command line. Then you can control which kind of messages to send to
the master server:
+set sv_heartbeat <heartbeat> +set sv_flatline <flatline>
+set cl_gamename <gamename>
The <heartbeat> and <flatline> message can be specific to your game. The
flatline message is sent to signal the master server that the game server is
quitting. Vanilla quake3 uses "QuakeArena-1" both for the heartbeat and
flatline messages.
The cl_gamename message is for dpmaster to specify which game the client
wants a server list for. It is only used in the new ipv6 based getServersExt
query.
Example line:
+set com_basegame basefoo +set com_homepath .foo
+set sv_heartbeat fooalive +set sv_flatline foodead
+set cl_gamename foo
If you really changed parts that would make vanilla ioquake3 incompatible with
your mod, we have included another way to conveniently build a stand-alone
binary. Just run make with the option BUILD_STANDALONE=1. Don't forget to edit
the PRODUCT_NAME and subsequent #defines in qcommon/q_shared.h with
information appropriate for your project.
While a lot of work has been put into ioquake3 that you can benefit from free
of charge, it does not mean that you have no obligations to fulfil. Please be
aware that as soon as you start distributing your game with an engine based on
our sources we expect you to fully comply with the requirements as stated in
the GPL. That includes making sources and modifications you made to the
ioquake3 engine as well as the game-code used to compile the .qvm files for
the game logic freely available to everyone. Furthermore, note that the "QIIIA
Game Source License" prohibits distribution of mods that are intended to
operate on a version of Q3 not sanctioned by id software:
"with this Agreement, ID grants to you the non-exclusive and limited right
to distribute copies of the Software ... for operation only with the full
version of the software game QUAKE III ARENA"
This means that if you're creating a standalone game, you cannot use said
license on any portion of the product. As the only other license this code has
been released under is the GPL, this is the only option.
This does NOT mean that you cannot market this game commercially. The GPL does
not prohibit commercial exploitation and all assets (e.g. textures, sounds,
maps) created by yourself are your property and can be sold like every other
game you find in stores.
cl_guid Support
cl_guid is a cvar which is part of the client's USERINFO string. Its value
is a 32 character string made up of [a-f] and [0-9] characters. This
value is pseudo-unique for every player. Id's Quake 3 Arena client also
sets cl_guid, but only if Punkbuster is enabled on the client.
If cl_guidServerUniq is non-zero (the default), then this value is also
pseudo-unique for each server a client connects to (based on IP:PORT of
the server).
The purpose of cl_guid is to add an identifier for each player on
a server. This value can be reset by the client at any time so it's not
useful for blocking access. However, it can have at least two uses in
your mod's game code:
1) improve logging to allow statistical tools to index players by more
than just name
2) granting some weak admin rights to players without requiring passwords
Using HTTP/FTP Download Support (Server)
You can enable redirected downloads on your server even if it's not
an ioquake3 server. You simply need to use the 'sets' command to put
@ -415,208 +577,6 @@ SDL Keyboard Differences
text. Also, in addition to the nominated console keys, Shift-ESC is hard
coded to always toggle the console.
QuakeLive mouse acceleration (patch and this text written by TTimo from id)
I've been using an experimental mouse acceleration code for a while, and
decided to make it available to everyone. Don't be too worried if you don't
understand the explanations below, this is mostly intended for advanced
players:
To enable it, set cl_mouseAccelStyle 1 (0 is the default/legacy behavior)
New style is controlled with 3 cvars:
sensitivity
cl_mouseAccel
cl_mouseAccelOffset
The old code (cl_mouseAccelStyle 0) can be difficult to calibrate because if
you have a base sensitivity setup, as soon as you set a non zero acceleration
your base sensitivity at low speeds will change as well. The other problem
with style 0 is that you are stuck on a square (power of two) acceleration
curve.
The new code tries to solve both problems:
Once you setup your sensitivity to feel comfortable and accurate enough for
low mouse deltas with no acceleration (cl_mouseAccel 0), you can start
increasing cl_mouseAccel and tweaking cl_mouseAccelOffset to get the
amplification you want for high deltas with little effect on low mouse deltas.
cl_mouseAccel is a power value. Should be >= 1, 2 will be the same power curve
as style 0. The higher the value, the faster the amplification grows with the
mouse delta.
cl_mouseAccelOffset sets how much base mouse delta will be doubled by
acceleration. The closer to zero you bring it, the more acceleration will
happen at low speeds. This is also very useful if you are changing to a new
mouse with higher dpi, if you go from 500 to 1000 dpi, you can divide your
cl_mouseAccelOffset by two to keep the same overall 'feel' (you will likely
gain in precision when you do that, but that is not related to mouse
acceleration).
Mouse acceleration is tricky to configure, and when you do you'll have to
re-learn your aiming. But you will find that it's very much forth it in the
long run.
If you try the new acceleration code and start using it, I'd be very
interested by your feedback.
---------------------------------------------------- README for Developers -----
64bit mods
If you wish to compile external mods as shared libraries on a 64bit platform,
and the mod source is derived from the id Q3 SDK, you will need to modify the
interface code a little. Open the files ending in _syscalls.c and change
every instance of int to intptr_t in the declaration of the syscall function
pointer and the dllEntry function. Also find the vmMain function for each
module (usually in cg_main.c g_main.c etc.) and similarly replace the return
value in the prototype with intptr_t (arg0, arg1, ...stay int).
Add the following code snippet to q_shared.h:
#ifdef Q3_VM
typedef int intptr_t;
#else
#include <stdint.h>
#endif
Note if you simply wish to run mods on a 64bit platform you do not need to
recompile anything since by default Q3 uses a virtual machine system.
Creating mods compatible with Q3 1.32b
If you're using this package to create mods for the last official release of
Q3, it is necessary to pass the commandline option '-vq3' to your invocation
of q3asm. This is because by default q3asm outputs an updated qvm format that
is necessary to fix a bug involving the optimizing pass of the x86 vm JIT
compiler.
Creating standalone games
Have you finished the daunting task of removing all dependencies on the Q3
game data? You probably now want to give your users the opportunity to play
the game without owning a copy of Q3, which consequently means removing cd-key
and authentication server checks. In addition to being a straightforward Q3
client, ioquake3 also purports to be a reliable and stable code base on which
to base your game project.
However, before you start compiling your own version of ioquake3, you have to
ask yourself: Have we changed or will we need to change anything of importance
in the engine?
If your answer to this question is "no", it probably makes no sense to build
your own binaries. Instead, you can just use the pre-built binaries on the
website. Just make sure the game is called with:
+set com_basegame <yournewbase>
in any links/scripts you install for your users to start the game. The
binary must not detect any original quake3 game pak files. If this
condition is met, the game will set com_standalone to 1 and is then running
in stand alone mode.
If you want the engine to use a different directory in your homepath than
e.g. "Quake3" on Windows or ".q3a" on Linux, then set a new name at startup
by adding
+set com_homepath <homedirname>
to the command line. You can also control which kind of messages to send to
the master server:
+set sv_heartbeat <heartbeat> +set sv_flatline <flatline>
+set cl_gamename <gamename>
The <heartbeat> and <flatline> message can be specific to your game. The
flatline message is sent to signal the master server that the game server is
quitting. Vanilla quake3 uses "QuakeArena-1" both for the heartbeat and
flatline messages.
The cl_gamename message is for dpmaster to specify which game the client
wants a server list for. It is only used in the new ipv6 based getServersExt
query.
Example line:
+set com_basegame basefoo +set com_homepath .foo
+set sv_heartbeat fooalive +set sv_flatline foodead
+set cl_gamename foo
If you really changed parts that would make vanilla ioquake3 incompatible with
your mod, we have included another way to conveniently build a stand-alone
binary. Just run make with the option BUILD_STANDALONE=1. Don't forget to edit
the PRODUCT_NAME and subsequent #defines in qcommon/q_shared.h with
information appropriate for your project.
While a lot of work has been put into ioquake3 that you can benefit from free
of charge, it does not mean that you have no obligations to fulfil. Please be
aware that as soon as you start distributing your game with an engine based on
our sources we expect you to fully comply with the requirements as stated in
the GPL. That includes making sources and modifications you made to the
ioquake3 engine as well as the game-code used to compile the .qvm files for
the game logic freely available to everyone. Furthermore, note that the "QIIIA
Game Source License" prohibits distribution of mods that are intended to
operate on a version of Q3 not sanctioned by id software:
"with this Agreement, ID grants to you the non-exclusive and limited right
to distribute copies of the Software ... for operation only with the full
version of the software game QUAKE III ARENA"
This means that if you're creating a standalone game, you cannot use said
license on any portion of the product. As the only other license this code has
been released under is the GPL, this is the only option.
This does NOT mean that you cannot market this game commercially. The GPL does
not prohibit commercial exploitation and all assets (e.g. textures, sounds,
maps) created by yourself are your property and can be sold like every other
game you find in stores.
Network protocols
There are now two cvars that give you some degree of freedom over the reported
protocol versions between clients and servers: "protocol" and "oldprotocol".
The reason for this is that some standalone games increased the protocol
number even though nothing really changed in their protocol and the ioquake3
engine is still fully compatible.
In order to fix a vulnerability in the network protocol as outlined in
http://aluigi.altervista.org/papers/q3noclient.txt
a new network protocol was introduced that defends against such attacks.
Unfortunately, this protocol will be incompatible to the original quake3 1.32c
which is the latest official release from id.
Luckily, ioquake3 has backwards compatibility, on the client as well as on the
server. This means ioquake3 players can play on old servers just as ioquake3
servers are able to service old clients.
The cvar "protocol" denotes the protocol version for the new hardened
protocol, whereas the "oldprotocol" cvar denotes the protocol version for the
legacy protocol.
If the value for "oldprotocol" and "protocol" is identical, then the legacy
protocol is always used. If oldprotocol is set to 0, then support for the
legacy protocol is disabled.
Mods that use a standalone engine obviously do not require dual protocol
support, and it is turned off if the engine is compiled with STANDALONE per
default. You can enable it in q_shared.h if desired by defining
PROTOCOL_SUPPORT_OLD.
cl_guid Support
cl_guid is a cvar which is part of the client's USERINFO string. Its value
is a 32 character string made up of [a-f] and [0-9] characters. This
value is pseudo-unique for every player. Id's Quake 3 Arena client also
sets cl_guid, but only if Punkbuster is enabled on the client.
If cl_guidServerUniq is non-zero (the default), then this value is also
pseudo-unique for each server a client connects to (based on IP:PORT of
the server).
The purpose of cl_guid is to add an identifier for each player on
a server. This value can be reset by the client at any time so it's not
useful for blocking access. However, it can have at least two uses in
your mod's game code:
1) improve logging to allow statistical tools to index players by more
than just name
2) granting some weak admin rights to players without requiring passwords
PNG support
ioquake3 supports the use of PNG (Portable Network Graphic) images as
textures. It should be noted that the use of such images in a map will

View file

@ -533,6 +533,7 @@ void CL_WriteDemoMessage ( msg_t *msg, int headerBytes ) {
len = clc.serverMessageSequence;
swlen = LittleLong( len );
FS_Write (&swlen, 4, clc.demofile);
// skip the packet sequencing information
len = msg->cursize - headerBytes;
swlen = LittleLong(len);
@ -635,24 +636,14 @@ void CL_Record_f( void ) {
if ( Cmd_Argc() == 2 ) {
s = Cmd_Argv(1);
Q_strncpyz( demoName, s, sizeof( demoName ) );
#ifdef PROTOCOL_SUPPORT_OLD
if(clc.compat)
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_oldprotocol->integer);
else
#endif
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer);
Com_sprintf (name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer );
} else {
int number;
// scan for a free demo name
for ( number = 0 ; number <= 9999 ; number++ ) {
CL_DemoFilename( number, demoName );
#ifdef PROTOCOL_SUPPORT_OLD
if(clc.compat)
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_oldprotocol->integer);
else
#endif
Com_sprintf(name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer);
Com_sprintf (name, sizeof(name), "demos/%s.%s%d", demoName, DEMOEXT, com_protocol->integer );
if (!FS_FileExists(name))
break; // file doesn't exist
@ -674,6 +665,7 @@ void CL_Record_f( void ) {
clc.spDemoRecording = qfalse;
}
Q_strncpyz( clc.demoName, demoName, sizeof( clc.demoName ) );
// don't start saving messages until a non-delta compressed message is received
@ -897,62 +889,36 @@ void CL_ReadDemoMessage( void ) {
CL_WalkDemoExt
====================
*/
static int CL_WalkDemoExt(char *arg, char *name, int *demofile)
static void CL_WalkDemoExt(char *arg, char *name, int *demofile)
{
int i = 0;
*demofile = 0;
#ifdef PROTOCOL_SUPPORT_OLD
if(com_oldprotocol->integer > 0)
{
Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_oldprotocol->integer);
FS_FOpenFileRead(name, demofile, qtrue);
if (*demofile)
{
Com_Printf("Demo file: %s\n", name);
return com_oldprotocol->integer;
}
}
if(com_protocol->integer != com_oldprotocol->integer)
#endif
{
Com_sprintf(name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_protocol->integer);
FS_FOpenFileRead(name, demofile, qtrue);
Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, com_protocol->integer);
if (*demofile)
{
Com_Printf("Demo file: %s\n", name);
return com_protocol->integer;
}
FS_FOpenFileRead( name, demofile, qtrue );
if (*demofile)
{
Com_Printf("Demo file: %s\n", name);
return;
}
Com_Printf("Not found: %s\n", name);
while(demo_protocols[i])
{
#ifdef PROTOCOL_SUPPORT_OLD
if(demo_protocols[i] == com_oldprotocol->integer)
continue;
#endif
if(demo_protocols[i] == com_protocol->integer)
continue;
Com_sprintf (name, MAX_OSPATH, "demos/%s.%s%d", arg, DEMOEXT, demo_protocols[i]);
FS_FOpenFileRead( name, demofile, qtrue );
if (*demofile)
{
Com_Printf("Demo file: %s\n", name);
return demo_protocols[i];
break;
}
else
Com_Printf("Not found: %s\n", name);
i++;
}
return -1;
}
/*
@ -1012,11 +978,7 @@ void CL_PlayDemo_f( void ) {
break;
}
if(demo_protocols[i] || protocol == com_protocol->integer
#ifdef PROTOCOL_SUPPORT_OLD
|| protocol == com_oldprotocol->integer
#endif
)
if(demo_protocols[i] || protocol == com_protocol->integer)
{
Com_sprintf(name, sizeof(name), "demos/%s", arg);
FS_FOpenFileRead(name, &clc.demofile, qtrue);
@ -1033,11 +995,11 @@ void CL_PlayDemo_f( void ) {
Q_strncpyz(retry, arg, len + 1);
retry[len] = '\0';
protocol = CL_WalkDemoExt(retry, name, &clc.demofile);
CL_WalkDemoExt(retry, name, &clc.demofile);
}
}
else
protocol = CL_WalkDemoExt(arg, name, &clc.demofile);
CL_WalkDemoExt(arg, name, &clc.demofile);
if (!clc.demofile) {
Com_Error( ERR_DROP, "couldn't open %s", name);
@ -1051,13 +1013,6 @@ void CL_PlayDemo_f( void ) {
clc.demoplaying = qtrue;
Q_strncpyz( cls.servername, Cmd_Argv(1), sizeof( cls.servername ) );
#ifdef PROTOCOL_SUPPORT_OLD
if(protocol <= com_oldprotocol->integer)
clc.compat = qtrue;
else
clc.compat = qfalse;
#endif
// read demo messages until connected
while ( cls.state >= CA_CONNECTED && cls.state < CA_PRIMED ) {
CL_ReadDemoMessage();
@ -2198,16 +2153,7 @@ void CL_CheckForResend( void ) {
port = Cvar_VariableValue ("net_qport");
Q_strncpyz( info, Cvar_InfoString( CVAR_USERINFO ), sizeof( info ) );
#ifdef PROTOCOL_SUPPORT_OLD
if(com_oldprotocol->integer == com_protocol->integer)
clc.compat = qtrue;
if(clc.compat)
Info_SetValueForKey(info, "protocol", va("%i", com_oldprotocol->integer));
else
#endif
Info_SetValueForKey(info, "protocol", va("%i", com_protocol->integer));
Info_SetValueForKey( info, "protocol", va("%i", com_protocol->integer ) );
Info_SetValueForKey( info, "qport", va("%i", port ) );
Info_SetValueForKey( info, "challenge", va("%i", clc.challenge ) );
@ -2448,7 +2394,6 @@ Responses to broadcasts, etc
void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
char *s;
char *c;
int challenge;
MSG_BeginReadingOOB( msg );
MSG_ReadLong( msg ); // skip the -1
@ -2470,33 +2415,18 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
return;
}
c = Cmd_Argv(2);
if(*c)
challenge = atoi(c);
#ifdef PROTOCOL_SUPPORT_OLD
if(!clc.compat)
if(!NET_CompareAdr(from, clc.serverAddress))
{
if(!*c || challenge != clc.challenge)
{
Com_Printf("Bad challenge for challengeResponse. Ignored.\n");
return;
}
}
else
#endif
{
if(!NET_CompareAdr(from, clc.serverAddress))
{
// This challenge response is not coming from the expected address.
// Check whether we have a matching client challenge to prevent
// connection hi-jacking.
// This challenge response is not coming from the expected address.
// Check whether we have a matching client challenge to prevent
// connection hi-jacking.
if(!*c || challenge != clc.challenge)
{
Com_DPrintf("Challenge response received from unexpected source. Ignored.\n");
return;
}
c = Cmd_Argv(2);
if(!*c || atoi(c) != clc.challenge)
{
Com_DPrintf("Challenge response received from unexpected source. Ignored.\n");
return;
}
}
@ -2527,34 +2457,7 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
Com_Printf( "connectResponse from wrong address. Ignored.\n" );
return;
}
#ifdef PROTOCOL_SUPPORT_OLD
if(!clc.compat)
{
c = Cmd_Argv(1);
if(*c)
challenge = atoi(c);
else
{
Com_Printf("Bad connectResponse received. Ignored.\n");
return;
}
if(challenge != clc.challenge)
{
Com_Printf("ConnectResponse with bad challenge received. Ignored.\n");
return;
}
}
Netchan_Setup(NS_CLIENT, &clc.netchan, from, Cvar_VariableValue("net_qport"),
clc.challenge, clc.compat);
#else
Netchan_Setup(NS_CLIENT, &clc.netchan, from, Cvar_VariableValue("net_qport"),
clc.challenge);
#endif
Netchan_Setup (NS_CLIENT, &clc.netchan, from, Cvar_VariableValue( "net_qport" ) );
cls.state = CA_CONNECTED;
clc.lastPacketSentTime = -9999; // send first packet immediately
return;
@ -2572,6 +2475,13 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
return;
}
// a disconnect message from the server, which will happen if the server
// dropped the connection but it is still getting packets from us
if (!Q_stricmp(c, "disconnect")) {
CL_DisconnectPacket( from );
return;
}
// echo request from server
if ( !Q_stricmp(c, "echo") ) {
NET_OutOfBandPrint( NS_CLIENT, from, "%s", Cmd_Argv(1) );
@ -2591,33 +2501,10 @@ void CL_ConnectionlessPacket( netadr_t from, msg_t *msg ) {
}
// echo request from server
if(!Q_stricmp(c, "print")){
if ( !Q_stricmp(c, "print") ) {
s = MSG_ReadString( msg );
#ifdef PROTOCOL_SUPPORT_OLD
// Hack to detect legacy server protocol
if(cls.state == CA_CHALLENGING && com_oldprotocol->integer > 0)
{
char buf[128];
int len;
len = Com_sprintf(buf, sizeof(buf), "Server uses protocol version %d",
com_oldprotocol->integer);
if(len < sizeof(buf) && !Q_strncmp(s, buf, len) && !isdigit(s[len]))
{
// This is an old, but compatible protocol version.
// Go back to connecting state.
clc.compat = qtrue;
cls.state = CA_CONNECTING;
return;
}
}
#endif
Q_strncpyz( clc.serverMessage, s, sizeof( clc.serverMessage ) );
Com_Printf( "%s", s );
return;
}
@ -3558,13 +3445,7 @@ void CL_ServerInfoPacket( netadr_t from, msg_t *msg ) {
// if this isn't the correct protocol version, ignore it
prot = atoi( Info_ValueForKey( infoString, "protocol" ) );
if(prot != com_protocol->integer
#ifdef PROTOCOL_SUPPORT_OLD
&& prot != com_oldprotocol->integer
#endif
)
{
if ( prot != com_protocol->integer ) {
Com_DPrintf( "Different protocol info packet: %s\n", infoString );
return;
}

View file

@ -147,6 +147,9 @@ void CL_Netchan_Transmit( netchan_t *chan, msg_t* msg ) {
Netchan_Transmit( chan, msg->cursize, msg->data );
}
extern int oldsize;
int newsize = 0;
/*
=================
CL_Netchan_Process
@ -158,8 +161,7 @@ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) {
ret = Netchan_Process( chan, msg );
if (!ret)
return qfalse;
CL_Netchan_Decode( msg );
newsize += msg->cursize;
return qtrue;
}

View file

@ -260,10 +260,6 @@ typedef struct {
float voipPower;
#endif
#ifdef PROTOCOL_SUPPORT_OLD
qboolean compat;
#endif
// big stuff at end of structure so most offsets are 15 bits or less
netchan_t netchan;
} clientConnection_t;

View file

@ -32,7 +32,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#endif
int demo_protocols[] =
{ 67, 66, 0 };
{ 66, 67, 68, 0 };
#define MAX_NUM_ARGVS 50
@ -86,9 +86,6 @@ cvar_t *com_maxfpsMinimized;
cvar_t *com_abnormalExit;
cvar_t *com_standalone;
cvar_t *com_protocol;
#ifdef PROTOCOL_SUPPORT_OLD
cvar_t *com_oldprotocol;
#endif
cvar_t *com_basegame;
cvar_t *com_homepath;
cvar_t *com_busyWait;
@ -2713,9 +2710,6 @@ void Com_Init( char *commandLine ) {
s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ );
com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO );
com_protocol = Cvar_Get ("protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_INIT);
#ifdef PROTOCOL_SUPPORT_OLD
com_oldprotocol = Cvar_Get ("oldprotocol", va("%i", PROTOCOL_OLD_VERSION), CVAR_INIT);
#endif
Sys_Init();

View file

@ -1030,11 +1030,6 @@ qboolean FS_IsDemoExt(const char *filename, int namelen)
if(protocol == com_protocol->integer)
return qtrue;
#ifdef PROTOCOL_SUPPORT_OLD
if(protocol == PROTOCOL_OLD_VERSION)
return qtrue;
#endif
for(index = 0; demo_protocols[index]; index++)
{
if(demo_protocols[index] == protocol)

View file

@ -83,12 +83,7 @@ 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, int challenge
#ifdef PROTOCOL_SUPPORT_OLD
, qboolean compat
#endif
)
{
void Netchan_Setup( netsrc_t sock, netchan_t *chan, netadr_t adr, int qport ) {
Com_Memset (chan, 0, sizeof(*chan));
chan->sock = sock;
@ -96,10 +91,6 @@ void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int
chan->qport = qport;
chan->incomingSequence = 0;
chan->outgoingSequence = 1;
#ifdef PROTOCOL_SUPPORT_OLD
chan->compat = compat;
chan->challenge = challenge;
#endif
}
// TTimo: unused, commenting out to make gcc happy
@ -199,24 +190,17 @@ void Netchan_TransmitNextFragment( netchan_t *chan ) {
msg_t send;
byte send_buf[MAX_PACKETLEN];
int fragmentLength;
int outgoingSequence;
// write the packet header
MSG_InitOOB (&send, send_buf, sizeof(send_buf)); // <-- only do the oob here
outgoingSequence = chan->outgoingSequence | FRAGMENT_BIT;
MSG_WriteLong(&send, outgoingSequence);
MSG_WriteLong( &send, chan->outgoingSequence | FRAGMENT_BIT );
// send the qport if we are a client
if ( chan->sock == NS_CLIENT ) {
MSG_WriteShort( &send, qport->integer );
}
#ifdef PROTOCOL_SUPPORT_OLD
if(!chan->compat)
#endif
MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence));
// copy the reliable message to the packet first
fragmentLength = FRAGMENT_SIZE;
if ( chan->unsentFragmentStart + fragmentLength > chan->unsentLength ) {
@ -284,17 +268,12 @@ void Netchan_Transmit( netchan_t *chan, int length, const byte *data ) {
MSG_InitOOB (&send, send_buf, sizeof(send_buf));
MSG_WriteLong( &send, chan->outgoingSequence );
chan->outgoingSequence++;
// send the qport if we are a client
if(chan->sock == NS_CLIENT)
MSG_WriteShort(&send, qport->integer);
#ifdef PROTOCOL_SUPPORT_OLD
if(!chan->compat)
#endif
MSG_WriteLong(&send, NETCHAN_GENCHECKSUM(chan->challenge, chan->outgoingSequence));
chan->outgoingSequence++;
if ( chan->sock == NS_CLIENT ) {
MSG_WriteShort( &send, qport->integer );
}
MSG_WriteData( &send, data, length );
@ -348,17 +327,6 @@ qboolean Netchan_Process( netchan_t *chan, msg_t *msg ) {
qport = MSG_ReadShort( msg );
}
#ifdef PROTOCOL_SUPPORT_OLD
if(!chan->compat)
#endif
{
int checksum = MSG_ReadLong(msg);
// UDP spoofing protection
if(NETCHAN_GENCHECKSUM(chan->challenge, sequence) != checksum)
return qfalse;
}
// read the fragment information
if ( fragmented ) {
fragmentStart = MSG_ReadShort( msg );

View file

@ -962,7 +962,7 @@ int Q_CountChar(const char *string, char tocount)
return count;
}
int QDECL Com_sprintf(char *dest, int size, const char *fmt, ...)
void QDECL Com_sprintf(char *dest, int size, const char *fmt, ...)
{
int len;
va_list argptr;
@ -973,8 +973,6 @@ int QDECL Com_sprintf(char *dest, int size, const char *fmt, ...)
if(len >= size)
Com_Printf("Com_sprintf: Output length %d too short, require %d bytes.\n", size, len);
return len;
}
/*

View file

@ -34,7 +34,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define GAMENAME_FOR_MASTER "iofoo3" // must NOT contain whitespaces
#define HEARTBEAT_FOR_MASTER GAMENAME_FOR_MASTER
#define FLATLINE_FOR_MASTER GAMENAME_FOR_MASTER "dead"
// #define PROTOCOL_SUPPORT_OLD // You probably don't need this for your standalone game
#else
#define PRODUCT_NAME "ioq3"
#define BASEGAME "baseq3"
@ -43,7 +42,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#define GAMENAME_FOR_MASTER "Quake3Arena"
#define HEARTBEAT_FOR_MASTER "QuakeArena-1"
#define FLATLINE_FOR_MASTER HEARTBEAT_FOR_MASTER
#define PROTOCOL_SUPPORT_OLD
#endif
#define BASETA "missionpack"
@ -684,7 +682,7 @@ void Parse2DMatrix (char **buf_p, int y, int x, float *m);
void Parse3DMatrix (char **buf_p, int z, int y, int x, float *m);
int Com_HexStrToInt( const char *str );
int QDECL Com_sprintf (char *dest, int size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
void QDECL Com_sprintf (char *dest, int size, const char *fmt, ...) __attribute__ ((format (printf, 3, 4)));
char *Com_SkipTokens( char *s, int numTokens, char *sep );
char *Com_SkipCharset( char *s, char *sep );

View file

@ -194,8 +194,7 @@ void NET_Sleep(int msec);
#define MAX_DOWNLOAD_WINDOW 8 // max of eight download frames
#define MAX_DOWNLOAD_BLKSIZE 2048 // 2048 byte block chunks
#define NETCHAN_GENCHECKSUM(challenge, sequence) ((challenge) ^ ((sequence) * (challenge)))
/*
Netchan handles packet fragmentation and out of order / duplicate suppression
@ -224,20 +223,10 @@ typedef struct {
int unsentFragmentStart;
int unsentLength;
byte unsentBuffer[MAX_MSGLEN];
int challenge;
#ifdef PROTOCOL_SUPPORT_OLD
qboolean compat;
#endif
} netchan_t;
void Netchan_Init( int qport );
void Netchan_Setup(netsrc_t sock, netchan_t *chan, netadr_t adr, int qport, int challenge
#ifdef PROTOCOL_SUPPORT_OLD
, qboolean compat
#endif
);
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 );
@ -253,8 +242,7 @@ PROTOCOL
==============================================================
*/
#define PROTOCOL_VERSION 69
#define PROTOCOL_OLD_VERSION 68
#define PROTOCOL_VERSION 68
// 1.31 - 67
// maintain a list of compatible protocols for demo playing
@ -869,9 +857,6 @@ extern cvar_t *cl_packetdelay;
extern cvar_t *sv_packetdelay;
extern cvar_t *com_protocol;
#ifdef PROTOCOL_SUPPORT_OLD
extern cvar_t *com_oldprotocol;
#endif
// com_speeds times
extern int time_game;

View file

@ -188,11 +188,7 @@ typedef struct client_s {
#endif
int oldServerTime;
qboolean csUpdated[MAX_CONFIGSTRINGS+1];
#ifdef PROTOCOL_SUPPORT_OLD
qboolean compat;
#endif
qboolean csUpdated[MAX_CONFIGSTRINGS+1];
} client_t;
//=============================================================================
@ -201,11 +197,7 @@ typedef struct client_s {
// MAX_CHALLENGES is made large to prevent a denial
// of service attack that could cycle all of them
// out before legitimate users connected
#define MAX_CHALLENGES 2048
// Allow a certain amount of challenges to have the same IP address
// to make it a bit harder to DOS one single IP address from connecting
// while not allowing a single ip to grab all challenge resources
#define MAX_CHALLENGES_MULTI (MAX_CHALLENGES / 2)
#define MAX_CHALLENGES 1024
#define AUTHORIZE_TIMEOUT 5000

View file

@ -55,10 +55,8 @@ void SV_GetChallenge(netadr_t from)
int i;
int oldest;
int oldestTime;
int oldestClientTime;
int clientChallenge;
const char *clientChallenge = Cmd_Argv(1);
challenge_t *challenge;
qboolean wasfound = qfalse;
// ignore if we are in single player
if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) {
@ -66,30 +64,15 @@ void SV_GetChallenge(netadr_t from)
}
oldest = 0;
oldestClientTime = oldestTime = 0x7fffffff;
oldestTime = 0x7fffffff;
// see if we already have a challenge for this ip
challenge = &svs.challenges[0];
clientChallenge = atoi(Cmd_Argv(1));
for(i = 0 ; i < MAX_CHALLENGES ; i++, challenge++)
{
if(!challenge->connected && NET_CompareAdr(from, challenge->adr))
{
wasfound = qtrue;
if(challenge->time < oldestClientTime)
oldestClientTime = challenge->time;
}
if(wasfound && i >= MAX_CHALLENGES_MULTI)
{
i = MAX_CHALLENGES;
for (i = 0 ; i < MAX_CHALLENGES ; i++, challenge++) {
if (!challenge->connected && NET_CompareAdr( from, challenge->adr ) ) {
break;
}
if(challenge->time < oldestTime)
{
if ( challenge->time < oldestTime ) {
oldestTime = challenge->time;
oldest = i;
}
@ -99,16 +82,17 @@ void SV_GetChallenge(netadr_t from)
{
// this is the first time this client has asked for a challenge
challenge = &svs.challenges[oldest];
challenge->clientChallenge = clientChallenge;
challenge->clientChallenge = 0;
challenge->adr = from;
challenge->firstTime = svs.time;
challenge->time = svs.time;
challenge->connected = qfalse;
}
// always generate a new challenge number, so the client cannot circumvent sv_maxping
challenge->challenge = ( (rand() << 16) ^ rand() ) ^ svs.time;
challenge->wasrefused = qfalse;
challenge->time = svs.time;
#ifndef STANDALONE
// Drop the authorize stuff if this client is coming in via v6 as the auth server does not support ipv6.
@ -137,7 +121,7 @@ void SV_GetChallenge(netadr_t from)
// if they have been challenging for a long time and we
// haven't heard anything from the authorize server, go ahead and
// let them in, assuming the id server is down
else if(svs.time - oldestClientTime > AUTHORIZE_TIMEOUT)
else if(svs.time - challenge->firstTime > AUTHORIZE_TIMEOUT)
Com_DPrintf( "authorize server timed out\n" );
else
{
@ -145,6 +129,10 @@ void SV_GetChallenge(netadr_t from)
cvar_t *fs;
char game[1024];
// If the client provided us with a client challenge, store it...
if(*clientChallenge)
challenge->clientChallenge = atoi(clientChallenge);
Com_DPrintf( "sending getIpAuthorize for %s\n", NET_AdrToString( from ));
strcpy(game, BASEGAME);
@ -165,7 +153,7 @@ void SV_GetChallenge(netadr_t from)
#endif
challenge->pingTime = svs.time;
NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %d", challenge->challenge, clientChallenge);
NET_OutOfBandPrint( NS_SERVER, challenge->adr, "challengeResponse %i %s", challenge->challenge, clientChallenge);
}
#ifndef STANDALONE
@ -301,9 +289,6 @@ void SV_DirectConnect( netadr_t from ) {
intptr_t denied;
int count;
char *ip;
#ifdef PROTOCOL_SUPPORT_OLD
qboolean compat = qfalse;
#endif
Com_DPrintf ("SVC_DirectConnect ()\n");
@ -316,21 +301,11 @@ void SV_DirectConnect( netadr_t from ) {
Q_strncpyz( userinfo, Cmd_Argv(1), sizeof(userinfo) );
version = atoi(Info_ValueForKey(userinfo, "protocol"));
#ifdef PROTOCOL_SUPPORT_OLD
if(version > 0 && com_oldprotocol->integer == version)
compat = qtrue;
else
#endif
{
if(version != com_protocol->integer)
{
NET_OutOfBandPrint(NS_SERVER, from, "print\nServer uses protocol version %i "
"(yours is %i).\n", com_protocol->integer, version);
Com_DPrintf(" rejected connect from version %i\n", version);
return;
}
version = atoi( Info_ValueForKey( userinfo, "protocol" ) );
if ( version != com_protocol->integer ) {
NET_OutOfBandPrint( NS_SERVER, from, "print\nServer uses protocol version %i (yours is %i).\n", com_protocol->integer, version );
Com_DPrintf (" rejected connect from version %i\n", version);
return;
}
challenge = atoi( Info_ValueForKey( userinfo, "challenge" ) );
@ -512,12 +487,7 @@ gotnewcl:
newcl->challenge = challenge;
// save the address
#ifdef PROTOCOL_SUPPORT_OLD
newcl->compat = compat;
Netchan_Setup(NS_SERVER, &newcl->netchan, from, qport, challenge, compat);
#else
Netchan_Setup(NS_SERVER, &newcl->netchan, from, qport, challenge);
#endif
Netchan_Setup (NS_SERVER, &newcl->netchan , from, qport);
// init the netchan queue
newcl->netchan_end_queue = &newcl->netchan_start_queue;
@ -538,7 +508,7 @@ gotnewcl:
SV_UserinfoChanged( newcl );
// send the connect packet to the client
NET_OutOfBandPrint(NS_SERVER, from, "connectResponse %d", challenge);
NET_OutOfBandPrint( NS_SERVER, from, "connectResponse" );
Com_DPrintf( "Going from CS_FREE to CS_CONNECTED for %s\n", newcl->name );