/* ================= CL_ReadNetMessage ================= */ void CL_ReadNetMessage( void ) { size_t curSize; while( CL_GetMessage( net_message_buffer, &curSize )) { BF_Init( &net_message, "ServerData", net_message_buffer, curSize ); // check for connectionless packet (0xffffffff) first if( BF_GetMaxBytes( &net_message ) >= 4 && *(int *)net_message.pData == -1 ) { CL_ConnectionlessPacket( net_from, &net_message ); continue; } // can't be a valid sequenced packet if( cls.state < ca_connected ) continue; if( BF_GetMaxBytes( &net_message ) < 8 ) { MsgDev( D_WARN, "%s: runt packet\n", NET_AdrToString( net_from )); continue; } // packet from server if( !cls.demoplayback && !NET_CompareAdr( net_from, cls.netchan.remote_address )) { MsgDev( D_ERROR, "CL_ReadPackets: %s:sequenced packet without connection\n", NET_AdrToString( net_from )); continue; } if( !cls.demoplayback && !Netchan_Process( &cls.netchan, &net_message )) continue; // wasn't accepted for some reason CL_ParseServerMessage( &net_message ); } // check for fragmentation/reassembly related packets. if( cls.state != ca_disconnected && Netchan_IncomingReady( &cls.netchan )) { // the header is different lengths for reliable and unreliable messages int headerBytes = BF_GetNumBytesRead( &net_message ); // process the incoming buffer(s) if( Netchan_CopyNormalFragments( &cls.netchan, &net_message )) { CL_ParseServerMessage( &net_message ); } if( Netchan_CopyFileFragments( &cls.netchan, &net_message )) { // remove from resource request stuff. CL_ProcessFile( true, cls.netchan.incomingfilename ); } } Netchan_UpdateProgress( &cls.netchan ); }
void CL_ParseZPacket (void) { #ifndef NO_ZLIB byte buff_in[MAX_MSGLEN]; byte buff_out[0xFFFF]; sizebuf_t sb, old; int16 compressed_len = (int16)MSG_ReadShort (&net_message); int16 uncompressed_len = (int16)MSG_ReadShort (&net_message); if (uncompressed_len <= 0) Com_Error (ERR_DROP, "CL_ParseZPacket: uncompressed_len <= 0"); if (compressed_len <= 0) Com_Error (ERR_DROP, "CL_ParseZPacket: compressed_len <= 0"); MSG_ReadData (&net_message, buff_in, compressed_len); SZ_Init (&sb, buff_out, uncompressed_len); sb.cursize = ZLibDecompress (buff_in, compressed_len, buff_out, uncompressed_len, -15); old = net_message; net_message = sb; CL_ParseServerMessage (); net_message = old; Com_DPrintf ("Got a ZPacket, %d->%d\n", uncompressed_len + 4, compressed_len); #else Com_Error (ERR_DROP, "Receied a zPacket but no zlib in this binary"); #endif }
/** * Read all incoming data from the server */ int CL_ReadFromServer(void) { int ret; cl.oldtime = cl.time; cl.time += host_frametime; do { ret = CL_GetMessage(); if (ret == -1) Host_Error("CL_ReadFromServer: lost server connection"); if (!ret) break; cl.last_received_message = realtime; CL_ParseServerMessage(); } while (ret && cls.state == ca_connected); if (cl_shownet.getBool()) Con_Printf("\n"); CL_RelinkEntities(); CL_UpdateTEnts(); // bring the links up to date return 0; }
/* ================= CL_PacketEvent A packet has arrived from the main event loop ================= */ void CL_PacketEvent( netadr_t from, msg_t *msg ) { clc.lastPacketTime = cls.realtime; if ( msg->cursize >= 4 && *(int *)msg->data == -1 ) { CL_ConnectionlessPacket( from, msg ); return; } if ( cls.state < CA_CONNECTED ) { return; // can't be a valid sequenced packet } if ( msg->cursize < 8 ) { Com_Printf ("%s: Runt packet\n",NET_AdrToString( from )); return; } // // packet from server // if ( !NET_CompareAdr( from, clc.netchan.remoteAddress ) ) { Com_DPrintf ("%s:sequenced packet without connection\n" ,NET_AdrToString( from ) ); // FIXME: send a client disconnect? return; } if (!Netchan_Process( &clc.netchan, msg) ) { return; // out of order, duplicated, etc } clc.lastPacketTime = cls.realtime; CL_ParseServerMessage( msg ); }
/** * @sa CL_ConnectionlessPacket * @sa CL_Frame * @sa CL_ParseServerMessage * @sa NET_ReadMsg * @sa SV_ReadPacket */ static void CL_ReadPackets (void) { dbuffer* msg; while ((msg = NET_ReadMsg(cls.netStream))) { const svc_ops_t cmd = NET_ReadByte(msg); if (cmd == svc_oob) CL_ConnectionlessPacket(msg); else CL_ParseServerMessage(cmd, msg); delete msg; } }
void CL_ParseZPacket (sizebuf_t *msg) { byte buff_in[MAX_MSGLEN]; byte buff_out[0xFFFF]; sizebuf_t sb; uint16 compressed_len = MSG_ReadShort (msg); uint16 uncompressed_len = MSG_ReadShort (msg); if (uncompressed_len <= 0) Com_Error (ERR_DROP, "CL_ParseZPacket: uncompressed_len <= 0"); if (compressed_len <= 0) Com_Error (ERR_DROP, "CL_ParseZPacket: compressed_len <= 0"); MSG_ReadData (msg, buff_in, compressed_len); SZ_Init (&sb, buff_out, uncompressed_len); sb.cursize = ZLibDecompress (buff_in, compressed_len, buff_out, uncompressed_len, -15); CL_ParseServerMessage(&sb); Com_DPrintf ("Got a ZPacket, %d->%d\n", uncompressed_len + 4, compressed_len); }
/* ==================== CL_ReadDemoMessage Handles playback of demos ==================== */ void CL_ReadDemoMessage(void) { int i; float f; if (!cls.demoplayback) return; // LordHavoc: pausedemo if (cls.demopaused) return; for (;;) { // decide if it is time to grab the next message // always grab until fully connected if (cls.signon == SIGNONS) { if (cls.timedemo) { cls.td_frames++; cls.td_onesecondframes++; // if this is the first official frame we can now grab the real // td_starttime so the bogus time on the first frame doesn't // count against the final report if (cls.td_frames == 0) { cls.td_starttime = realtime; cls.td_onesecondnexttime = cl.time + 1; cls.td_onesecondrealtime = realtime; cls.td_onesecondframes = 0; cls.td_onesecondminfps = 0; cls.td_onesecondmaxfps = 0; cls.td_onesecondavgfps = 0; cls.td_onesecondavgcount = 0; } if (cl.time >= cls.td_onesecondnexttime) { double fps = cls.td_onesecondframes / (realtime - cls.td_onesecondrealtime); if (cls.td_onesecondavgcount == 0) { cls.td_onesecondminfps = fps; cls.td_onesecondmaxfps = fps; } cls.td_onesecondrealtime = realtime; cls.td_onesecondminfps = min(cls.td_onesecondminfps, fps); cls.td_onesecondmaxfps = max(cls.td_onesecondmaxfps, fps); cls.td_onesecondavgfps += fps; cls.td_onesecondavgcount++; cls.td_onesecondframes = 0; cls.td_onesecondnexttime++; } } else if (cl.time <= cl.mtime[0]) { // don't need another message yet return; } } // get the next message FS_Read(cls.demofile, &cl_message.cursize, 4); cl_message.cursize = LittleLong(cl_message.cursize); if(cl_message.cursize & DEMOMSG_CLIENT_TO_SERVER) // This is a client->server message! Ignore for now! { // skip over demo packet FS_Seek(cls.demofile, 12 + (cl_message.cursize & (~DEMOMSG_CLIENT_TO_SERVER)), SEEK_CUR); continue; } if (cl_message.cursize > cl_message.maxsize) { Con_Printf("Demo message (%i) > cl_message.maxsize (%i)", cl_message.cursize, cl_message.maxsize); cl_message.cursize = 0; CL_Disconnect(); return; } VectorCopy(cl.mviewangles[0], cl.mviewangles[1]); for (i = 0;i < 3;i++) { FS_Read(cls.demofile, &f, 4); cl.mviewangles[0][i] = LittleFloat(f); } if (FS_Read(cls.demofile, cl_message.data, cl_message.cursize) == cl_message.cursize) { MSG_BeginReading(&cl_message); CL_ParseServerMessage(); if (cls.signon != SIGNONS) Cbuf_Execute(); // immediately execute svc_stufftext if in the demo before connect! // In case the demo contains a "svc_disconnect" message if (!cls.demoplayback) return; if (cls.timedemo) return; } else { CL_Disconnect(); return; } } }
/* ================= CL_ReadDemoMessage ================= */ void CL_ReadDemoMessage(void) { int r; msg_t buf; byte bufData[MAX_MSGLEN]; int s; if (!clc.demofile) { CL_DemoCompleted(); return; } #if NEW_DEMOFUNC di.numSnaps++; if (di.snapCount < maxRewindBackups && ((!di.gotFirstSnap && !(cls.state >= CA_CONNECTED && cls.state < CA_PRIMED)) || (di.gotFirstSnap && di.numSnaps % (di.snapsInDemo / maxRewindBackups) == 0))) { rewindBackups_t *rb; if (!di.skipSnap) { // first snap triggers loading screen when rewinding di.skipSnap = qtrue; goto keep_reading; } di.gotFirstSnap = qtrue; rb = &rewindBackups[di.snapCount]; if (!rb->valid) { rb->valid = qtrue; rb->numSnaps = di.numSnaps; rb->seekPoint = FS_FTell(clc.demofile); memcpy(&rb->cl, &cl, sizeof(clientActive_t)); memcpy(&rb->clc, &clc, sizeof(clientConnection_t)); memcpy(&rb->cls, &cls, sizeof(clientStatic_t)); } di.snapCount++; } keep_reading: #endif // get the sequence number r = FS_Read(&s, 4, clc.demofile); if (r != 4) { CL_DemoCompleted(); return; } clc.serverMessageSequence = LittleLong(s); // init the message MSG_Init(&buf, bufData, sizeof(bufData)); // get the length r = FS_Read(&buf.cursize, 4, clc.demofile); if (r != 4) { CL_DemoCompleted(); return; } buf.cursize = LittleLong(buf.cursize); if (buf.cursize == -1) { CL_DemoCompleted(); return; } if (buf.cursize > buf.maxsize) { Com_FuncDrop("demoMsglen > MAX_MSGLEN"); return; } r = FS_Read(buf.data, buf.cursize, clc.demofile); if (r != buf.cursize) { Com_FuncPrinf("Demo file was truncated.\n"); CL_DemoCompleted(); return; } clc.lastPacketTime = cls.realtime; buf.readcount = 0; CL_ParseServerMessage(&buf); }