/* * 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 ); } } } } }
/* * TV_Downstream_ReadPackets */ void TV_Downstream_ReadPackets( void ) { int i, socketind, ret, game_port; client_t *cl; #ifdef TCP_SUPPORT socket_t newsocket; #endif socket_t *socket; netadr_t address; msg_t msg; qbyte msgData[MAX_MSGLEN]; socket_t* sockets [] = { &tvs.socket_udp, &tvs.socket_udp6, }; #ifdef TCP_SUPPORT if( tvs.socket_tcp.open ) { while( qtrue ) { // find a free slot for( i = 0; i < MAX_INCOMING_CONNECTIONS; i++ ) { if( !tvs.incoming[i].active ) break; } if( i == MAX_INCOMING_CONNECTIONS ) break; if( ( ret = NET_Accept( &tvs.socket_tcp, &newsocket, &address ) ) == 0 ) break; if( ret == -1 ) { Com_Printf( "NET_Accept: Error: %s\n", NET_ErrorString() ); continue; } tvs.incoming[i].active = qtrue; tvs.incoming[i].socket = newsocket; tvs.incoming[i].address = address; tvs.incoming[i].time = tvs.realtime; } } for( i = 0; i < MAX_INCOMING_CONNECTIONS; i++ ) { if( !tvs.incoming[i].active ) continue; ret = NET_GetPacket( &tvs.incoming[i].socket, &address, &msg ); if( ret == -1 ) { NET_CloseSocket( &tvs.incoming[i].socket ); tvs.incoming[i].active = qfalse; } else if( ret == 1 ) { if( *(int *)msg.data != -1 ) { // sequence packet without upstreams NET_CloseSocket( &tvs.incoming[i].socket ); tvs.incoming[i].active = qfalse; continue; } TV_Downstream_UpstreamlessPacket( &tvs.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]; while( socket->open && ( ret = NET_GetPacket( socket, &address, &msg ) ) != 0 ) { if( ret == -1 ) { Com_Printf( "NET_GetPacket: Error: %s\n", NET_ErrorString() ); continue; } // check for upstreamless packet (0xffffffff) first if( *(int *)msg.data == -1 ) { TV_Downstream_UpstreamlessPacket( 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 = tvs.clients; i < tv_maxclients->integer; i++, cl++ ) { unsigned short remoteaddr_port, addr_port; if( cl->state == CS_FREE || cl->state == CS_ZOMBIE ) continue; if( !NET_CompareBaseAddress( &address, &cl->netchan.remoteAddress ) ) continue; if( cl->netchan.game_port != game_port ) continue; remoteaddr_port = NET_GetAddressPort( &cl->netchan.remoteAddress ); addr_port = NET_GetAddressPort( &address ); if( remoteaddr_port != addr_port ) { Com_DPrintf( "%s" S_COLOR_WHITE ": Fixing up a translated port from %i to %i\n", cl->name, remoteaddr_port, addr_port ); NET_SetAddressPort( &cl->netchan.remoteAddress, addr_port ); } if( TV_Downstream_ProcessPacket( &cl->netchan, &msg ) ) { // this is a valid, sequenced packet, so process it cl->lastPacketReceivedTime = tvs.realtime; TV_Downstream_ParseClientMessage( cl, &msg ); } break; } } } // handle clients with individual sockets for( i = 0; i < tv_maxclients->integer; i++ ) { cl = &tvs.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( "%s" S_COLOR_WHITE ": Error receiving packet: %s\n", cl->name, NET_ErrorString() ); if( cl->reliable ) TV_Downstream_DropClient( cl, DROP_TYPE_GENERAL, "Error receiving packet: %s", NET_ErrorString() ); } else { if( *(int *)msg.data == -1 ) { TV_Downstream_UpstreamlessPacket( cl->netchan.socket, &address, &msg ); } else { if( TV_Downstream_ProcessPacket( &cl->netchan, &msg ) ) { cl->lastPacketReceivedTime = tvs.realtime; TV_Downstream_ParseClientMessage( cl, &msg ); } } } } } }