fixed crashy race condition when querying master servers.

try to do something about crazy cursor biases in games that are not likely to get the QSG cursor.
fix unvised q3bsp pvs. again.
add cl_delay_packets cvar as a clientside analogue to sv_minping (which is often unchangeable by the actual players).
fix a qcc issue with static locals screwing everything up.
fix dpmaster issues when NQPROT isn't defined.

git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@5168 fc73d0e0-1445-4013-8a0c-d673dee63da5
This commit is contained in:
Spoike 2017-11-15 12:38:20 +00:00
parent 69fe8342cf
commit 27e8e812a2
14 changed files with 101 additions and 27 deletions

View File

@ -158,6 +158,21 @@ net_masterlist_t net_masterlist[] = {
{MP_UNSPECIFIED, CVAR(NULL, NULL)}
};
qboolean Net_AddressIsMaster(netadr_t *adr)
{
size_t i, j;
//never throttle packets from master servers. we don't want to go missing.
for (i = 0; net_masterlist[i].cv.name; i++)
{
if (!net_masterlist[i].protocol || net_masterlist[i].resolving || net_masterlist[i].needsresolve)
continue;
for (j = 0; j < MAX_MASTER_ADDRESSES; j++)
if (net_masterlist[i].adr[j].type != NA_INVALID)
if (NET_CompareAdr(&net_from, &net_masterlist[i].adr[j]))
return true;
}
return false;
}
void Net_Master_Init(void)
{
int i;
@ -1441,7 +1456,6 @@ void CLMaster_AddMaster_Worker_Resolve(void *ctx, void *data, size_t a, size_t b
work->adr = adrs[0];
else
memset(&work->adr, 0, sizeof(work->adr));
COM_AddWork(WG_MAIN, CLMaster_AddMaster_Worker_Resolved, NULL, work, a, b);
//add dupes too (eg: ipv4+ipv6)
for (i = 1; i < found; i++)
@ -1459,7 +1473,7 @@ void CLMaster_AddMaster_Worker_Resolve(void *ctx, void *data, size_t a, size_t b
if (j == i)
{ //not already added, hurrah
master_t *alt = Z_Malloc(sizeof(master_t)+strlen(work->name)+1+strlen(work->address)+1);
alt->address = work->name + strlen(work->name)+1;
alt->address = alt->name + strlen(work->name)+1;
alt->mastertype = work->mastertype;
alt->protocoltype = work->protocoltype;
strcpy(alt->name, work->name);
@ -1467,9 +1481,13 @@ void CLMaster_AddMaster_Worker_Resolve(void *ctx, void *data, size_t a, size_t b
alt->sends = 1;
alt->nosave = true;
alt->adr = adrs[i];
COM_AddWork(WG_MAIN, CLMaster_AddMaster_Worker_Resolved, NULL, alt, a, b);
COM_AddWork(WG_MAIN, CLMaster_AddMaster_Worker_Resolved, NULL, work, a, b);
work = alt;
}
}
COM_AddWork(WG_MAIN, CLMaster_AddMaster_Worker_Resolved, NULL, work, a, b);
}
void Master_AddMaster (char *address, enum mastertype_e mastertype, enum masterprotocol_e protocol, char *description)

View File

@ -83,7 +83,7 @@ static qboolean csqc_worldchanged; //make sure any caches are rebuilt properly b
static char csqc_printbuffer[8192];
#define CSQCPROGSGROUP "CSQC progs control"
cvar_t pr_csqc_maxedicts = CVAR("pr_csqc_maxedicts", "65536"); //not tied to protocol nor server.
cvar_t pr_csqc_maxedicts = CVAR("pr_csqc_maxedicts", "65536"); //not tied to protocol nor server. can be set arbitrarily high, except for memory allocations.
cvar_t pr_csqc_memsize = CVAR("pr_csqc_memsize", "-1");
cvar_t cl_csqcdebug = CVAR("cl_csqcdebug", "0"); //prints entity numbers which arrive (so I can tell people not to apply it to players...)
cvar_t cl_nocsqc = CVAR("cl_nocsqc", "0");

View File

@ -974,7 +974,7 @@ void QCBUILTIN PF_SubConGetSet (pubprogfuncs_t *prinst, struct globalvars_s *pr_
else if (!strcmp(field, "next"))
{
con = con->next;
if (con)
if (con && con != &con_main)
RETURN_TSTRING(con->name);
}
else if (!strcmp(field, "unseen"))

View File

@ -82,9 +82,9 @@ cvar_t _windowed_mouse = CVARF ("_windowed_mouse","1",
cvar_t con_ocranaleds = CVAR ("con_ocranaleds", "2");
cvar_t cl_cursor = CVAR ("cl_cursor", "");
cvar_t cl_cursorscale = CVAR ("cl_cursor_scale", "0.2");
cvar_t cl_cursorbiasx = CVAR ("cl_cursor_bias_x", "7.5");
cvar_t cl_cursorbiasy = CVAR ("cl_cursor_bias_y", "0.8");
cvar_t cl_cursorscale = CVAR ("cl_cursor_scale", "1.0");
cvar_t cl_cursorbiasx = CVAR ("cl_cursor_bias_x", "0.0");
cvar_t cl_cursorbiasy = CVAR ("cl_cursor_bias_y", "0.0");
cvar_t gl_nocolors = CVARF ("gl_nocolors", "0", CVAR_ARCHIVE);
cvar_t gl_part_flame = CVARFD ("gl_part_flame", "1", CVAR_ARCHIVE, "Enable particle emitting from models. Mainly used for torch and flame effects.");

View File

@ -529,8 +529,10 @@ static qboolean FS_Manifest_ParseTokens(ftemanifest_t *man)
}
else if (!Q_strcasecmp(cmd, "install"))
{
Z_Free(man->installupd);
man->installupd = Z_StrDup(Cmd_Argv(1));
if (man->installupd)
Z_StrCat(&man->defaultoverrides, va(";%s", Cmd_Args()));
else
man->installupd = Z_StrDup(Cmd_Argv(1));
}
else if (!Q_strcasecmp(cmd, "protocolname"))
{
@ -587,6 +589,7 @@ static qboolean FS_Manifest_ParseTokens(ftemanifest_t *man)
}
}
}
//FIXME: these should generate package-manager entries.
#ifndef NOLEGACY
else if (!Q_strcasecmp(cmd, "filedependancies") || !Q_strcasecmp(cmd, "archiveddependancies"))
FS_Manifest_ParsePackage(man, mdt_installation);
@ -3026,7 +3029,8 @@ void COM_Gamedir (const char *dir, const struct gamepacks *packagespaths)
/*quake requires a few settings for compatibility*/
#define EZQUAKECOMPETITIVE "set ruleset_allow_fbmodels 1\n"
#define QCFG "set com_parseutf8 0\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" ZFIXHACK EZQUAKECOMPETITIVE
#define QRPCOMPAT "cl_cursor_scale 0.2\ncl_cursor_bias_x 7.5\ncl_cursor_bias_y 0.8"
#define QCFG "set com_parseutf8 0\nset allow_download_refpackages 0\nset sv_bigcoords \"\"\nmap_autoopenportals 1\n" "sv_port "STRINGIFY(PORT_QWSERVER)" "STRINGIFY(PORT_NQSERVER)"\n" ZFIXHACK EZQUAKECOMPETITIVE QRPCOMPAT
//nehahra has to be weird with extra cvars, and buggy fullbrights.
#define NEHCFG QCFG "set nospr32 0\nset cutscene 1\nalias startmap_sp \"map nehstart\"\nr_fb_bmodels 0\nr_fb_models 0\n"
/*stuff that makes dp-only mods work a bit better*/

View File

@ -3449,7 +3449,7 @@ static qboolean CModQ3_LoadVisibility (model_t *mod, qbyte *mod_base, lump_t *l)
numclusters++;
#else
//but its much faster to merge all leafs into a single pvs cluster. no vis is no vis.
numclusters = 2;
numclusters = 8*sizeof(int);
for (i = 0; i < mod->numleafs; i++)
mod->leafs[i].cluster = !!mod->leafs[i].cluster;
#endif

View File

@ -247,6 +247,7 @@ typedef struct
extern int net_drop; // packets dropped before this one
void Net_Master_Init(void);
qboolean Net_AddressIsMaster(netadr_t *adr);
void Netchan_Init (void);
int Netchan_Transmit (netchan_t *chan, int length, qbyte *data, int rate);

View File

@ -102,6 +102,7 @@ cvar_t net_enable_http = CVARD("net_enable_http", "1", "If enabled, tcp port
cvar_t net_enable_websockets = CVARD("net_enable_websockets", "1", "If enabled, tcp ports will accept websocket game clients.");
cvar_t net_enable_webrtcbroker = CVARD("net_enable_webrtcbroker", "1", "If 1, tcp ports will accept websocket connections from clients trying to broker direct webrtc connections. This should be low traffic, but might involve a lot of mostly-idle connections.");
#endif
cvar_t cl_delay_packets = CVARD("cl_delay_packets", "0", "Extra latency, in milliseconds.");
extern cvar_t sv_public, sv_listen_qw, sv_listen_nq, sv_listen_dp;
#ifdef QWOVERQ3
@ -129,7 +130,7 @@ loopback_t loopbacks[2];
#ifdef HAVE_DTLS
static neterr_t FTENET_DTLS_SendPacket(ftenet_connections_t *col, int length, const void *data, netadr_t *to);
#endif
static neterr_t NET_SendPacketCol (ftenet_connections_t *collection, int length, const void *data, netadr_t *to);
//=============================================================================
@ -6395,6 +6396,7 @@ qboolean NET_UpdateRates(ftenet_connections_t *collection, qboolean inbound, siz
/*firstsock is a cookie*/
int NET_GetPacket (netsrc_t netsrc, int firstsock)
{
struct ftenet_delayed_packet_s *p;
ftenet_connections_t *collection;
unsigned int ctime;
if (netsrc == NS_SERVER)
@ -6419,6 +6421,18 @@ int NET_GetPacket (netsrc_t netsrc, int firstsock)
if (!collection)
return -1;
while ((p = collection->delayed_packets) && (int)(Sys_Milliseconds()-p->sendtime) > 0)
{
collection->delayed_packets = p->next;
#ifdef HAVE_DTLS
if (p->dest.prot == NP_DTLS)
FTENET_DTLS_SendPacket(collection, p->cursize, p->data, &p->dest);
else
#endif
NET_SendPacketCol (collection, p->cursize, p->data, &p->dest);
Z_Free(p);
}
while (firstsock < MAX_CONNECTIONS)
{
if (collection->conn[firstsock])
@ -6555,6 +6569,23 @@ neterr_t NET_SendPacket (netsrc_t netsrc, int length, const void *data, netadr_t
return NETERR_NOROUTE;
#else
collection = cls.sockets;
if (cl_delay_packets.value >= 1)
{
struct ftenet_delayed_packet_s *p, **l;
if (!collection)
return NETERR_NOROUTE; //erk...
p = BZ_Malloc(sizeof(*p) - sizeof(p->data) + length);
p->sendtime = Sys_Milliseconds() + (int)cl_delay_packets.value;
p->next = NULL;
p->cursize = length;
p->dest = *to;
memcpy(p->data, data, length);
for (l = &collection->delayed_packets; *l; l = &((*l)->next))
;
*l = p;
return NETERR_SENT; //fixme: mtu, noroute, etc... panic? only allow if udp dest?
}
#endif
}
#ifdef HAVE_DTLS
@ -7282,6 +7313,7 @@ void NET_Init (void)
Cvar_Register(&net_hybriddualstack, "networking");
Cvar_Register(&net_fakeloss, "networking");
Cvar_Register(&cl_delay_packets, "networking");
#ifndef CLIENTONLY
Cmd_AddCommand("sv_addport", SVNET_AddPort_f);

View File

@ -334,6 +334,15 @@ typedef struct ftenet_connections_s
struct dtlspeer_s *dtls; //linked list. linked lists are shit, but at least it keeps pointers valid when things are resized.
const dtlsfuncs_t *dtlsfuncs;
#endif
struct ftenet_delayed_packet_s
{
unsigned int sendtime; //in terms of Sys_Milliseconds()
struct ftenet_delayed_packet_s *next;
netadr_t dest;
size_t cursize;
qbyte data[1];
} *delayed_packets;
} ftenet_connections_t;
void ICE_Tick(void);

View File

@ -1199,7 +1199,7 @@ void QCC_UnmarshalLocals(void)
}
eog = numpr_globals;
//next, finalize non-static locals.
//next, finalize non-static non-shared locals.
for (i=0 ; i<numfunctions ; i++)
{
if (functions[i].privatelocals)
@ -1229,7 +1229,8 @@ void QCC_UnmarshalLocals(void)
{
numpr_globals = onum;
for (d = functions[i].firstlocal; d; d = d->nextlocal)
QCC_FinaliseDef(d);
if (!d->isstatic && !(d->constant && d->initialized))
QCC_FinaliseDef(d);
if (biggest < numpr_globals)
biggest = numpr_globals;
@ -1598,18 +1599,18 @@ pbool QCC_WriteData (int crc)
funcs[i].parm_size[p++] = size;
a++;
}
for (; local && !local->used; local = local->nextlocal)
for (; local && (!local->used || local->isstatic || (local->constant && local->initialized)); local = local->nextlocal)
;
if (!p && local)
funcs[i].parm_start = local->ofs;
for (; local; local = local->nextlocal)
{
if (!local->used || local->isstatic || (local->constant && local->initialized))
continue;
size = local->type->size;
if (local->arraysize) //arrays are annoying
size = local->arraylengthprefix+size*local->arraysize;
if (local->used)
funcs[i].locals += size;
funcs[i].locals += size;
}
funcs[i].numparms = p;
}

View File

@ -11550,7 +11550,7 @@ void PR_DumpPlatform_f(void)
{"CSQC_Event_Sound", "float(float entnum, float channel, string soundname, float vol, float attenuation, vector pos, float pitchmod, float flags"/*", float timeofs*/")", CS},
// {"CSQC_ServerSound", "//void()", CS},
{"CSQC_LoadResource", "float(string resname, string restype)", CS, "Called each time some resource is being loaded. CSQC can invoke various draw calls to provide a loading screen, until WorldLoaded is called."},
{"CSQC_Parse_TempEntity", "float()", CS, "Please don't use this. Use CSQC_Parse_Event and multicasts instead."},
{"CSQC_Parse_TempEntity", "float()", CS, "Please don't use this. Use CSQC_Parse_Event and multicasts instead.\nThe use of serverside protocol translation to handle QW vs NQ protocols mean that you're likely to end up reading slightly different data. Which is bad.\nReturn true to say that you fully handled the tempentity. Return false to have the client attempt to rewind the network stream and parse the message itself."},
{"GameCommand", "void(string cmdtext)", CS|MENU},
{"Cef_GeneratePage", "string(string uri, string method, string postdata, __in string requestheaders, __inout string responseheaders)", QW|NQ|CS|MENU, "Provides an entrypoint to generate pages for the CEF plugin from within QC. Headers are \n-separated key/value pairs (use tokenizebyseparator)."},

View File

@ -117,7 +117,7 @@ extern cvar_t sv_allow_splitscreen;
cvar_t sv_guidhash = CVARD("sv_guidkey", "", "If set, clients will calculate their GUID values against this string instead of the server's IP address. This allows consistency between multiple servers (for stats tracking), but do NOT treat the client's GUID as something that is secure.");
cvar_t sv_serverip = CVARD("sv_serverip", "", "Set this cvar to the server's public ip address if the server is behind a firewall and cannot detect its own public address. Providing a port is required if the firewall/nat remaps it, but is otherwise optional.");
cvar_t sv_public = CVAR("sv_public", "0");
cvar_t sv_public = CVARD("sv_public", "0", "Controls whether the server will publically advertise itself to master servers or not. Additionally, if set to -1, will block all new connection requests even on lan.");
cvar_t sv_listen_qw = CVARAFD("sv_listen_qw", "1", "sv_listen", 0, "Specifies whether normal clients are allowed to connect.");
cvar_t sv_listen_nq = CVARD("sv_listen_nq", "2", "Allow new (net)quake clients to connect to the server.\n0 = don't let them in.\n1 = allow them in (WARNING: this allows 'qsmurf' DOS attacks).\n2 = accept (net)quake clients by emulating a challenge (as secure as QW/Q2 but does not fully conform to the NQ protocol).");
cvar_t sv_listen_dp = CVARD("sv_listen_dp", "0", "Allows the server to respond with the DP-specific handshake protocol.\nWarning: this can potentially get confused with quake2, and results in race conditions with both vanilla netquake and quakeworld protocols.\nOn the plus side, DP clients can usually be identified correctly, enabling a model+sound limit boost.");
@ -1188,7 +1188,7 @@ static void SVC_Status (void)
SV_EndRedirect ();
}
#ifdef NQPROT
#if 1//def NQPROT
static void SVC_GetInfo (char *challenge, int fullstatus)
{
//dpmaster support
@ -1202,8 +1202,10 @@ static void SVC_GetInfo (char *challenge, int fullstatus)
const char *gamestatus;
eval_t *v;
#ifdef NQPROT
if (!sv_listen_nq.ival && !sv_listen_dp.ival)
return;
#endif
for (i=0 ; i<svs.allocated_client_slots ; i++)
{
@ -1247,7 +1249,9 @@ static void SVC_GetInfo (char *challenge, int fullstatus)
Info_SetValueForKey(resp, "gamename", protocolname, sizeof(response) - (resp-response));
Info_SetValueForKey(resp, "modname", FS_GetGamedir(true), sizeof(response) - (resp-response));
// Info_SetValueForKey(resp, "gamedir", FS_GetGamedir(true), sizeof(response) - (resp-response));
#ifdef NQPROT
Info_SetValueForKey(resp, "protocol", va("%d", NQ_NETCHAN_VERSION), sizeof(response) - (resp-response));
#endif
Info_SetValueForKey(resp, "clients", va("%d", numclients), sizeof(response) - (resp-response));
Info_SetValueForKey(resp, "sv_maxclients", maxclients.string, sizeof(response) - (resp-response));
Info_SetValueForKey(resp, "mapname", Info_ValueForKey(svs.info, "map"), sizeof(response) - (resp-response));
@ -3563,8 +3567,12 @@ qboolean SVC_ThrottleInfo (void)
{
#define THROTTLE_PPS 20
static unsigned int blockuntil;
unsigned int curtime = Sys_Milliseconds();
unsigned int inc = 1000/THROTTLE_PPS;
unsigned int curtime, i, inc = 1000/THROTTLE_PPS;
if (Net_AddressIsMaster(&net_from))
return true; //allow it without contributing to any throttling.
curtime = Sys_Milliseconds();
/*don't go too far back*/
//if (blockuntil < curtime - 1000)
@ -3718,8 +3726,8 @@ qboolean SV_ConnectionlessPacket (void)
//its a subtle difference, but means we can avoid wasteful spam for real qw clients.
SVC_GetChallenge ((net_message.cursize==16)?true:false);
}
#ifdef NQPROT
/*for DP*/
#if 1//def NQPROT
/*for DP origionally, but dpmaster expects it, and we need dpmaster for custom protocol names*/
else if (!strcmp(c, "getstatus"))
{
if (sv_public.ival >= 0)

View File

@ -1,3 +1,4 @@
!!ver 100 150
!!permu BUMP //for offsetmapping rather than bumpmapping (real bumps are handled elsewhere)
!!cvarf r_glsl_offsetmapping_scale
!!samps 2

View File

@ -45,7 +45,7 @@
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;FTEPLUGIN"
MinimalRebuild="true"
BasicRuntimeChecks="3"
RuntimeLibrary="2"
RuntimeLibrary="0"
UsePrecompiledHeader="0"
WarningLevel="3"
DebugInformationFormat="4"