From 27e8e812a282b746f41ee8c947c282cffa95c64e Mon Sep 17 00:00:00 2001 From: Spoike Date: Wed, 15 Nov 2017 12:38:20 +0000 Subject: [PATCH] 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 --- engine/client/net_master.c | 24 +++++++++++++++++++--- engine/client/pr_csqc.c | 2 +- engine/client/pr_menu.c | 2 +- engine/client/renderer.c | 6 +++--- engine/common/fs.c | 10 ++++++--- engine/common/gl_q2bsp.c | 2 +- engine/common/net.h | 1 + engine/common/net_wins.c | 34 ++++++++++++++++++++++++++++++- engine/common/netinc.h | 9 ++++++++ engine/qclib/qccmain.c | 13 ++++++------ engine/server/pr_cmds.c | 2 +- engine/server/sv_main.c | 20 ++++++++++++------ engine/shaders/glsl/lpp_wall.glsl | 1 + plugins/mpq/fs_mpq.vcproj | 2 +- 14 files changed, 101 insertions(+), 27 deletions(-) diff --git a/engine/client/net_master.c b/engine/client/net_master.c index 448f039f..e95355da 100644 --- a/engine/client/net_master.c +++ b/engine/client/net_master.c @@ -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) diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 4a6eb6d3..5a716bb9 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -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"); diff --git a/engine/client/pr_menu.c b/engine/client/pr_menu.c index f28fddf2..cdf07eb3 100644 --- a/engine/client/pr_menu.c +++ b/engine/client/pr_menu.c @@ -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")) diff --git a/engine/client/renderer.c b/engine/client/renderer.c index 61c0b1fe..b52eefb0 100644 --- a/engine/client/renderer.c +++ b/engine/client/renderer.c @@ -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."); diff --git a/engine/common/fs.c b/engine/common/fs.c index 669bd533..b45643d3 100644 --- a/engine/common/fs.c +++ b/engine/common/fs.c @@ -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*/ diff --git a/engine/common/gl_q2bsp.c b/engine/common/gl_q2bsp.c index 53b9b9b0..ec86f0a9 100644 --- a/engine/common/gl_q2bsp.c +++ b/engine/common/gl_q2bsp.c @@ -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 diff --git a/engine/common/net.h b/engine/common/net.h index 77c5507d..437bbdd5 100644 --- a/engine/common/net.h +++ b/engine/common/net.h @@ -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); diff --git a/engine/common/net_wins.c b/engine/common/net_wins.c index 261b7b86..da78ad01 100644 --- a/engine/common/net_wins.c +++ b/engine/common/net_wins.c @@ -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); diff --git a/engine/common/netinc.h b/engine/common/netinc.h index 0cce0ea0..668ac423 100644 --- a/engine/common/netinc.h +++ b/engine/common/netinc.h @@ -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); diff --git a/engine/qclib/qccmain.c b/engine/qclib/qccmain.c index c4591183..d5f6d433 100644 --- a/engine/qclib/qccmain.c +++ b/engine/qclib/qccmain.c @@ -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 ; inextlocal) - 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; } diff --git a/engine/server/pr_cmds.c b/engine/server/pr_cmds.c index 2c619add..7b9b1c63 100644 --- a/engine/server/pr_cmds.c +++ b/engine/server/pr_cmds.c @@ -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)."}, diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 5236efaf..2801948a 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -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= 0) diff --git a/engine/shaders/glsl/lpp_wall.glsl b/engine/shaders/glsl/lpp_wall.glsl index 705fa5a3..24fa046e 100644 --- a/engine/shaders/glsl/lpp_wall.glsl +++ b/engine/shaders/glsl/lpp_wall.glsl @@ -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 diff --git a/plugins/mpq/fs_mpq.vcproj b/plugins/mpq/fs_mpq.vcproj index afbe4a33..ad29533e 100644 --- a/plugins/mpq/fs_mpq.vcproj +++ b/plugins/mpq/fs_mpq.vcproj @@ -45,7 +45,7 @@ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;FTEPLUGIN" MinimalRebuild="true" BasicRuntimeChecks="3" - RuntimeLibrary="2" + RuntimeLibrary="0" UsePrecompiledHeader="0" WarningLevel="3" DebugInformationFormat="4"