/* ================= 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 ); }
/* ================= CL_Netchan_Process ================= */ qboolean CL_Netchan_Process(netchan_t *chan, msg_t *msg) { int ret; // int i; // static int newsize = 0; ret = Netchan_Process(chan, msg); if(!ret) { return qfalse; } #if DO_NET_ENCODE CL_Netchan_Decode(msg); #endif // Huff_Decompress( msg, CL_DECODE_START ); // for(i=CL_DECODE_START+msg->readcount;i<msg->cursize;i++) { // if (msg->data[i] != chksum[i-(CL_DECODE_START+msg->readcount)]) { // Com_Error(ERR_DROP,"bad %d v %d\n", msg->data[i], chksum[i-(CL_DECODE_START+msg->readcount)]); // } // } newsize += msg->cursize; // Com_Printf("saved %d to %d (%d%%)\n", (oldsize>>3), newsize, 100-(newsize*100/(oldsize>>3))); return qtrue; }
/* * SV_ProcessPacket */ static qboolean SV_ProcessPacket( netchan_t *netchan, msg_t *msg ) { int zerror; if( !Netchan_Process( netchan, msg ) ) return qfalse; // wasn't accepted for some reason // now if compressed, expand it MSG_BeginReading( msg ); MSG_ReadLong( msg ); // sequence MSG_ReadLong( msg ); // sequence_ack MSG_ReadShort( msg ); // game_port if( msg->compressed ) { zerror = Netchan_DecompressMessage( msg ); if( zerror < 0 ) { // compression error. Drop the packet Com_DPrintf( "SV_ProcessPacket: Compression error %i. Dropping packet\n", zerror ); return qfalse; } } return qtrue; }
/* * ================= * SV_ReadPackets * ================= */ void SV_ReadPackets(void) { int i; client_t *cl; int qport; while (NET_GetPacket(NS_SERVER, &net_from, &net_message)) { // check for connectionless packet (0xffffffff) first if (*(int *)net_message.data == -1) { SV_ConnectionlessPacket(); continue; } // read the qport out of the message so we can fix up // stupid address translating routers MSG_BeginReading(&net_message); MSG_ReadLong(&net_message); // sequence number MSG_ReadLong(&net_message); // sequence number qport = MSG_ReadShort(&net_message) & 0xffff; // check for packets from connected clients for (i = 0, cl = svs.clients; i < maxclients->value; i++, cl++) { if (cl->state == cs_free) { continue; } if (!NET_CompareBaseAdr(net_from, cl->netchan.remote_address)) { continue; } if (cl->netchan.qport != qport) { continue; } if (cl->netchan.remote_address.port != net_from.port) { Com_Printf("SV_ReadPackets: fixing up a translated port\n"); cl->netchan.remote_address.port = net_from.port; } if (Netchan_Process(&cl->netchan, &net_message)) { // this is a valid, sequenced packet, so process it if (cl->state != cs_zombie) { cl->lastmessage = svs.realtime; // don't timeout SV_ExecuteClientMessage(cl); } } break; } if (i != maxclients->value) { continue; } } }
/* ================= SV_ReadPackets ================= */ void SV_PacketEvent( netadr_t from, msg_t *msg ) { int i; client_t *cl; int qport; // check for connectionless packet (0xffffffff) first if ( msg->cursize >= 4 && *(int *)msg->data == -1) { SV_ConnectionlessPacket( from, msg ); return; } // read the qport out of the message so we can fix up // stupid address translating routers MSG_BeginReading( msg ); MSG_ReadLong( msg ); // sequence number MSG_ReadLong( msg ); // sequence number qport = MSG_ReadShort( msg ) & 0xffff; // find which client the message is from for (i=0, cl=svs.clients ; i < 1 ; i++,cl++) { if (cl->state == CS_FREE) { continue; } if ( !NET_CompareBaseAdr( from, cl->netchan.remoteAddress ) ) { continue; } // it is possible to have multiple clients from a single IP // address, so they are differentiated by the qport variable if (cl->netchan.qport != qport) { continue; } // the IP port can't be used to differentiate them, because // some address translating routers periodically change UDP // port assignments if (cl->netchan.remoteAddress.port != from.port) { Com_Printf( "SV_ReadPackets: fixing up a translated port\n" ); cl->netchan.remoteAddress.port = from.port; } // make sure it is a valid, in sequence packet if (Netchan_Process(&cl->netchan, msg)) { // zombie clients stil neet to do the Netchan_Process // to make sure they don't need to retransmit the final // reliable message, but they don't do any other processing if (cl->state != CS_ZOMBIE) { cl->lastPacketTime = sv.time; // don't timeout cl->frames[ cl->netchan.incomingAcknowledged & PACKET_MASK ] .messageAcked = sv.time; SV_ExecuteClientMessage( cl, msg ); } } return; } // if we received a sequenced packet from an address we don't reckognize, // send an out of band disconnect packet to it NET_OutOfBandPrint( NS_SERVER, from, "disconnect" ); }
/* ================= Netchan_SV_Process ================= */ qboolean SV_Netchan_Process(client_t *client, msg_t *msg) { int ret; ret = Netchan_Process(&client->netchan, msg); if (!ret) return qfalse; SV_Netchan_Decode(client, msg); return qtrue; }
/* ================= 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 ); }
/* ================= CL_Netchan_Process ================= */ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { int ret; ret = Netchan_Process( chan, msg ); if (!ret) return qfalse; return qtrue; }
/* ================= CL_Netchan_Process ================= */ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { int ret; ret = Netchan_Process( chan, msg ); if (!ret) return qfalse; CL_Netchan_Decode( msg ); newsize += msg->cursize; return qtrue; }
/* ================= Netchan_SV_Process ================= */ qboolean SV_Netchan_Process( client_t *client, msg_t *msg ) { int ret; ret = Netchan_Process( &client->netchan, msg ); if ( !ret ) { return qfalse; } if ( !SV_GameIsSinglePlayer() ) { SV_Netchan_Decode( client, msg ); } return qtrue; }
/* ================= CL_Netchan_Process ================= */ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { int ret; ret = Netchan_Process( chan, msg ); if ( !ret ) { return qfalse; } if ( !SV_GameIsSinglePlayer() ) { CL_Netchan_Decode( msg ); } newsize += msg->cursize; return qtrue; }
/* ================= Netchan_SV_Process ================= */ qboolean SV_Netchan_Process( client_t *client, msg_t *msg ) { int ret; ret = Netchan_Process( &client->netchan, msg ); if (!ret) return qfalse; #ifdef LEGACY_PROTOCOL if(client->compat) SV_Netchan_Decode(client, msg); #endif return qtrue; }
/* * @brief */ static void Sv_ReadPackets(void) { int32_t i; sv_client_t * cl; byte qport; while (Net_ReceiveDatagram(NS_UDP_SERVER, &net_from, &net_message)) { // check for connectionless packet (0xffffffff) first if (*(uint32_t *) net_message.data == 0xffffffff) { Sv_ConnectionlessPacket(); continue; } // read the qport out of the message so we can fix up // stupid address translating routers Net_BeginReading(&net_message); Net_ReadLong(&net_message); // sequence number Net_ReadLong(&net_message); // sequence number qport = Net_ReadByte(&net_message) & 0xff; // check for packets from connected clients for (i = 0, cl = svs.clients; i < sv_max_clients->integer; i++, cl++) { if (cl->state == SV_CLIENT_FREE) continue; if (!Net_CompareClientNetaddr(&net_from, &cl->net_chan.remote_address)) continue; if (cl->net_chan.qport != qport) continue; if (cl->net_chan.remote_address.port != net_from.port) { Com_Warn("Fixing up a translated port\n"); cl->net_chan.remote_address.port = net_from.port; } // this is a valid, sequenced packet, so process it if (Netchan_Process(&cl->net_chan, &net_message)) { cl->last_message = svs.real_time; // nudge timeout Sv_ParseClientMessage(cl); } // we've processed the packet for the correct client, so break break; } } }
/* ================= CL_Netchan_Process ================= */ bool CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { int ret; ret = Netchan_Process( chan, msg ); if (!ret) return false; #ifdef LEGACY_PROTOCOL if(chan->compat) CL_Netchan_Decode(msg); #endif return true; }
/* ================= Netchan_SV_Process ================= */ qboolean SV_Netchan_Process( client_t *client, msg_t *msg ) { int ret; // int i; ret = Netchan_Process( &client->netchan, msg ); if (!ret) return qfalse; SV_Netchan_Decode( client, msg ); // Huff_Decompress( msg, SV_DECODE_START ); // for(i=SV_DECODE_START+msg->readcount;i<msg->cursize;i++) { // if (msg->data[i] != chksum[i-(SV_DECODE_START+msg->readcount)]) { // Com_Error(ERR_DROP,"bad\n"); // } // } return qtrue; }
/* ======================================================================================================================================= CL_Netchan_Process ======================================================================================================================================= */ qboolean CL_Netchan_Process(netchan_t *chan, msg_t *msg) { int ret; ret = Netchan_Process(chan, msg); if (!ret) { return qfalse; } #ifdef LEGACY_PROTOCOL if (chan->compat) { CL_Netchan_Decode(msg); } #endif return qtrue; }
/* ================= CL_Netchan_Process ================= */ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { int ret; // int i; // static int newsize = 0; ret = Netchan_Process( chan, msg ); if ( !ret ) { return qfalse; } #ifdef LEGACY_PROTOCOL if(chan->compat) CL_Netchan_Decode(msg); #endif return qtrue; }
/* ================= SV_ReadPackets ================= */ static void SV_ReadPackets (void) { int i; client_t *cl; while (NET_GetPacket ()) { if (SV_FilterPacket ()) { SV_SendBan (); // tell them we aren't listening... continue; } // check for connectionless packet (0xffffffff) first if (*(int *)net_message.data == -1) { SV_ConnectionlessPacket (); continue; } // check for packets from connected clients for (i = 0, cl = svs.clients; i < MAX_CLIENTS; i++, cl++) { if (cl->state == cs_free) continue; if (!NET_CompareAdr (net_from, cl->netchan.remote_address)) continue; if (Netchan_Process(&cl->netchan)) { // this is a valid, sequenced packet, so process it svs.stats.packets++; cl->send_message = true; // reply at end of frame if (cl->state != cs_zombie) SV_ExecuteClientMessage (cl); } break; } if (i != MAX_CLIENTS) continue; // packet is not from a known client // Con_Printf ("%s:sequenced packet without connection\n", NET_AdrToString(net_from)); } }
/* ================= CL_Netchan_Process ================= */ qboolean CL_Netchan_Process( netchan_t *chan, msg_t *msg ) { int ret; #if defined RTCW_SP // int i; // static int newsize = 0; #endif // RTCW_XX ret = Netchan_Process( chan, msg ); if ( !ret ) { return qfalse; } #if (defined RTCW_SP && DO_NET_ENCODE) || defined RTCW_MP CL_Netchan_Decode( msg ); #elif defined RTCW_ET if ( !SV_GameIsSinglePlayer() ) { CL_Netchan_Decode( msg ); } #endif #if defined RTCW_SP // Huff_Decompress( msg, CL_DECODE_START ); // for(i=CL_DECODE_START+msg->readcount;i<msg->cursize;i++) { // if (msg->data[i] != chksum[i-(CL_DECODE_START+msg->readcount)]) { // Com_Error(ERR_DROP,"bad %d v %d\n", msg->data[i], chksum[i-(CL_DECODE_START+msg->readcount)]); // } // } #endif // RTCW_XX newsize += msg->cursize; #if defined RTCW_SP // Com_Printf("saved %d to %d (%d%%)\n", (oldsize>>3), newsize, 100-(newsize*100/(oldsize>>3))); #endif // RTCW_XX return qtrue; }
/* ================= SV_ReadPackets ================= */ void SV_ReadPackets( void ) { sv_client_t *cl; int i, qport, curSize; while( NET_GetPacket( NS_SERVER, &net_from, net_message_buffer, &curSize )) { BF_Init( &net_message, "ClientPacket", net_message_buffer, curSize ); // check for connectionless packet (0xffffffff) first if( BF_GetMaxBytes( &net_message ) >= 4 && *(int *)net_message.pData == -1 ) { SV_ConnectionlessPacket( net_from, &net_message ); continue; } // read the qport out of the message so we can fix up // stupid address translating routers BF_Clear( &net_message ); BF_ReadLong( &net_message ); // sequence number BF_ReadLong( &net_message ); // sequence number qport = (int)BF_ReadShort( &net_message ) & 0xffff; // check for packets from connected clients for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) { if( cl->state == cs_free || cl->fakeclient ) continue; if( !NET_CompareBaseAdr( net_from, cl->netchan.remote_address )) continue; if( cl->netchan.qport != qport ) continue; if( cl->netchan.remote_address.port != net_from.port ) { MsgDev( D_INFO, "SV_ReadPackets: fixing up a translated port\n"); cl->netchan.remote_address.port = net_from.port; } if( Netchan_Process( &cl->netchan, &net_message )) { cl->send_message = true; // reply at end of frame // this is a valid, sequenced packet, so process it if( cl->state != cs_zombie ) { cl->lastmessage = host.realtime; // don't timeout SV_ExecuteClientMessage( cl, &net_message ); svgame.globals->frametime = host.frametime; svgame.globals->time = sv.time; } } // fragmentation/reassembly sending takes priority over all game messages, want this in the future? if( Netchan_IncomingReady( &cl->netchan )) { if( Netchan_CopyNormalFragments( &cl->netchan, &net_message )) { BF_Clear( &net_message ); SV_ExecuteClientMessage( cl, &net_message ); } if( Netchan_CopyFileFragments( &cl->netchan, &net_message )) { SV_ProcessFile( cl, cl->netchan.incomingfilename ); } } break; } if( i != sv_maxclients->integer ) continue; } }