Beispiel #1
0
/*
* CL_QueryGetInfoMessage
*/
static void CL_QueryGetInfoMessage( const char *cmdname )
{
	netadr_t adr;
	char *requeststring;
	char *server;

	//get what master
	server = Cmd_Argv( 1 );
	if( !server || !( *server ) )
	{
		Com_Printf( "%s: no address provided %s...\n", Cmd_Argv( 0 ), server ? server : "" );
		return;
	}

	requeststring = va( cmdname );

	// send a broadcast packet
	Com_DPrintf( "quering %s...\n", server );

	if( NET_StringToAddress( server, &adr ) )
	{
		socket_t *socket;

		if( NET_GetAddressPort( &adr ) == 0 )
			NET_SetAddressPort( &adr, PORT_SERVER );

		socket = ( adr.type == NA_IP6 ? &cls.socket_udp6 : &cls.socket_udp );
		Netchan_OutOfBandPrint( socket, &adr, requeststring );
	}
	else
	{
		Com_Printf( "Bad address: %s\n", server );
	}
}
Beispiel #2
0
/*
* TV_Downstream_AddMaster_f
* Add a master server to the list
*/
static void TV_Downstream_AddMaster_f( const char *master )
{
	int i;

	if( !master || !master[0] )
		return;

	if( !tv_public->integer )
	{
		Com_Printf( "'TV_Downstream_AddMaster_f' Only public servers use masters.\n" );
		return;
	}

	for( i = 0; i < MAX_MASTERS; i++ )
	{
		if( tv_master_adr[i].type != NA_NOTRANSMIT )
			continue;

		if( !NET_StringToAddress( master, &tv_master_adr[i] ) )
		{
			Com_Printf( "'SV_AddMaster_f' Bad Master server address: %s\n", master );
			return;
		}
		if( NET_GetAddressPort( &tv_master_adr[i] ) == 0 )
			NET_SetAddressPort( &tv_master_adr[i], PORT_MASTER );

		Com_Printf( "Added new master server #%i at %s\n", i, NET_AddressToString( &tv_master_adr[i] ) );
		return;
	}

	Com_Printf( "'TV_Downstream_AddMaster_f' List of master servers is already full\n" );
}
Beispiel #3
0
/*
* SV_AddMaster_f
* Add a master server to the list
*/
static void SV_AddMaster_f( char *address, bool steam )
{
	int i;

	if( !address || !address[0] )
		return;

	if( !sv_public->integer )
	{
		Com_Printf( "'SV_AddMaster_f' Only public servers use masters.\n" );
		return;
	}

	//never go public when not acting as a game server
	if( sv.state > ss_game )
		return;

	for( i = 0; i < MAX_MASTERS; i++ )
	{
		sv_master_t *master = &sv_masters[i];

		if( master->address.type != NA_NOTRANSMIT )
			continue;

		if( !NET_StringToAddress( address, &master->address ) )
		{
			Com_Printf( "'SV_AddMaster_f' Bad Master server address: %s\n", address );
			return;
		}

		if( NET_GetAddressPort( &master->address ) == 0 )
			NET_SetAddressPort( &master->address, steam ? PORT_MASTER_STEAM : PORT_MASTER );

		master->steam = steam;

		Com_Printf( "Added new master server #%i at %s\n", i, NET_AddressToString( &master->address ) );
		return;
	}

	Com_Printf( "'SV_AddMaster_f' List of master servers is already full\n" );
}
Beispiel #4
0
/*
* SV_AddMaster_f
* Add a master server to the list
*/
static void SV_AddMaster_f( char *master )
{
	int i;

	if( !master || !master[0] )
		return;

	if( !sv_public->integer )
	{
		Com_Printf( "'SV_AddMaster_f' Only public servers use masters.\n" );
		return;
	}

	//never go public when not acting as a game server
	if( sv.state > ss_game )
		return;

	for( i = 0; i < MAX_MASTERS; i++ )
	{
		if( master_adr[i].type != NA_NOTRANSMIT )
			continue;

		if( !NET_StringToAddress( master, &master_adr[i] ) )
		{
			Com_Printf( "'SV_AddMaster_f' Bad Master server address: %s\n", master );
			return;
		}

		if( NET_GetAddressPort( &master_adr[i] ) == 0 )
			NET_SetAddressPort( &master_adr[i], PORT_MASTER );

		Com_Printf( "Added new master server #%i at %s\n", i, NET_AddressToString( &master_adr[i] ) );
		return;
	}

	Com_Printf( "'SV_AddMaster_f' List of master servers is already full\n" );
}
Beispiel #5
0
/*
* TV_Init
* 
* Only called at plat.exe startup, not for each game
*/
void TV_Init( void )
{
	Com_Printf( "Initializing " APPLICATION " TV server\n" );

	tv_mempool = Mem_AllocPool( NULL, "TV" );

	TV_AddCommands();

	Cvar_Get( "protocol", va( "%i", APP_PROTOCOL_VERSION ), CVAR_SERVERINFO | CVAR_NOSET );
	Cvar_Get( "gamename", Cvar_String( "gamename" ), CVAR_SERVERINFO | CVAR_NOSET );

	tv_password = Cvar_Get( "tv_password", "", 0 );

	tv_ip = Cvar_Get( "tv_ip", "", CVAR_ARCHIVE | CVAR_NOSET );
	tv_port = Cvar_Get( "tv_port", va( "%i", PORT_TV_SERVER ), CVAR_ARCHIVE | CVAR_NOSET );
	tv_ip6 = Cvar_Get( "tv_ip6", "::", CVAR_ARCHIVE | CVAR_NOSET );
	tv_port6 = Cvar_Get( "tv_port6", va( "%i", PORT_TV_SERVER ), CVAR_ARCHIVE | CVAR_NOSET );
#ifdef TCP_ALLOW_TVCONNECT
	tv_udp = Cvar_Get( "tv_udp", "1", CVAR_SERVERINFO | CVAR_NOSET );
	tv_tcp = Cvar_Get( "tv_tcp", "1", CVAR_SERVERINFO | CVAR_NOSET );
#else
	tv_udp = Cvar_Get( "tv_udp", "1", CVAR_NOSET );
#endif

#ifndef TCP_ALLOW_TVCONNECT
	Cvar_FullSet( "tv_tcp", "0", CVAR_READONLY, true );
#endif

	tv_reconnectlimit = Cvar_Get( "tv_reconnectlimit", "3", CVAR_ARCHIVE );
	tv_timeout = Cvar_Get( "tv_timeout", "125", 0 );
	tv_zombietime = Cvar_Get( "tv_zombietime", "2", 0 );
	tv_name = Cvar_Get( "tv_name", APPLICATION "[TV]", CVAR_SERVERINFO | CVAR_ARCHIVE );
	tv_compresspackets = Cvar_Get( "tv_compresspackets", "1", 0 );
	tv_maxclients = Cvar_Get( "tv_maxclients", "32", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOSET );
	tv_maxmvclients = Cvar_Get( "tv_maxmvclients", "4", CVAR_ARCHIVE | CVAR_SERVERINFO | CVAR_NOSET );
	tv_public = Cvar_Get( "tv_public", "1", CVAR_ARCHIVE | CVAR_SERVERINFO );
	tv_rcon_password = Cvar_Get( "tv_rcon_password", "", 0 );
	tv_autorecord = Cvar_Get( "tv_autorecord", "", CVAR_ARCHIVE );
	tv_lobbymusic = Cvar_Get( "tv_lobbymusic", "", CVAR_ARCHIVE );

	tv_masterservers = Cvar_Get( "tv_masterservers", DEFAULT_MASTER_SERVERS_IPS, CVAR_LATCH );
	tv_masterservers_steam = Cvar_Get( "tv_masterservers_steam", DEFAULT_MASTER_SERVERS_STEAM_IPS, CVAR_LATCH );

	// flood control
	tv_floodprotection_messages = Cvar_Get( "tv_floodprotection_messages", "10", 0 );
	tv_floodprotection_messages->modified = true;
	tv_floodprotection_seconds = Cvar_Get( "tv_floodprotection_seconds", "4", 0 );
	tv_floodprotection_seconds->modified = true;
	tv_floodprotection_penalty = Cvar_Get( "tv_floodprotection_delay", "20", 0 );
	tv_floodprotection_penalty->modified = true;

	if( tv_maxclients->integer < 0 )
		Cvar_ForceSet( "tv_maxclients", "0" );

	if( tv_maxclients->integer )
	{
		tvs.clients = ( client_t * )Mem_Alloc( tv_mempool, sizeof( client_t ) * tv_maxclients->integer );
	}
	else
	{
		tvs.clients = NULL;
	}
	tvs.lobby.spawncount = rand();
	tvs.lobby.snapFrameTime = 100;

	// IPv4
	if( !NET_StringToAddress( tv_ip->string, &tvs.address ) )
		Com_Error( ERR_FATAL, "Couldn't understand address of tv_ip cvar: %s\n", NET_ErrorString() );
	NET_SetAddressPort( &tvs.address, tv_port->integer );

	if( tv_udp->integer )
	{
		if( !NET_OpenSocket( &tvs.socket_udp, SOCKET_UDP, &tvs.address, true ) )
		{
			Com_Printf( "Error: Couldn't open UDP socket: %s\n", NET_ErrorString() );
			Cvar_ForceSet( tv_udp->name, "0" );
		}
	}

	// IPv6
	if( !NET_StringToAddress( tv_ip6->string, &tvs.addressIPv6 ) )
		Com_Error( ERR_FATAL, "Couldn't understand address of tv_ip6 cvar: %s\n", NET_ErrorString() );
	NET_SetAddressPort( &tvs.addressIPv6, tv_port6->integer );

	if( tvs.addressIPv6.type != NA_NOTRANSMIT )
	{
		if( !NET_OpenSocket( &tvs.socket_udp6, SOCKET_UDP, &tvs.addressIPv6, true ) )
		{
			Com_Printf( "Error: Couldn't open UDP6 socket: %s\n", NET_ErrorString() );
		}
	}

#ifdef TCP_ALLOW_TVCONNECT
	if( tv_tcp->integer )
	{
		bool err = true;

		if( !NET_OpenSocket( &tvs.socket_tcp, SOCKET_TCP, &tvs.address, true ) )
		{
			Com_Printf( "Error: Couldn't open TCP socket: %s\n", NET_ErrorString() );
		}
		else
		{
			NET_SetSocketNoDelay( &tvs.socket_tcp, 1 );
			if( !NET_Listen( &tvs.socket_tcp ) )
			{
				Com_Printf( "Error: Couldn't listen to TCP socket: %s\n", NET_ErrorString() );
			}
			else
			{
				err = false;
			}
		}

		if( tvs.addressIPv6.type != NA_NOTRANSMIT )
		{
			if( !NET_OpenSocket( &tvs.socket_tcp6, SOCKET_TCP, &tvs.addressIPv6, true ) )
			{
				Com_Printf( "Error: Couldn't open TCP6 socket: %s\n", NET_ErrorString() );
			}
			else
			{
				NET_SetSocketNoDelay( &tvs.socket_tcp6, 1 );
				if( !NET_Listen( &tvs.socket_tcp6 ) )
				{
					Com_Printf( "Error: Couldn't listen to TCP6 socket: %s\n", NET_ErrorString() );
				}
				else
				{
					err = false;
				}
			}
		}

		if( err ) {
			Cvar_ForceSet( tv_tcp->name, "0" );
		}
	}
#endif

	TV_Downstream_InitMaster();
}
Beispiel #6
0
/*
* CL_GetServers_f
*/
void CL_GetServers_f( void )
{
	netadr_t adr, *padr;
	char *requeststring;
	int i;
	char *modname, *master;
	trie_error_t err;

	filter_allow_full = qfalse;
	filter_allow_empty = qfalse;
	for( i = 2; i < Cmd_Argc(); i++ )
	{
		if( !Q_stricmp( "full", Cmd_Argv( i ) ) )
			filter_allow_full = qtrue;

		if( !Q_stricmp( "empty", Cmd_Argv( i ) ) )
			filter_allow_empty = qtrue;
	}

	if( !Q_stricmp( Cmd_Argv( 1 ), "local" ) )
	{
		if( localQueryTimeStamp + LAN_SERVER_PINGING_TIMEOUT > Sys_Milliseconds() ) {
			return;
		}

		padr = &adr;
		localQueryTimeStamp = Sys_Milliseconds();

		// send a broadcast packet
		Com_DPrintf( "pinging broadcast...\n" );

		// erm... modname isn't sent in local queries?

		requeststring = va( "info %i %s %s", SERVERBROWSER_PROTOCOL_VERSION,
			filter_allow_full ? "full" : "",
			filter_allow_empty ? "empty" : "" );

		for( i = 0; i < NUM_BROADCAST_PORTS; i++ )
		{
			NET_BroadcastAddress( padr, PORT_SERVER + i );
			Netchan_OutOfBandPrint( &cls.socket_udp, padr, requeststring );
		}
		return;
	}

	//get what master
	master = Cmd_Argv( 2 );
	if( !master || !( *master ) )
		return;

	modname = Cmd_Argv( 3 );
	// never allow anyone to use DEFAULT_BASEGAME as mod name
	if( !modname || !modname[0] || !Q_stricmp( modname, DEFAULT_BASEGAME ) )
		modname = APPLICATION;

	assert( modname[0] );

	// check memory cache
	QMutex_Lock( resolveLock );
	err = Trie_Find( serverlist_masters_trie, master, TRIE_EXACT_MATCH, (void **)&padr );
	QMutex_Unlock( resolveLock );

	if( err == TRIE_OK && ( padr->type == NA_IP || padr->type == NA_IP6 ) )
	{
		const char *cmdname;
		socket_t *socket;

		if ( padr->type == NA_IP )
		{
			cmdname = "getservers";
			socket = &cls.socket_udp;
		}
		else
		{
			cmdname = "getserversExt";
			socket = &cls.socket_udp6;
		}

		// create the message
		requeststring = va( "%s %c%s %i %s %s", cmdname, toupper( modname[0] ), modname+1, SERVERBROWSER_PROTOCOL_VERSION,
			filter_allow_full ? "full" : "",
			filter_allow_empty ? "empty" : "" );

		if( NET_GetAddressPort( padr ) == 0 )
			NET_SetAddressPort( padr, PORT_MASTER );

		Netchan_OutOfBandPrint( socket, padr, requeststring );

		Com_DPrintf( "quering %s...%s: %s\n", master, NET_AddressToString(padr), requeststring );
	}
	else
	{
		Com_Printf( "Bad address: %s\n", master );
	}
}
Beispiel #7
0
/*
* SV_InitGame
* A brand new game has been started
*/
void SV_InitGame( void )
{
	int i;
	edict_t	*ent;
	netadr_t address, ipv6_address;

	// make sure the client is down
	CL_Disconnect( NULL );
	SCR_BeginLoadingPlaque();

	if( svs.initialized )
	{
		// cause any connected clients to reconnect
		SV_ShutdownGame( "Server restarted", qtrue );

		// SV_ShutdownGame will also call Cvar_GetLatchedVars
	}
	else
	{
		// get any latched variable changes (sv_maxclients, etc)
		Cvar_GetLatchedVars( CVAR_LATCH );
	}

	svs.initialized = qtrue;

	if( sv_skilllevel->integer > 2 )
		Cvar_ForceSet( "sv_skilllevel", "2" );
	if( sv_skilllevel->integer < 0 )
		Cvar_ForceSet( "sv_skilllevel", "0" );

	// init clients
	if( sv_maxclients->integer < 1 )
		Cvar_FullSet( "sv_maxclients", "8", CVAR_SERVERINFO | CVAR_LATCH, qtrue );
	else if( sv_maxclients->integer > MAX_CLIENTS )
		Cvar_FullSet( "sv_maxclients", va( "%i", MAX_CLIENTS ), CVAR_SERVERINFO | CVAR_LATCH, qtrue );

	svs.spawncount = rand();
	svs.clients = Mem_Alloc( sv_mempool, sizeof( client_t )*sv_maxclients->integer );
	svs.client_entities.num_entities = sv_maxclients->integer * UPDATE_BACKUP * MAX_SNAP_ENTITIES;
	svs.client_entities.entities = Mem_Alloc( sv_mempool, sizeof( entity_state_t ) * svs.client_entities.num_entities );

	// init network stuff

	address.type = NA_NOTRANSMIT;
	ipv6_address.type = NA_NOTRANSMIT;

	if( !dedicated->integer )
	{
		NET_InitAddress( &address, NA_LOOPBACK );
		if( !NET_OpenSocket( &svs.socket_loopback, SOCKET_LOOPBACK, &address, qtrue ) )
			Com_Error( ERR_FATAL, "Couldn't open loopback socket: %s\n", NET_ErrorString() );
	}

	if( dedicated->integer || sv_maxclients->integer > 1 )
	{
		qboolean socket_opened = qfalse;

		// IPv4
		NET_StringToAddress( sv_ip->string, &address );
		NET_SetAddressPort( &address, sv_port->integer );
		if( !NET_OpenSocket( &svs.socket_udp, SOCKET_UDP, &address, qtrue ) )
			Com_Printf( "Error: Couldn't open UDP socket: %s\n", NET_ErrorString() );
		else
			socket_opened = qtrue;

		// IPv6
		NET_StringToAddress( sv_ip6->string, &ipv6_address );
		if( ipv6_address.type == NA_IP6 )
		{
			NET_SetAddressPort( &ipv6_address, sv_port6->integer );
			if( !NET_OpenSocket( &svs.socket_udp6, SOCKET_UDP, &ipv6_address, qtrue ) )
				Com_Printf( "Error: Couldn't open UDP6 socket: %s\n", NET_ErrorString() );
			else
				socket_opened = qtrue;
		}
		else
			Com_Printf( "Error: invalid IPv6 address: %s\n", sv_ip6->string );

		if( dedicated->integer && !socket_opened )
			Com_Error( ERR_FATAL, "Couldn't open any socket\n" );
	}

#ifdef TCP_ALLOW_CONNECT
	if( sv_tcp->integer && ( dedicated->integer || sv_maxclients->integer > 1 ) )
	{
		if( !NET_OpenSocket( &svs.socket_tcp, SOCKET_TCP, &address, qtrue ) )
		{
			Com_Printf( "Error: Couldn't open TCP socket: %s", NET_ErrorString() );
			Cvar_ForceSet( "sv_tcp", "0" );
		}
		else
		{
			if( !NET_Listen( &svs.socket_tcp ) )
			{
				Com_Printf( "Error: Couldn't listen to TCP socket: %s", NET_ErrorString() );
				NET_CloseSocket( &svs.socket_tcp );
				Cvar_ForceSet( "sv_tcp", "0" );
			}
		}
	}
#endif

	// init mm
	// SV_MM_Init();

	// init game
	SV_InitGameProgs();
	for( i = 0; i < sv_maxclients->integer; i++ )
	{
		ent = EDICT_NUM( i+1 );
		ent->s.number = i+1;
		svs.clients[i].edict = ent;
	}

	// load the map
	assert( !svs.cms );
	svs.cms = CM_New( NULL );
}
Beispiel #8
0
/*
* 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 );
				}
			}
		}
	}
}
Beispiel #9
0
/*
* 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 );
					}
				}
			}
		}
	}
}