/* * ================= * 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" ); }
void SV_ReadPackets() { guard(SV_ReadPackets); 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 net_message.BeginReading(); MSG_ReadLong(&net_message); // sequence number MSG_ReadLong(&net_message); // sequence number int qport = MSG_ReadShort(&net_message) & 0xFFFF; // check for packets from connected clients int i; client_t *cl; for (i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++) { if (cl->state == cs_free) continue; // compare address: ignore network port, but use qport if (!NET_CompareBaseAdr(&net_from, &cl->netchan.remote_address)) continue; if (cl->netchan.port != qport) continue; // found a client if (cl->netchan.remote_address.port != net_from.port) { appWPrintf("SV_ReadPackets: fixing up a translated port\n"); cl->netchan.remote_address.port = net_from.port; } if (cl->netchan.Process(&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 != sv_maxclients->integer) continue; } unguard; }
/** * @sa CL_ReadPacket * @sa NET_ReadMsg * @sa SV_Start */ void SV_ReadPacket (struct net_stream *s) { client_t *cl = (client_t *)NET_StreamGetData(s); struct dbuffer *msg; while ((msg = NET_ReadMsg(s))) { const int cmd = NET_ReadByte(msg); if (cmd == clc_oob) SV_ConnectionlessPacket(s, msg); else if (cl) SV_ExecuteClientMessage(cl, cmd, msg); else NET_StreamFree(s); free_dbuffer(msg); } }
/* ================= 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)); } }
/** * @sa CL_ReadPacket * @sa NET_ReadMsg * @sa SV_Start */ void SV_ReadPacket (struct net_stream *s) { client_t *cl = static_cast<client_t *>(NET_StreamGetData(s)); dbuffer *msg; while ((msg = NET_ReadMsg(s))) { const int cmd = NET_ReadByte(msg); if (cmd == clc_oob) SV_ConnectionlessPacket(s, msg); else if (cl) SV_ExecuteClientMessage(cl, cmd, msg); else { NET_StreamFree(s); s = NULL; } delete msg; } }
void gsc_player_connectionlesspacket(int id) { char* cmd; // rcon pass status if ( ! stackGetParams("s", &cmd)) { printf("scriptengine> ERROR: gsc_player_connectionlesspacket(): param \"cmd\"[1] has to be an string!\n"); stackPushUndefined(); return; } char message[1024]; message[0] = -1; message[1] = -1; message[2] = -1; message[3] = -1; message[4] = 0; strcat(message, cmd); msg_t msg; msg.data = message; msg.maxsize = 131072; msg.cursize = strlen(msg.data)+1; msg.readcount = 0; msg.overflowed = false; msg.bit = 0; #if COD_VERSION == COD2_1_0 int remoteaddress_offset = 452036; #else int remoteaddress_offset = 452308; #endif int info_player = PLAYERBASE(id); netadr_t * from = (netadr_t*)(info_player + remoteaddress_offset); SV_ConnectionlessPacket(*from, &msg); stackReturnInt(1); }
/* ================= SV_ReadPackets ================= */ void SV_ReadPackets (void) { int i; client_t *cl; int qport; // first deal with delayed packets from connected clients for (i = 0, cl=svs.clients; i < MAX_CLIENTS; i++, cl++) { if (cl->state == cs_free) continue; net_from = cl->netchan.remote_address; while (cl->packets && svs.realtime - cl->packets->time >= cl->delay) { SZ_Clear(&net_message); SZ_Write(&net_message, cl->packets->msg.data, cl->packets->msg.cursize); SV_ExecuteClientMessage(cl); SV_FreeHeadDelayedPacket(cl); } } // now deal with new packets while (NET_GetPacket(NS_SERVER)) { 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; } // read the qport out of the message so we can fix up // stupid address translating routers MSG_BeginReading (); MSG_ReadLong (); // sequence number MSG_ReadLong (); // sequence number qport = MSG_ReadShort () & 0xffff; // check which client sent this packet for (i=0, cl=svs.clients ; i<MAX_CLIENTS ; 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_DPrintf ("SV_ReadPackets: fixing up a translated port\n"); cl->netchan.remote_address.port = net_from.port; } break; } if (i == MAX_CLIENTS) continue; // ok, we know who sent this packet, but do we need to delay executing it? if (cl->delay > 0) { if (!svs.free_packets) // packet has to be dropped.. break; // insert at end of list if (!cl->packets) { cl->last_packet = cl->packets = svs.free_packets; } else { // this works because '=' associates from right to left cl->last_packet = cl->last_packet->next = svs.free_packets; } svs.free_packets = svs.free_packets->next; cl->last_packet->next = NULL; cl->last_packet->time = svs.realtime; SZ_Clear(&cl->last_packet->msg); SZ_Write(&cl->last_packet->msg, net_message.data, net_message.cursize); } else { SV_ExecuteClientMessage (cl); } } }
/* ================= 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; } // Broadcast packets should never be treated as sequenced packets! // Don't even bother telling them to go away. It's not our game! // if ( broadcast ) // return; // read the qport out of the message so we can fix up // stupid address translating routers MSG_BeginReadingOOB( msg ); MSG_ReadLong( msg ); // sequence number qport = MSG_ReadShort( msg ) & 0xffff; // find which client the message is from for (i=0, cl=svs.clients ; i < sv_maxclients->integer ; i++,cl++) { #ifdef _XBOX ClientManager::ActivateClient(i); #endif 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 (SV_Netchan_Process(cl, msg)) { // zombie clients still need 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 = svs.time; // don't timeout 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" ); }
/* ================= 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; } }
/* * SV_ReadPackets */ static void SV_ReadPackets( void ) { int i, socketind, ret; client_t *cl; #ifdef TCP_SUPPORT socket_t newsocket; netadr_t mmserver; #endif int game_port; socket_t *socket; netadr_t address; static msg_t msg; static qbyte msgData[MAX_MSGLEN]; socket_t* sockets [] = { &svs.socket_loopback, &svs.socket_udp, &svs.socket_udp6, }; #ifdef TCP_SUPPORT if( SV_MM_Initialized() ) SV_MM_NetAddress( &mmserver ); if( svs.socket_tcp.open ) { while( qtrue ) { // find a free slot for( i = 0; i < MAX_INCOMING_CONNECTIONS; i++ ) { if( !svs.incoming[i].active ) break; } if( i == MAX_INCOMING_CONNECTIONS ) break; if( ( ret = NET_Accept( &svs.socket_tcp, &newsocket, &address ) ) == 0 ) break; if( ret == -1 ) { Com_Printf( "NET_Accept: Error: %s\n", NET_ErrorString() ); continue; } Com_Printf( "New TCP connection from %s\n", NET_AddressToString( &address ) ); svs.incoming[i].active = qtrue; svs.incoming[i].socket = newsocket; svs.incoming[i].address = address; svs.incoming[i].time = svs.realtime; } } for( i = 0; i < MAX_INCOMING_CONNECTIONS; i++ ) { if( !svs.incoming[i].active ) continue; ret = NET_GetPacket( &svs.incoming[i].socket, &address, &msg ); if( ret == -1 ) { Com_Printf( "NET_GetPacket: Error: %s\n", NET_ErrorString() ); NET_CloseSocket( &svs.incoming[i].socket ); svs.incoming[i].active = qfalse; } else if( ret == 1 ) { if( SV_MM_Initialized() && NET_CompareBaseAddress( &mmserver, &address ) ) { Com_DPrintf( "TCP packet from matchmaker\n" ); SV_MM_SetConnection( &svs.incoming[i] ); SV_MM_Packet( &msg ); SV_MM_SetConnection( NULL ); continue; } if( *(int *)msg.data != -1 ) { Com_Printf( "Sequence packet without connection\n" ); NET_CloseSocket( &svs.incoming[i].socket ); svs.incoming[i].active = qfalse; continue; } Com_Printf( "Connectionless TCP packet from: %s\n", NET_AddressToString( &address ) ); SV_ConnectionlessPacket( &svs.incoming[i].socket, &address, &msg ); } } #endif MSG_Init( &msg, msgData, sizeof( msgData ) ); for( socketind = 0; socketind < sizeof( sockets ) / sizeof( sockets[0] ); socketind++ ) { socket = sockets[socketind]; if( !socket->open ) continue; while( ( ret = NET_GetPacket( socket, &address, &msg ) ) != 0 ) { if( ret == -1 ) { Com_Printf( "NET_GetPacket: Error: %s\n", NET_ErrorString() ); continue; } // check for connectionless packet (0xffffffff) first if( *(int *)msg.data == -1 ) { SV_ConnectionlessPacket( socket, &address, &msg ); continue; } // read the game port 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 game_port = MSG_ReadShort( &msg ) & 0xffff; // data follows // check for packets from connected clients for( i = 0, cl = svs.clients; i < sv_maxclients->integer; i++, cl++ ) { unsigned short addr_port; if( cl->state == CS_FREE || cl->state == CS_ZOMBIE ) continue; if( cl->edict && ( cl->edict->r.svflags & SVF_FAKECLIENT ) ) continue; if( !NET_CompareBaseAddress( &address, &cl->netchan.remoteAddress ) ) continue; if( cl->netchan.game_port != game_port ) continue; addr_port = NET_GetAddressPort( &address ); if( NET_GetAddressPort( &cl->netchan.remoteAddress ) != addr_port ) { Com_Printf( "SV_ReadPackets: fixing up a translated port\n" ); NET_SetAddressPort( &cl->netchan.remoteAddress, addr_port ); } if( SV_ProcessPacket( &cl->netchan, &msg ) ) // this is a valid, sequenced packet, so process it { cl->lastPacketReceivedTime = svs.realtime; SV_ParseClientMessage( cl, &msg ); } break; } } } // handle clients with individual sockets for( i = 0; i < sv_maxclients->integer; i++ ) { cl = &svs.clients[i]; if( cl->state == CS_ZOMBIE || cl->state == CS_FREE ) continue; if( !cl->individual_socket ) continue; // not while, we only handle one packet per client at a time here if( ( ret = NET_GetPacket( cl->netchan.socket, &address, &msg ) ) != 0 ) { if( ret == -1 ) { Com_Printf( "Error receiving packet from %s: %s\n", NET_AddressToString( &cl->netchan.remoteAddress ), NET_ErrorString() ); if( cl->reliable ) SV_DropClient( cl, DROP_TYPE_GENERAL, "Error receiving packet: %s", NET_ErrorString() ); } else { if( SV_ProcessPacket( &cl->netchan, &msg ) ) { // this is a valid, sequenced packet, so process it cl->lastPacketReceivedTime = svs.realtime; SV_ParseClientMessage( cl, &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) }