From 6dbfc0ebbe761727e953b7af77789f6e87e253ce Mon Sep 17 00:00:00 2001 From: Spoike Date: Tue, 8 Mar 2022 05:34:26 +0000 Subject: [PATCH] Fix msg_readcount issues. git-svn-id: https://svn.code.sf.net/p/fteqw/code/trunk@6218 fc73d0e0-1445-4013-8a0c-d673dee63da5 --- engine/client/cl_demo.c | 16 +++++++----- engine/client/cl_ents.c | 12 ++++----- engine/client/cl_input.c | 2 +- engine/client/cl_main.c | 16 ++++++------ engine/client/cl_parse.c | 53 +++++++++++++++++--------------------- engine/client/cl_tent.c | 15 +++++------ engine/client/clq2_ents.c | 8 +++--- engine/client/pr_csqc.c | 30 +++++++++++---------- engine/common/common.c | 47 +++++++++++++++++++++------------ engine/common/common.h | 1 - engine/common/net_chan.c | 8 +++--- engine/server/sv_cluster.c | 4 +-- engine/server/sv_main.c | 17 +++++++++--- engine/server/sv_master.c | 4 ++- engine/server/sv_user.c | 29 ++++++++++++--------- 15 files changed, 145 insertions(+), 117 deletions(-) diff --git a/engine/client/cl_demo.c b/engine/client/cl_demo.c index b6c48addf..470026916 100644 --- a/engine/client/cl_demo.c +++ b/engine/client/cl_demo.c @@ -162,18 +162,18 @@ void CL_WriteDemoMessage (sizebuf_t *msg, int payloadoffset) c = dem_read; VFS_WRITE (cls.demooutfile, &c, sizeof(c)); - if (*(int*)msg->data == -1) + if (*(int*)msg->data == -1 && payloadoffset==0) { //connectionless packet. len = LittleLong (msg->cursize); VFS_WRITE (cls.demooutfile, &len, 4); - VFS_WRITE (cls.demooutfile, msg->data + msg_readcount, msg->cursize - msg_readcount); + VFS_WRITE (cls.demooutfile, msg->data + payloadoffset, msg->cursize - payloadoffset); } else { //regenerate a legacy netchan. no fragmentation support, but whatever. this ain't udp. //the length - len = LittleLong (msg->cursize - msg_readcount + 8); + len = LittleLong (msg->cursize - payloadoffset + 8); VFS_WRITE (cls.demooutfile, &len, 4); //hack the netchan here. i = cls.netchan.incoming_sequence; @@ -181,7 +181,7 @@ void CL_WriteDemoMessage (sizebuf_t *msg, int payloadoffset) i = cls.netchan.incoming_acknowledged; VFS_WRITE (cls.demooutfile, &i, 4); //and the data - VFS_WRITE (cls.demooutfile, msg->data + msg_readcount, msg->cursize - msg_readcount); + VFS_WRITE (cls.demooutfile, msg->data + payloadoffset, msg->cursize - payloadoffset); } break; #ifdef Q2CLIENT @@ -1008,11 +1008,10 @@ void CL_Stop_f (void) #endif { SZ_Clear (&net_message); - msg_readcount = 0; MSG_WriteLong (&net_message, -1); // -1 sequence means out of band MSG_WriteByte (&net_message, svc_disconnect); MSG_WriteString (&net_message, "EndOfDemo"); - CL_WriteDemoMessage (&net_message, sizeof(int)); + CL_WriteDemoMessage (&net_message, 0); } // finish up @@ -1750,7 +1749,8 @@ void CL_Record_f (void) if (cls.state != ca_active) { - Con_Printf ("You must be connected to record.\n"); + Con_Printf ("You must either be connected to record, or specify a map name to load.\n"); + Con_Printf ("%s: \n", Cmd_Argv(0)); return; } @@ -2108,6 +2108,8 @@ void CL_Record_f (void) break; } + cl.validsequence = 0; //ask for a sequence reset. + if (cls.fteprotocolextensions2 & PEXT2_REPLACEMENTDELTAS) if (cl.numackframes < sizeof(cl.ackframes)/sizeof(cl.ackframes[0])) cl.ackframes[cl.numackframes++] = -1; diff --git a/engine/client/cl_ents.c b/engine/client/cl_ents.c index 108ca5a3d..bea10d45f 100644 --- a/engine/client/cl_ents.c +++ b/engine/client/cl_ents.c @@ -632,7 +632,7 @@ void CLFTE_ReadDelta(unsigned int entnum, entity_state_t *news, entity_state_t * bits |= MSG_ReadByte()<<24; if (cl_shownet.ival >= 3) - Con_Printf("%3i: Update %4i 0x%x\n", msg_readcount, entnum, bits); + Con_Printf("%3i: Update %4i 0x%x\n", MSG_GetReadCount(), entnum, bits); if (bits & UF_RESET) { @@ -1137,13 +1137,13 @@ void CLFTE_ParseEntities(void) if (removeflag) { if (cl_shownet.ival >= 3) - Con_Printf("%3i: Remove %i @ %i\n", msg_readcount, newnum, cls.netchan.incoming_sequence); + Con_Printf("%3i: Remove %i @ %i\n", MSG_GetReadCount(), newnum, cls.netchan.incoming_sequence); if (!newnum) { /*removal of world - means forget all entities*/ if (cl_shownet.ival >= 3) - Con_Printf("%3i: Reset all\n", msg_readcount); + Con_Printf("%3i: Reset all\n", MSG_GetReadCount()); newp->num_entities = 0; oldp = &nullp; oldp->num_entities = 0; @@ -1330,7 +1330,7 @@ void CLQW_ParsePacketEntities (qboolean delta) if (word & U_MOREBITS) { - int oldpos = msg_readcount; + int oldpos = MSG_GetReadCount(); int excessive; excessive = MSG_ReadByte(); if (excessive & U_EVENMORE) @@ -1342,7 +1342,7 @@ void CLQW_ParsePacketEntities (qboolean delta) newnum += 1024; } - msg_readcount = oldpos;//undo the read... + MSG_ReadSkip(oldpos-MSG_GetReadCount());//undo the read... } oldnum = oldindex >= oldp->num_entities ? 9999 : oldp->entities[oldindex].number; @@ -1459,7 +1459,7 @@ void DP5_ParseDelta(entity_state_t *s, packet_entities_t *pack) unsigned int bits; if (cl_shownet.ival >= 3) - Con_Printf("%3i: Update %i", msg_readcount, s->number); + Con_Printf("%3i: Update %i", MSG_GetReadCount(), s->number); bits = MSG_ReadByte(); if (bits & E5_EXTEND1) diff --git a/engine/client/cl_input.c b/engine/client/cl_input.c index d02340a8d..cd14bcd86 100644 --- a/engine/client/cl_input.c +++ b/engine/client/cl_input.c @@ -2094,7 +2094,7 @@ qboolean CLQW_SendCmd (sizebuf_t *buf, qboolean actuallysend) cl.validsequence = 0; //delta_sequence is the _expected_ previous sequences, so is set before it arrives. - if (cl.validsequence && !cl_nodelta.ival && cls.state == ca_active && !cls.demorecording) + if (cl.validsequence && !cl_nodelta.ival && cls.state == ca_active)// && !cls.demorecording) { cl.inframes[cls.netchan.outgoing_sequence&UPDATE_MASK].delta_sequence = cl.validsequence; MSG_WriteByte (buf, clc_delta); diff --git a/engine/client/cl_main.c b/engine/client/cl_main.c index 3b929d983..548fd3b0c 100644 --- a/engine/client/cl_main.c +++ b/engine/client/cl_main.c @@ -3280,7 +3280,7 @@ void CL_ConnectionlessPacket (void) if (c == A2C_PRINT) { - if (!strncmp(net_message.data+msg_readcount, "\\chunk", 6)) + if (!strncmp(net_message.data+MSG_GetReadCount(), "\\chunk", 6)) { if (NET_CompareBaseAdr(&cls.netchan.remote_address, &net_from) == false) if (cls.realserverip.type == NA_INVALID || NET_CompareBaseAdr(&cls.realserverip, &net_from) == false) @@ -3292,7 +3292,7 @@ void CL_ConnectionlessPacket (void) if (CL_ParseOOBDownload()) { - if (msg_readcount != net_message.cursize) + if (MSG_GetReadCount() != net_message.cursize) { Con_Printf ("junk on the end of the packet\n"); CL_Disconnect_f(); @@ -3634,13 +3634,13 @@ void CL_ConnectionlessPacket (void) if (connectinfo.protocol == CP_QUAKE2) { char *nl; - msg_readcount--; - c = msg_readcount; + MSG_ReadSkip(-1); + c = MSG_GetReadCount(); s = MSG_ReadString (); nl = strchr(s, '\n'); if (nl) { - msg_readcount = c + nl-s + 1; + MSG_ReadSkip(c + nl-s + 1 - MSG_GetReadCount()); msg_badread = false; *nl = '\0'; } @@ -3678,7 +3678,7 @@ void CL_ConnectionlessPacket (void) else { Con_TPrintf ("unknown connectionless packet for q2: %s\n", s); - msg_readcount = c; + MSG_ReadSkip(c - MSG_GetReadCount()); c = MSG_ReadByte(); } } @@ -4202,7 +4202,7 @@ void CL_ReadPacket(void) case NQNC_RELIABLE: case NQNC_UNRELIABLE: MSG_ChangePrimitives(cls.netchan.netprim); - CL_WriteDemoMessage (&net_message, msg_readcount); + CL_WriteDemoMessage (&net_message, MSG_GetReadCount()); CLNQ_ParseServerMessage (); break; } @@ -4240,7 +4240,7 @@ void CL_ReadPacket(void) else if (!Netchan_Process(&cls.netchan)) return; // wasn't accepted for some reason - CL_WriteDemoMessage (&net_message, msg_readcount); + CL_WriteDemoMessage (&net_message, MSG_GetReadCount()); if (cls.netchan.incoming_sequence > cls.netchan.outgoing_sequence) { //server should not be responding to packets we have not sent yet diff --git a/engine/client/cl_parse.c b/engine/client/cl_parse.c index 0e0ef831d..42b4518c1 100644 --- a/engine/client/cl_parse.c +++ b/engine/client/cl_parse.c @@ -2726,14 +2726,14 @@ static void CL_ParseDownload (qboolean zlib) if (cls.demoplayback && cls.demoplayback != DPB_EZTV) { if (size > 0) - msg_readcount += size; + MSG_ReadSkip(size); return; // not in demo playback, we don't know the name of the file. } if (!dl) { //download packet without file requested. if (size > 0) - msg_readcount += size; + MSG_ReadSkip(size); return; // not in demo playback } @@ -2752,7 +2752,7 @@ static void CL_ParseDownload (qboolean zlib) dl->method = DL_QW; if (!DL_Begun(dl)) { - msg_readcount += size; + MSG_ReadSkip(size); Con_TPrintf ("Failed to open %s\n", dl->tempname); CL_DownloadFailed(dl->remotename, dl, DLFAIL_CLIENTFILE); CL_RequestNextDownload (); @@ -2770,7 +2770,7 @@ static void CL_ParseDownload (qboolean zlib) char cdata[8192]; unsigned int done = 0; memset(&s, 0, sizeof(s)); - s.next_in = net_message.data + msg_readcount; + s.next_in = net_message.data + MSG_GetReadCount(); s.avail_in = clen; if (inflateInit2(&s, -15) != Z_OK) Host_EndGame ("CL_ParseZDownload: unable to initialise zlib"); @@ -2799,7 +2799,7 @@ static void CL_ParseDownload (qboolean zlib) #else Host_EndGame("Unable to handle zlib downloads, zlib is not supported in this build"); #endif - msg_readcount += size; + MSG_ReadSkip(size); } else #ifdef PEXT_ZLIBDL @@ -2809,15 +2809,15 @@ static void CL_ParseDownload (qboolean zlib) percent = percent - 101; - VFS_WRITE (cls.download, ZLibDownloadDecode(&compsize, net_message.data + msg_readcount, size), size); + VFS_WRITE (cls.download, ZLibDownloadDecode(&compsize, net_message.data + MSG_GetReadCount(), size), size); - msg_readcount += compsize; + MSG_ReadSkip(compsize); } else #endif { - VFS_WRITE (dl->file, net_message.data + msg_readcount, size); - msg_readcount += size; + VFS_WRITE (dl->file, net_message.data + MSG_GetReadCount(), size); + MSG_ReadSkip(size); } dl->completedbytes += size; @@ -6983,7 +6983,7 @@ static void Con_HexDump(qbyte *packet, size_t len, size_t badoffset) } void CL_DumpPacket(void) { - Con_HexDump(net_message.data, net_message.cursize, msg_readcount-1); + Con_HexDump(net_message.data, net_message.cursize, MSG_GetReadCount()-1); } static void CL_ParsePortalState(void) @@ -7093,8 +7093,9 @@ static void CL_ParseBaseAngle(int seat) VRUI_SnapAngle(); } -#define SHOWNET(x) if(cl_shownet.value>=2)Con_Printf ("%3i:%s\n", msg_readcount-1, x); -#define SHOWNET2(x, y) if(cl_shownet.value>=2)Con_Printf ("%3i:%3i:%s\n", msg_readcount-1, y, x); +#define SHOWNETEOM(x) if(cl_shownet.value>=2)Con_Printf ("%3i:%s\n", MSG_GetReadCount(), x); +#define SHOWNET(x) if(cl_shownet.value>=2)Con_Printf ("%3i:%s\n", MSG_GetReadCount()-1, x); +#define SHOWNET2(x, y) if(cl_shownet.value>=2)Con_Printf ("%3i:%3i:%s\n", MSG_GetReadCount()-1, y, x); /* ===================== CL_ParseServerMessage @@ -7180,7 +7181,7 @@ void CLQW_ParseServerMessage (void) break; } - cmdstart = msg_readcount; + cmdstart = MSG_GetReadCount(); cmd = MSG_ReadByte (); if (cmd == svcfte_choosesplitclient) @@ -7195,8 +7196,7 @@ void CLQW_ParseServerMessage (void) if (cmd == -1) { - msg_readcount++; // so the EOM showner has the right value - SHOWNET("END OF MESSAGE"); + SHOWNETEOM("END OF MESSAGE"); break; } @@ -7207,7 +7207,7 @@ void CLQW_ParseServerMessage (void) { default: CL_DumpPacket(); - Host_EndGame ("CLQW_ParseServerMessage: Illegible server message (%i@%i)%s", cmd, msg_readcount-1, (!cl.csqcdebug && suggestcsqcdebug)?"\n'sv_csqcdebug 1' might aid in debugging this.":"" ); + Host_EndGame ("CLQW_ParseServerMessage: Illegible server message (%i@%i)%s", cmd, MSG_GetReadCount()-1, (!cl.csqcdebug && suggestcsqcdebug)?"\n'sv_csqcdebug 1' might aid in debugging this.":"" ); return; case svc_time: @@ -7710,7 +7710,7 @@ void CLQW_ParseServerMessage (void) break; } - packetusage_pending[cmd] += msg_readcount-cmdstart; + packetusage_pending[cmd] += MSG_GetReadCount()-cmdstart; } } @@ -7725,17 +7725,15 @@ static void CLQ2_ParseZPacket(void) unsigned short clen = MSG_ReadShort(); unsigned short ulen = MSG_ReadShort(); sizebuf_t restoremsg; - int restorereadcount; - if (clen > net_message.cursize-msg_readcount) + if (clen > net_message.cursize-MSG_GetReadCount()) Host_EndGame ("CLQ2_ParseZPacket: svcr1q2_zpacket truncated"); if (ulen > net_message.maxsize-net_message.cursize) Host_EndGame ("CLQ2_ParseZPacket: svcr1q2_zpacket overflow"); - indata = net_message.data + msg_readcount; + indata = net_message.data + MSG_GetReadCount(); outdata = net_message.data + net_message.cursize; MSG_ReadSkip(clen); restoremsg = net_message; - restorereadcount = msg_readcount; - msg_readcount = net_message.cursize; + net_message.currentbit = net_message.cursize<<3; net_message.cursize += ulen; memset(&s, 0, sizeof(s)); @@ -7756,7 +7754,6 @@ static void CLQ2_ParseZPacket(void) CLQ2_ParseServerMessage(); net_message = restoremsg; - msg_readcount = restorereadcount; msg_badread = false; #endif } @@ -7780,7 +7777,7 @@ void CLQ2_ParseServerMessage (void) int i; unsigned int seat; // int j; - int startpos = msg_readcount; + int startpos = MSG_GetReadCount(); cl.last_servermessage = realtime; CL_ClearProjectiles (); @@ -7822,8 +7819,7 @@ void CLQ2_ParseServerMessage (void) if (cmd == -1) { - msg_readcount++; // so the EOM showner has the right value - SHOWNET("END OF MESSAGE"); + SHOWNETEOM("END OF MESSAGE"); break; } @@ -8200,8 +8196,7 @@ void CLNQ_ParseServerMessage (void) if (cmd == -1) { - msg_readcount++; // so the EOM showner has the right value - SHOWNET("END OF MESSAGE"); + SHOWNETEOM("END OF MESSAGE"); break; } @@ -8220,7 +8215,7 @@ void CLNQ_ParseServerMessage (void) default: badsvc: CL_DumpPacket(); - Host_EndGame ("CLNQ_ParseServerMessage: Illegible server message (%i@%i)", cmd, msg_readcount-1); + Host_EndGame ("CLNQ_ParseServerMessage: Illegible server message (%i@%i)", cmd, MSG_GetReadCount()-1); return; case svc_nop: diff --git a/engine/client/cl_tent.c b/engine/client/cl_tent.c index 568487078..a46d504b7 100644 --- a/engine/client/cl_tent.c +++ b/engine/client/cl_tent.c @@ -1924,7 +1924,7 @@ void CL_ParseTEnt (void) void CL_ParseTEnt_Sized (void) { unsigned short sz = MSG_ReadShort(); - int start = msg_readcount; + int start = MSG_GetReadCount(); for(;;) { @@ -1940,25 +1940,24 @@ void CL_ParseTEnt_Sized (void) CL_ParseTEnt(); #endif - if (msg_readcount < start + sz) + if (MSG_GetReadCount() < start + sz) { //try to be more compatible with xonotic. int next = MSG_ReadByte(); if (next == svc_temp_entity) continue; - msg_readcount--; - Con_Printf("Sized temp_entity data too large (next byte %i, %i bytes unread)\n", next, (start+sz)-msg_readcount); - msg_readcount = start + sz; + Con_Printf("Sized temp_entity data too large (next byte %i, %i bytes unread)\n", next, (start+sz)-MSG_GetReadCount()-1); + MSG_ReadSkip(start+sz-MSG_GetReadCount()); return; } break; } - if (msg_readcount != start + sz) + if (MSG_GetReadCount() != start + sz) { - Con_Printf("Tempentity size did not match parsed size misread a gamecode packet (%i bytes too much)\n", msg_readcount - (start+sz)); - msg_readcount = start + sz; + Con_Printf("Tempentity size did not match parsed size misread a gamecode packet (%i bytes too much)\n", MSG_GetReadCount() - (start+sz)); + MSG_ReadSkip(start+sz-MSG_GetReadCount()); } } diff --git a/engine/client/clq2_ents.c b/engine/client/clq2_ents.c index 762263a8c..edde53395 100644 --- a/engine/client/clq2_ents.c +++ b/engine/client/clq2_ents.c @@ -1166,7 +1166,7 @@ static void CLQ2_ParsePacketEntities (q2frame_t *oldframe, q2frame_t *newframe) if (newnum >= MAX_Q2EDICTS) Host_EndGame ("CL_ParsePacketEntities: bad number:%i", newnum); - if (msg_readcount > net_message.cursize) + if (MSG_GetReadCount() > net_message.cursize) Host_EndGame ("CL_ParsePacketEntities: end of message"); if (!newnum) @@ -1483,7 +1483,7 @@ void CLR1Q2_ParsePlayerUpdate(void) st = &clq2_parse_entities[(frame->parse_entities+pnum) & (MAX_PARSE_ENTITIES-1)]; //I don't like how r1q2 does its maxclients, so I'm just going to go on message size instead - if (msg_readcount == net_message.cursize) + if (MSG_GetReadCount() == net_message.cursize) break; //the local client(s) is not included, thanks to prediction covering that. @@ -1503,11 +1503,11 @@ void CLR1Q2_ParsePlayerUpdate(void) } //just for sanity's sake - if (msg_readcount != net_message.cursize) + if (MSG_GetReadCount() != net_message.cursize) msg_badread = true; } //this should be the only/last thing in these packets, because if it isn't then we're screwed when a packet got lost - msg_readcount = net_message.cursize; + net_message.currentbit = net_message.cursize<<3; } /* diff --git a/engine/client/pr_csqc.c b/engine/client/pr_csqc.c index 156779222..5e2575369 100644 --- a/engine/client/pr_csqc.c +++ b/engine/client/pr_csqc.c @@ -9313,20 +9313,20 @@ void CSQC_ServerInfoChanged(void) qboolean CSQC_ParseTempEntity(void) { - int orc; + int obit; void *pr_globals; if (!csqcprogs || !csqcg.CSQC_Parse_TempEntity) return false; pr_globals = PR_globals(csqcprogs, PR_CURRENT); csqc_mayread = true; - orc = msg_readcount; + obit = net_message.currentbit; PR_ExecuteProgram (csqcprogs, csqcg.CSQC_Parse_TempEntity); csqc_mayread = false; if (G_FLOAT(OFS_RETURN)) return true; //failed. reset the read position. - msg_readcount = orc; + net_message.currentbit = obit; msg_badread = false; return false; } @@ -9338,7 +9338,7 @@ qboolean CSQC_ParseGamePacket(int seat, qboolean sized) if (sized) { int len = (unsigned short)MSG_ReadShort(); - int start = msg_readcount; + int start = MSG_GetReadCount(), end; if (!csqcprogs || !parsefnc) { @@ -9350,10 +9350,11 @@ qboolean CSQC_ParseGamePacket(int seat, qboolean sized) CSQC_ChangeLocalPlayer(seat); PR_ExecuteProgram (csqcprogs, parsefnc); - if (msg_readcount != start + len) + end = MSG_GetReadCount(); + if (end != start + len) { - Con_Printf("Gamecode misread a gamecode packet (%i bytes too much)\n", msg_readcount - (start+len)); - msg_readcount = start + len; + Con_Printf("Gamecode misread a gamecode packet (%i bytes too much)\n", end - (start+len)); + MSG_ReadSkip(start + len - end); //unread or skip. } } else @@ -9725,7 +9726,7 @@ void CSQC_ParseEntities(qboolean sized) if (sized) { packetsize = MSG_ReadShort(); - packetstart = msg_readcount; + packetstart = MSG_GetReadCount(); } else { @@ -9771,13 +9772,14 @@ void CSQC_ParseEntities(qboolean sized) if (sized) { - if (msg_readcount != packetstart+packetsize) + unsigned int readcount = MSG_GetReadCount(); + if (readcount != packetstart+packetsize) { - if (msg_readcount > packetstart+packetsize) - Con_Printf("CSQC overread entity %i. Size %i, read %i", entnum, packetsize, msg_readcount - packetstart); + if (readcount > packetstart+packetsize) + Con_Printf("CSQC overread entity %i. Size %i, read %i", entnum, packetsize, readcount - packetstart); else - Con_Printf("CSQC underread entity %i. Size %i, read %i", entnum, packetsize, msg_readcount - packetstart); - Con_Printf(", first byte is %i(%x)\n", net_message.data[msg_readcount], net_message.data[msg_readcount]); + Con_Printf("CSQC underread entity %i. Size %i, read %i", entnum, packetsize, readcount - packetstart); + Con_Printf(", first byte is %i(%x)\n", net_message.data[readcount], net_message.data[readcount]); #ifndef CLIENTONLY if (sv.state) { @@ -9785,7 +9787,7 @@ void CSQC_ParseEntities(qboolean sized) } #endif } - msg_readcount = packetstart+packetsize; //leetism. + MSG_ReadSkip(packetstart+packetsize - readcount); //unread or skip. } } } diff --git a/engine/common/common.c b/engine/common/common.c index 3ed848223..64ad41a12 100644 --- a/engine/common/common.c +++ b/engine/common/common.c @@ -1898,7 +1898,6 @@ void MSGCL_WriteDeltaUsercmd (sizebuf_t *buf, const usercmd_t *from, const userc // // reading functions // -int msg_readcount; qboolean msg_badread; struct netprim_s msg_nullnetprim; static sizebuf_t *msg_readmsg; @@ -1906,7 +1905,6 @@ static sizebuf_t *msg_readmsg; void MSG_BeginReading (sizebuf_t *sb, struct netprim_s prim) { msg_readmsg = sb; - msg_readcount = 0; msg_badread = false; sb->currentbit = 0; sb->packing = SZ_RAWBYTES; @@ -1932,27 +1930,32 @@ MSG_ReadRawBytes static int MSG_ReadRawBytes(sizebuf_t *msg, int bits) { int bitmask = 0; + unsigned int readcount = msg->currentbit>>3; + + if (readcount + (bits>>3) >= msg->cursize) + { + msg_badread = true; + msg->currentbit += bits; + return -1; + } if (bits <= 8) { - bitmask = (unsigned char)msg->data[msg_readcount]; - msg_readcount++; + bitmask = (unsigned char)msg->data[readcount]; msg->currentbit += 8; } else if (bits <= 16) { - bitmask = (unsigned short)(msg->data[msg_readcount] - + (msg->data[msg_readcount+1] << 8)); - msg_readcount += 2; + bitmask = (unsigned short)(msg->data[readcount] + + (msg->data[readcount+1] << 8)); msg->currentbit += 16; } else if (bits <= 32) { - bitmask = msg->data[msg_readcount] - + (msg->data[msg_readcount+1] << 8) - + (msg->data[msg_readcount+2] << 16) - + (msg->data[msg_readcount+3] << 24); - msg_readcount += 4; + bitmask = msg->data[readcount] + + (msg->data[readcount+1] << 8) + + (msg->data[readcount+2] << 16) + + (msg->data[readcount+3] << 24); msg->currentbit += 32; } @@ -2014,7 +2017,6 @@ static int MSG_ReadHuffBits(sizebuf_t *msg, int bits) msg->currentbit = msg->cursize<<3; return -1; } - msg_readcount = (msg->currentbit >> 3) + 1; return bitmask; } @@ -2081,14 +2083,19 @@ void MSG_ReadSkip(int bytes) bytes--; } } - if (msg_readcount+bytes > msg_readmsg->cursize) + msg_readmsg->currentbit += bytes<<3; + if (msg_readmsg->currentbit < 0) { - msg_readcount = msg_readmsg->cursize; + msg_readmsg->currentbit = 0; + msg_badread = true; + return; + } + if (msg_readmsg->currentbit > msg_readmsg->cursize<<3) + { + msg_readmsg->currentbit = msg_readmsg->cursize<<3; msg_badread = true; return; } - msg_readcount += bytes; - msg_readmsg->currentbit = msg_readcount<<3; } @@ -2096,6 +2103,7 @@ void MSG_ReadSkip(int bytes) int MSG_ReadChar (void) { int c; + unsigned int msg_readcount; if (msg_readmsg->packing!=SZ_RAWBYTES) return MSG_ReadBits(-8); @@ -2117,6 +2125,7 @@ int MSG_ReadChar (void) int MSG_ReadByte (void) { unsigned char c; + unsigned int msg_readcount; if (msg_readmsg->packing!=SZ_RAWBYTES) return MSG_ReadBits(8); @@ -2138,6 +2147,7 @@ int MSG_ReadByte (void) int MSG_ReadShort (void) { int c; + unsigned int msg_readcount; if (msg_readmsg->packing!=SZ_RAWBYTES) return (short)MSG_ReadBits(16); @@ -2161,6 +2171,7 @@ int MSG_ReadShort (void) int MSG_ReadLong (void) { int c; + unsigned int msg_readcount; if (msg_readmsg->packing!=SZ_RAWBYTES) return (int)MSG_ReadBits(32); @@ -2236,6 +2247,7 @@ float MSG_ReadFloat (void) float f; int l; } dat; + unsigned int msg_readcount; if (msg_readmsg->packing!=SZ_RAWBYTES) { @@ -2269,6 +2281,7 @@ double MSG_ReadDouble (void) quint64_t l; double f; } dat; + unsigned int msg_readcount = msg_readmsg->currentbit>>3; if (msg_readcount+8 > net_message.cursize) { diff --git a/engine/common/common.h b/engine/common/common.h index 97d4a0f72..62927ebf1 100644 --- a/engine/common/common.h +++ b/engine/common/common.h @@ -342,7 +342,6 @@ void MSGQW_WriteDeltaUsercmd (sizebuf_t *sb, const struct usercmd_s *from, const void MSGCL_WriteDeltaUsercmd (sizebuf_t *sb, const struct usercmd_s *from, const struct usercmd_s *cmd); void MSG_WriteDir (sizebuf_t *sb, float *dir); -extern int msg_readcount; extern qboolean msg_badread; // set if a read goes beyond end of message extern struct netprim_s msg_nullnetprim; diff --git a/engine/common/net_chan.c b/engine/common/net_chan.c index d01d259c9..e37cac15a 100644 --- a/engine/common/net_chan.c +++ b/engine/common/net_chan.c @@ -1087,7 +1087,7 @@ qboolean Netchan_Process (netchan_t *chan) if (offset) { - int len = net_message.cursize - msg_readcount; + int len = net_message.cursize - MSG_GetReadCount(); qboolean more = false; if (offset & 1) { @@ -1117,7 +1117,7 @@ qboolean Netchan_Process (netchan_t *chan) return false; /*dropped one*/ } - memcpy(chan->in_fragment_buf + offset, net_message.data + msg_readcount, len); + memcpy(chan->in_fragment_buf + offset, net_message.data + MSG_GetReadCount(), len); chan->in_fragment_length += len; if (more) @@ -1126,7 +1126,7 @@ qboolean Netchan_Process (netchan_t *chan) return false; } memcpy(net_message.data, chan->in_fragment_buf, chan->in_fragment_length); - msg_readcount = 0; + net_message.currentbit = 0; net_message.cursize = chan->in_fragment_length; if (showpackets.value) @@ -1194,7 +1194,7 @@ qboolean Netchan_Process (netchan_t *chan) if (chan->compresstable) { // Huff_CompressPacket(&net_message, (chan->sock == NS_SERVER)?10:8); - Huff_DecompressPacket(chan->compresstable, &net_message, msg_readcount); + Huff_DecompressPacket(chan->compresstable, &net_message, MSG_GetReadCount()); } #endif diff --git a/engine/server/sv_cluster.c b/engine/server/sv_cluster.c index 995376b23..8ab13bb5b 100644 --- a/engine/server/sv_cluster.c +++ b/engine/server/sv_cluster.c @@ -1187,7 +1187,7 @@ void MSV_ReadFromSubServer(pubsubserver_t *s) } break; } - if (msg_readcount != net_message.cursize || msg_badread) + if (MSG_GetReadCount() != net_message.cursize || msg_badread) Sys_Error("Master: Readcount isn't right (%i)\n", net_message.data[0]); } @@ -1525,7 +1525,7 @@ void SSV_ReadFromControlServer(void) break; } - if (msg_readcount != net_message.cursize || msg_badread) + if (MSG_GetReadCount() != net_message.cursize || msg_badread) Sys_Error("Subserver: Readcount isn't right (%i)\n", net_message.data[0]); } diff --git a/engine/server/sv_main.c b/engine/server/sv_main.c index 065472288..c7f4ce46d 100644 --- a/engine/server/sv_main.c +++ b/engine/server/sv_main.c @@ -4268,6 +4268,7 @@ qboolean SVNQ_ConnectionlessPacket(void) { int numnops = 0; int numnonnops = 0; + int c; /*make it at least robust enough to ignore any other stringcmds*/ while(1) { @@ -4278,13 +4279,23 @@ qboolean SVNQ_ConnectionlessPacket(void) continue; case clc_stringcmd: numnonnops++; - if (msg_readcount+17 <= net_message.cursize && !strncmp("challengeconnect ", &net_message.data[msg_readcount], 17)) +#define CCON "challengeconnect " + for(i = 0; ; i++) + { + if (!CCON[i]) + c = -1; + else + c = MSG_ReadByte(); + if (c != CCON[i]) + break; + } + if (!CCON[i]) { if (sv_showconnectionlessmessages.ival) Con_Printf(S_COLOR_GRAY"%s: CCREQ_CONNECT_COOKIE\n", NET_AdrToString (com_token, sizeof(com_token), &net_from)); Cmd_TokenizeString(MSG_ReadStringLine(), false, false); /*okay, so this is a reliable packet from a client, containing a 'cmd challengeconnect $challenge' response*/ - str = va("connect %i %i %s \"\\name\\unconnected\\mod\\%s\\modver\\%s\\flags\\%s\\password\\%s\"", NQ_NETCHAN_VERSION, 0, Cmd_Argv(1), Cmd_Argv(2), Cmd_Argv(3), Cmd_Argv(4), Cmd_Argv(5)); + str = va("connect %i %i %s \"\\name\\unconnected\\mod\\%s\\modver\\%s\\flags\\%s\\password\\%s\"", NQ_NETCHAN_VERSION, 0, Cmd_Argv(0), Cmd_Argv(1), Cmd_Argv(2), Cmd_Argv(3), Cmd_Argv(4)); Cmd_TokenizeString (str, false, false); SVC_DirectConnect(sequence); @@ -4292,7 +4303,7 @@ qboolean SVNQ_ConnectionlessPacket(void) /*if there is anything else in the packet, we don't actually care. its reliable, so they'll resend*/ return true; } - else + else if (c) //handle any trailing stuff if we don't know what it was. MSG_ReadString(); continue; case -1: diff --git a/engine/server/sv_master.c b/engine/server/sv_master.c index 95fd92dc9..770ac7416 100644 --- a/engine/server/sv_master.c +++ b/engine/server/sv_master.c @@ -1087,6 +1087,7 @@ static void SVM_DiscoveredServer(netadr_t *a, const char *query) static void SVM_ProcessUDPPacket(void) { char *s, *line; + int firstbit; //we shouldn't be taking anything else... if (net_from.prot != NP_DGRAM) @@ -1125,6 +1126,7 @@ static void SVM_ProcessUDPPacket(void) { //go back to start... MSG_BeginReading(&net_message, msg_nullnetprim); } + firstbit = net_message.currentbit; line = MSG_ReadStringLine(); s = COM_Parse(line); if (!strcmp(com_token, "getservers") || !strcmp(com_token, "getserversExt")) @@ -1349,7 +1351,7 @@ static void SVM_ProcessUDPPacket(void) else if (!strncmp(com_token, "getserversExtResponse", 21) && com_token[21] == '\\') { //response from a FTE-master request (lots of IPs from a 'slave' master that we're stealing) netadr_t a = {NA_INVALID}; - msg_readcount = 4+21; //grr + net_message.currentbit = firstbit+(21*8); //grr msg_badread = false; svm.total.heartbeats++; for (;;) diff --git a/engine/server/sv_user.c b/engine/server/sv_user.c index 34b4b16db..ccabe6c59 100644 --- a/engine/server/sv_user.c +++ b/engine/server/sv_user.c @@ -2778,7 +2778,7 @@ void SV_NextUpload (void) // suck out rest of packet size = MSG_ReadShort (); MSG_ReadByte (); - msg_readcount += size; + MSG_ReadSkip(size); return; } @@ -2802,8 +2802,8 @@ void SV_NextUpload (void) OutofBandPrintf(&host_client->snap_from, "Server receiving %s from %d...\n", host_client->uploadfn, host_client->userid); } - VFS_WRITE (host_client->upload, net_message.data + msg_readcount, size); - msg_readcount += size; + VFS_WRITE (host_client->upload, net_message.data + MSG_GetReadCount(), size); + MSG_ReadSkip(size); if (percent != 100) { @@ -8869,6 +8869,7 @@ void SVNQ_ReadClientMove (qboolean forceangle16, qboolean quakeex) void SVNQ_ExecuteClientMessage (client_t *cl) { + extern cvar_t sv_listen_dp; int c; char *s; // client_frame_t *frame; @@ -8980,16 +8981,20 @@ void SVNQ_ExecuteClientMessage (client_t *cl) break; case SCP_NETQUAKE: case SCP_BJP3: - //Hack to work around buggy DP clients that don't reset the proquake hack for the next server - //this ONLY works because the other clc commands are very unlikely to both be 3 bytes big and sent unreliably - //aka: DP ProQuake angles hack hack - //note that if a client then decides to use 16bit angles via this hack then it would be the 'fte dp proquake angles hack hack hack'.... - if (!cl->fteprotocolextensions && !cl->fteprotocolextensions2) - if ((net_message.cursize-(msg_readcount-1) == 16 && cl->proquake_angles_hack) || - (net_message.cursize-(msg_readcount-1) == 19 && !cl->proquake_angles_hack)) + if (sv_listen_dp.ival) { - cl->proquake_angles_hack ^= 1; - SV_ClientPrintf(cl, PRINT_HIGH, "Client sent "S_COLOR_RED"wrong"S_COLOR_WHITE" clc_move size, switching to %u-bit angles to try to compensate\n", cl->proquake_angles_hack?16:8); + unsigned int readcount = MSG_GetReadCount(); + //Hack to work around buggy DP clients that don't reset the proquake hack for the next server + //this ONLY works because the other clc commands are very unlikely to both be 3 bytes big and sent unreliably + //aka: DP ProQuake angles hack hack + //note that if a client then decides to use 16bit angles via this hack then it would be the 'fte dp proquake angles hack hack hack'.... + if (!cl->fteprotocolextensions && !cl->fteprotocolextensions2) + if ((net_message.cursize-(readcount-1) == 16 && cl->proquake_angles_hack) || + (net_message.cursize-(readcount-1) == 19 && !cl->proquake_angles_hack)) + { + cl->proquake_angles_hack ^= 1; + SV_ClientPrintf(cl, PRINT_HIGH, "Client sent "S_COLOR_RED"wrong"S_COLOR_WHITE" clc_move size, switching to %u-bit angles to try to compensate\n", cl->proquake_angles_hack?16:8); + } } forceangle16 = cl->proquake_angles_hack; break;