Index: README =================================================================== --- README (revision 2095) +++ README (working copy) @@ -189,6 +189,9 @@ legacy Quake3 1.32c protocol, see "Network protocols" section below (startup only) + com_useDpmasterProtocol - Enable to use the dpmaster protocol + instead of legacy Quake3 master protocol + (startup only) com_maxfpsUnfocused - Maximum frames per second when unfocused com_maxfpsMinimized - Maximum frames per second when minimized com_busyWait - Will use a busy loop to wait for rendering @@ -527,25 +530,36 @@ +set com_homepath - to the command line. You can also control which kind of messages to send to + to the command line. You can also control the gamename: + + +set com_gamename + + The message can be specific to your game. It is used to prevent + clients for other games from connecting and identifying the game to dpmaster, + if the dpmaster protocol is used (see below). must not contain + spaces. ioquake3 uses the gamename "Quake3Arena", which is expect by dpmaster + for identifying as quake3. + + You can also control which kind of messages to send to the master server: + +set com_useDpmasterProtocol +set sv_heartbeat +set sv_flatline - +set cl_gamename + If the value is 1, the dpmaster protocol is used. + Using the dpmaster protocol the game can be separate from quake3 on the master + server using com_gamename. The and 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 com_gamename FooBar + +set com_useDpmasterProtocol 1 +set sv_heartbeat fooalive +set sv_flatline foodead - +set cl_gamename foo If you really changed parts that would make vanilla ioquake3 incompatible with Index: code/server/sv_client.c =================================================================== --- code/server/sv_client.c (revision 2095) +++ code/server/sv_client.c (working copy) @@ -59,23 +59,26 @@ int clientChallenge; challenge_t *challenge; qboolean wasfound = qfalse; - char *gameName; + char *gamename; // ignore if we are in single player if ( Cvar_VariableValue( "g_gametype" ) == GT_SINGLE_PLAYER || Cvar_VariableValue("ui_singlePlayerActive")) { return; } - gameName = Cmd_Argv(2); - if(gameName && *gameName) + gamename = Cmd_Argv(2); + + // reject client if the gamename string sent by the client doesn't match ours +#ifdef LEGACY_PROTOCOL + if ((com_legacyprotocol->integer && gamename && *gamename && strcmp(gamename, com_gamename->string)) + || (!com_legacyprotocol->integer && (!gamename || !*gamename || strcmp(gamename, com_gamename->string)))) +#else + if(!gamename || !*gamename || strcmp(gamename, com_gamename->string)) +#endif { - // reject client if the heartbeat string sent by the client doesn't match ours - if(strcmp(gameName, sv_heartbeat->string)) - { - NET_OutOfBandPrint(NS_SERVER, from, "print\nGame mismatch: This is a %s server\n", - sv_heartbeat->string); - return; - } + NET_OutOfBandPrint(NS_SERVER, from, "print\nGame mismatch: This is a %s server%s\n", + com_gamename->string, gamename[0] ? va(" (not %s)", gamename) : ""); + return; } oldest = 0; Index: code/server/sv_init.c =================================================================== --- code/server/sv_init.c (revision 2095) +++ code/server/sv_init.c (working copy) @@ -686,9 +686,20 @@ sv_strictAuth = Cvar_Get ("sv_strictAuth", "1", CVAR_ARCHIVE ); #endif sv_banFile = Cvar_Get("sv_banFile", "serverbans.dat", CVAR_ARCHIVE); - sv_heartbeat = Cvar_Get("sv_heartbeat", HEARTBEAT_FOR_MASTER, CVAR_INIT); - sv_flatline = Cvar_Get("sv_flatline", FLATLINE_FOR_MASTER, CVAR_INIT); +#ifdef LEGACY_MASTER_PROTOCOL + if (com_useDpmasterProtocol->integer) + { + sv_heartbeat = Cvar_Get("sv_heartbeat", "DarkPlaces", CVAR_INIT); + sv_flatline = Cvar_Get("sv_flatline", "DarkPlaces", CVAR_INIT); + } + else +#endif + { + sv_heartbeat = Cvar_Get("sv_heartbeat", HEARTBEAT_FOR_MASTER, CVAR_INIT); + sv_flatline = Cvar_Get("sv_flatline", FLATLINE_FOR_MASTER, CVAR_INIT); + } + // initialize bot cvars so they are listed and can be set before loading the botlib SV_BotInitCvars(); Index: code/server/sv_main.c =================================================================== --- code/server/sv_main.c (revision 2095) +++ code/server/sv_main.c (working copy) @@ -644,6 +644,11 @@ // to prevent timed spoofed reply packets that add ghost servers Info_SetValueForKey( infostring, "challenge", Cmd_Argv(1) ); +#ifdef LEGACY_MASTER_PROTOCOL + if (com_useDpmasterProtocol->integer) +#endif + Info_SetValueForKey( infostring, "gamename", com_gamename->string ); + #ifdef LEGACY_PROTOCOL if(com_legacyprotocol->integer > 0) Info_SetValueForKey(infostring, "protocol", va("%i", com_legacyprotocol->integer)); Index: code/qcommon/q_shared.h =================================================================== --- code/qcommon/q_shared.h (revision 2095) +++ code/qcommon/q_shared.h (working copy) @@ -32,26 +32,34 @@ #define CLIENT_WINDOW_TITLE "changeme" #define CLIENT_WINDOW_MIN_TITLE "changeme2" #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 HOMEPATH_NAME_UNIX ".foo" #define HOMEPATH_NAME_WIN "FooBar" #define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN // #define LEGACY_PROTOCOL // You probably don't need this for your standalone game +// #define LEGACY_MASTER_PROTOCOL // You probably don't need this either #else #define PRODUCT_NAME "ioq3" #define BASEGAME "baseq3" #define CLIENT_WINDOW_TITLE "ioquake3" #define CLIENT_WINDOW_MIN_TITLE "ioq3" #define GAMENAME_FOR_MASTER "Quake3Arena" - #define HEARTBEAT_FOR_MASTER "QuakeArena-1" - #define FLATLINE_FOR_MASTER HEARTBEAT_FOR_MASTER #define HOMEPATH_NAME_UNIX ".q3a" #define HOMEPATH_NAME_WIN "Quake3" #define HOMEPATH_NAME_MACOSX HOMEPATH_NAME_WIN #define LEGACY_PROTOCOL + #define LEGACY_MASTER_PROTOCOL #endif +#ifdef LEGACY_MASTER_PROTOCOL + // Heartbeat for legacy Q3A master server + #define HEARTBEAT_FOR_MASTER "QuakeArena-1" + #define FLATLINE_FOR_MASTER HEARTBEAT_FOR_MASTER +#else + // Heartbeat for dpmaster protocol + #define HEARTBEAT_FOR_MASTER "DarkPlaces" + #define FLATLINE_FOR_MASTER HEARTBEAT_FOR_MASTER +#endif + #define BASETA "missionpack" #ifdef _MSC_VER Index: code/qcommon/qcommon.h =================================================================== --- code/qcommon/qcommon.h (revision 2095) +++ code/qcommon/qcommon.h (working copy) @@ -868,10 +868,14 @@ extern cvar_t *cl_packetdelay; extern cvar_t *sv_packetdelay; +extern cvar_t *com_gamename; extern cvar_t *com_protocol; #ifdef LEGACY_PROTOCOL extern cvar_t *com_legacyprotocol; #endif +#ifdef LEGACY_MASTER_PROTOCOL +extern cvar_t *com_useDpmasterProtocol; +#endif // com_speeds times extern int time_game; Index: code/qcommon/common.c =================================================================== --- code/qcommon/common.c (revision 2095) +++ code/qcommon/common.c (working copy) @@ -85,10 +85,14 @@ cvar_t *com_maxfpsMinimized; cvar_t *com_abnormalExit; cvar_t *com_standalone; +cvar_t *com_gamename; cvar_t *com_protocol; #ifdef LEGACY_PROTOCOL cvar_t *com_legacyprotocol; #endif +#ifdef LEGACY_MASTER_PROTOCOL +cvar_t *com_useDpmasterProtocol; +#endif cvar_t *com_basegame; cvar_t *com_homepath; cvar_t *com_busyWait; @@ -2787,6 +2791,7 @@ s = va("%s %s %s", Q3_VERSION, PLATFORM_STRING, __DATE__ ); com_version = Cvar_Get ("version", s, CVAR_ROM | CVAR_SERVERINFO ); + com_gamename = Cvar_Get("com_gamename", GAMENAME_FOR_MASTER, CVAR_INIT); com_protocol = Cvar_Get("com_protocol", va("%i", PROTOCOL_VERSION), CVAR_SERVERINFO | CVAR_INIT); #ifdef LEGACY_PROTOCOL com_legacyprotocol = Cvar_Get("com_legacyprotocol", va("%i", PROTOCOL_LEGACY_VERSION), CVAR_INIT); @@ -2798,6 +2803,10 @@ #endif Cvar_Get("protocol", com_protocol->string, CVAR_ROM); +#ifdef LEGACY_MASTER_PROTOCOL + com_useDpmasterProtocol = Cvar_Get("com_useDpmasterProtocol", "0", CVAR_INIT); +#endif + Sys_Init(); if( Sys_WritePIDFile( ) ) { Index: code/client/cl_main.c =================================================================== --- code/client/cl_main.c (revision 2095) +++ code/client/cl_main.c (working copy) @@ -109,8 +109,6 @@ cvar_t *cl_consoleKeys; -cvar_t *cl_gamename; - clientActive_t cl; clientConnection_t clc; clientStatic_t cls; @@ -2225,9 +2223,9 @@ #endif // The challenge request shall be followed by a client challenge so no malicious server can hijack this connection. - // Add the heartbeat gamename so the server knows we're running the correct game and can reject the client + // Add the gamename so the server knows we're running the correct game and can reject the client // with a meaningful message - Com_sprintf(data, sizeof(data), "getchallenge %d %s", clc.challenge, Cvar_VariableString("sv_heartbeat")); + Com_sprintf(data, sizeof(data), "getchallenge %d %s", clc.challenge, com_gamename->string); NET_OutOfBandPrint(NS_CLIENT, clc.serverAddress, "%s", data); break; @@ -3391,8 +3389,6 @@ // ~ and `, as keys and characters cl_consoleKeys = Cvar_Get( "cl_consoleKeys", "~ ` 0x7e 0x60", CVAR_ARCHIVE); - cl_gamename = Cvar_Get("cl_gamename", GAMENAME_FOR_MASTER, CVAR_TEMP); - // userinfo Cvar_Get ("name", "UnnamedPlayer", CVAR_USERINFO | CVAR_ARCHIVE ); Cvar_Get ("rate", "25000", CVAR_USERINFO | CVAR_ARCHIVE ); @@ -3615,9 +3611,29 @@ char info[MAX_INFO_STRING]; char *infoString; int prot; + char *gamename; infoString = MSG_ReadString( msg ); +#ifdef LEGACY_MASTER_PROTOCOL + if (com_useDpmasterProtocol->integer) +#endif + { + // if this isn't the correct gamename, ignore it + gamename = Info_ValueForKey( infoString, "gamename" ); + +#ifdef LEGACY_PROTOCOL + if ((com_legacyprotocol->integer && *gamename && strcmp(gamename, com_gamename->string)) + || (!com_legacyprotocol->integer && (!*gamename || strcmp(gamename, com_gamename->string)))) +#else + if (!*gamename || strcmp(gamename, com_gamename->string)) +#endif + { + Com_DPrintf( "Game mismatch in info packet: %s\n", infoString ); + return; + } + } + // if this isn't the correct protocol version, ignore it prot = atoi( Info_ValueForKey( infoString, "protocol" ) ); @@ -3995,20 +4011,34 @@ if (to.type == NA_IP6 || to.type == NA_MULTICAST6) { int v4enabled = Cvar_VariableIntegerValue("net_enabled") & NET_ENABLEV4; +#ifdef LEGACY_MASTER_PROTOCOL + const char *gamename = (com_useDpmasterProtocol->integer) ? com_gamename->string : GAMENAME_FOR_MASTER; +#else + const char *gamename = com_gamename->string; +#endif if(v4enabled) { Com_sprintf(command, sizeof(command), "getserversExt %s %s", - cl_gamename->string, Cmd_Argv(2)); + gamename, Cmd_Argv(2)); } else { Com_sprintf(command, sizeof(command), "getserversExt %s %s ipv6", - cl_gamename->string, Cmd_Argv(2)); + gamename, Cmd_Argv(2)); } } +#ifdef LEGACY_MASTER_PROTOCOL + else if (com_useDpmasterProtocol->integer) + Com_sprintf(command, sizeof(command), "getservers %s %s", + com_gamename->string, Cmd_Argv(2)); else Com_sprintf(command, sizeof(command), "getservers %s", Cmd_Argv(2)); +#else + else + Com_sprintf(command, sizeof(command), "getservers %s %s", + com_gamename->string, Cmd_Argv(2)); +#endif for (i=3; i < count; i++) {