/* ================= 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_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 ); }
/** * @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; } }
static void FWD_network_update(void) { fd_set rfds; struct timeval tv; int retval; int i1; peer_t *p; FD_ZERO(&rfds); // select on main server socket FD_SET(net_socket, &rfds); i1 = net_socket + 1; for (p = peers; p; p = p->next) { // select on peers sockets FD_SET(p->s, &rfds); if (p->s >= i1) i1 = p->s + 1; } // if not DLL - read stdin #ifndef APP_DLL #ifndef _WIN32 // try read stdin only if connected to a terminal. if (isatty(STDIN) && isatty(STDOUT)) { FD_SET(STDIN, &rfds); if (STDIN >= i1) i1 = STDIN + 1; } #endif // _WIN32 #endif /* Sleep for some time, wake up immidiately if there input packet. */ tv.tv_sec = 0; tv.tv_usec = 100000; // 100 ms retval = select(i1, &rfds, (fd_set *)0, (fd_set *)0, &tv); // read console input. // NOTE: we do not do that if we are in DLL mode... Sys_ReadSTDIN(&ps, rfds); if (retval <= 0) return; // if we have input packet on main server/proxy socket, then read it if(FD_ISSET(net_socket, &rfds)) { qbool connectionless; int cnt; // read it for(;;) { if (!NET_GetPacket(net_socket, &net_message)) break; // check for bans. if (SV_IsBanned(&net_from)) continue; if (net_message.cursize == 1 && net_message.data[0] == A2A_ACK) { QRY_SV_PingReply(); continue; } MSG_BeginReading(); connectionless = (MSG_ReadLong() == -1); if (connectionless) { if (MSG_BadRead()) continue; if (!SV_ConnectionlessPacket()) continue; // seems we do not need forward it } // search in peers for (p = peers; p; p = p->next) { // we have this peer already, so forward/send packet to remote server if (NET_CompareAddress(&p->from, &net_from)) break; } // peer was not found if (!p) continue; // forward data to the server/proxy if (p->ps >= ps_connected) { cnt = 1; // one packet by default // check for "drop" aka client disconnect, // first 10 bytes for NON connectionless packet is netchan related shit in QW if (p->proto == pr_qw && !connectionless && net_message.cursize > 10 && net_message.data[10] == clc_stringcmd) { if (!strcmp((char*)net_message.data + 10 + 1, "drop")) { // Sys_Printf("peer drop detected\n"); p->ps = ps_drop; // drop peer ASAP cnt = 3; // send few packets due to possibile packet lost } } for ( ; cnt > 0; cnt--) NET_SendPacket(p->s, net_message.cursize, net_message.data, &p->to); } time(&p->last); } } // now lets check peers sockets, perhaps we have input packets too for (p = peers; p; p = p->next) { if(FD_ISSET(p->s, &rfds)) { // yeah, we have packet, read it then for (;;) { if (!NET_GetPacket(p->s, &net_message)) break; // check for bans. if (SV_IsBanned(&net_from)) continue; // we should check is this packet from remote server, this may be some evil packet from haxors... if (!NET_CompareAddress(&p->to, &net_from)) continue; MSG_BeginReading(); if (MSG_ReadLong() == -1) { if (MSG_BadRead()) continue; if (!CL_ConnectionlessPacket(p)) continue; // seems we do not need forward it NET_SendPacket(net_socket, net_message.cursize, net_message.data, &p->from); continue; } if (p->ps >= ps_connected) NET_SendPacket(net_socket, net_message.cursize, net_message.data, &p->from); // qqshka: commented out // time(&p->last); } // for (;;) } // if(FD_ISSET(p->s, &rfds)) if (p->ps == ps_challenge) { // send challenge time to time if (time(NULL) - p->connect > 2) { p->connect = time(NULL); Netchan_OutOfBandPrint(p->s, &p->to, "getchallenge%s", p->proto == pr_qw ? "\n" : ""); } } } // for (p = peers; p; p = p->next) }