Example #1
0
/*
* TV_Lobby_SendClientDatagram
*/
static qboolean TV_Lobby_SendClientDatagram( client_t *client )
{
    qbyte msg_buf[MAX_MSGLEN];
    msg_t msg;

    assert( client );
    assert( !client->relay );

    TV_Downstream_InitClientMessage( client, &msg, msg_buf, sizeof( msg_buf ) );

    TV_Downstream_AddReliableCommandsToMessage( client, &msg );
    TV_Lobby_WriteFrameSnapToClient( client, &msg );

    return TV_Downstream_SendMessageToClient( client, &msg );
}
Example #2
0
/*
* TV_Downstream_DenyDownload
* Helper function for generating initdownload packets for denying download
*/
static void TV_Downstream_DenyDownload( client_t *client, const char *reason )
{
	msg_t message;
	uint8_t messageData[MAX_MSGLEN];

	assert( client );
	assert( reason && reason[0] );

	// size -1 is used to signal that it's refused
	// URL field is used for deny reason
	TV_Downstream_InitClientMessage( client, &message, messageData, sizeof( messageData ) );
	TV_Downstream_SendServerCommand( client, "initdownload \"%s\" %i %u %i \"%s\"", "", -1, 0, false, reason );
	TV_Downstream_AddReliableCommandsToMessage( client, &message );
	TV_Downstream_SendMessageToClient( client, &message );
}
Example #3
0
/*
* TV_Downstream_SendClientMessages
*/
void TV_Downstream_SendClientMessages( void )
{
	int i;
	client_t *client;
	msg_t message;
	qbyte messageData[MAX_MSGLEN];

	// send a message to each connected client
	for( i = 0, client = tvs.clients; i < tv_maxclients->integer; i++, client++ )
	{
		if( client->state == CS_FREE || client->state == CS_ZOMBIE )
			continue;

		if( client->state < CS_SPAWNED )
		{
			// send pending reliable commands, or send heartbeats for not timing out
			/*			if( client->reliableSequence > client->reliableSent ||
			(client->reliableSequence > client->reliableAcknowledge &&
			tvs.realtime - client->lastPacketSentTime > 50) ||
			tvs.realtime - client->lastPacketSentTime > 500 ) */
			if( client->reliableSequence > client->reliableAcknowledge ||
				tvs.realtime - client->lastPacketSentTime > 1000 )
			{
				TV_Downstream_InitClientMessage( client, &message, messageData, sizeof( messageData ) );

				TV_Downstream_AddReliableCommandsToMessage( client, &message );
				if( !TV_Downstream_SendMessageToClient( client, &message ) )
				{
					Com_Printf( "%s" S_COLOR_WHITE ": Error sending message: %s\n", client->name, NET_ErrorString() );
					if( client->reliable )
					{
						TV_Downstream_DropClient( client, DROP_TYPE_GENERAL, "Error sending message: %s\n",
							NET_ErrorString() );
					}
				}
			}
		}
	}
}
Example #4
0
/*
* TV_Relay_SendClientDatagram
*/
static bool TV_Relay_SendClientDatagram( relay_t *relay, client_t *client ) {
	uint8_t msg_buf[MAX_MSGLEN];
	msg_t msg;
	snapshot_t *frame;

	assert( relay );
	assert( client );
	assert( relay == client->relay );

	TV_Downstream_InitClientMessage( client, &msg, msg_buf, sizeof( msg_buf ) );

	TV_Downstream_AddReliableCommandsToMessage( client, &msg );

	// send over all the relevant entity_state_t
	// and the player_state_t
	TV_Relay_BuildClientFrameSnap( relay, client );

	frame = relay->curFrame;
	SNAP_WriteFrameSnapToClient( &relay->gi, client, &msg, relay->framenum, relay->serverTime, relay->baselines,
								 &relay->client_entities, frame->numgamecommands, frame->gamecommands, frame->gamecommandsData );

	return TV_Downstream_SendMessageToClient( client, &msg );
}
Example #5
0
/*
* TV_Downstream_DropClient
*/
void TV_Downstream_DropClient( client_t *drop, int type, const char *format, ... )
{
	va_list	argptr;
	char string[1024];
	msg_t Message;
	qbyte MessageData[MAX_MSGLEN];

	va_start( argptr, format );
	Q_vsnprintfz( string, sizeof( string ), format, argptr );
	va_end( argptr );

	Com_Printf( "%s" S_COLOR_WHITE " dropped: %s\n", drop->name, string );

	TV_Downstream_InitClientMessage( drop, &Message, MessageData, sizeof( MessageData ) );

	TV_Downstream_SendServerCommand( drop, "disconnect %i \"%s\"", type, string );
	TV_Downstream_AddReliableCommandsToMessage( drop, &Message );

	TV_Downstream_SendMessageToClient( drop, &Message );
	Netchan_PushAllFragments( &drop->netchan );

	if( drop->relay && /*drop->relay->state == CA_ACTIVE && */drop->state >= CS_CONNECTING )
		TV_Relay_ClientDisconnect( drop->relay, drop );

	// make sure everything is clean
	TV_Downstream_ClientResetCommandBuffers( drop, qtrue );

	SNAP_FreeClientFrames( drop );

	if( drop->download.name )
	{
		if( drop->download.data )
		{
			FS_FreeBaseFile( drop->download.data );
			drop->download.data = NULL;
		}

		Mem_ZoneFree( drop->download.name );
		drop->download.name = NULL;

		drop->download.size = 0;
		drop->download.timeout = 0;
	}

	if( drop->individual_socket )
		NET_CloseSocket( &drop->socket );

	if( drop->mv )
	{
		tvs.nummvclients--;
		drop->mv = qfalse;
	}

	memset( &drop->flood, 0, sizeof( drop->flood ) );

	drop->edict = NULL;
	drop->relay = NULL;
	drop->tv = qfalse;
	drop->state = CS_ZOMBIE;    // become free in a few seconds
	drop->name[0] = 0;
}
Example #6
0
/*
* TV_Downstream_New_f
* 
* Sends the first message from the server to a connected client.
* This will be sent on the initial upstream and upon each server load.
*/
void TV_Downstream_New_f( client_t *client )
{
	int playernum, numpure;
	int tv_bitflags;
	purelist_t *iter;
	msg_t message;
	uint8_t messageData[MAX_MSGLEN];

	// if in CS_AWAITING we have sended the response packet the new once already,
	// but client might have not got it so we send it again
	if( client->state >= CS_SPAWNED )
	{
		Com_DPrintf( "New not valid -- already spawned\n" );
		return;
	}

	// relay is not ready yet
	if( client->relay && client->relay->state < CA_ACTIVE )
	{
		TV_Relay_DelayNew( client );
		return;
	}

	//
	// serverdata needs to go over for all types of servers
	// to make sure the protocol is right, and to set the gamedir
	//
	TV_Downstream_InitClientMessage( client, &message, messageData, sizeof( messageData ) );

	// send the serverdata
	MSG_WriteByte( &message, svc_serverdata );
	MSG_WriteLong( &message, APP_PROTOCOL_VERSION );
	if( !client->relay )
	{
		MSG_WriteLong( &message, tvs.lobby.spawncount );
		MSG_WriteShort( &message, tvs.lobby.snapFrameTime );
		MSG_WriteString( &message, FS_BaseGameDirectory() );
		MSG_WriteString( &message, FS_GameDirectory() );
	}
	else
	{
		MSG_WriteLong( &message, client->relay->servercount );
		MSG_WriteShort( &message, client->relay->snapFrameTime );
		MSG_WriteString( &message, client->relay->basegame );
		MSG_WriteString( &message, client->relay->game );
	}

	if( client->relay )
	{
		// we use our own playernum on the relay server
		MSG_WriteShort( &message, client->relay->playernum );
	}
	else
	{
		playernum = client - tvs.clients;
		MSG_WriteShort( &message, playernum );
	}

	// send full levelname
	if( !client->relay )
		MSG_WriteString( &message, tv_name->string );
	else
		MSG_WriteString( &message, client->relay->levelname );

	memset( &client->lastcmd, 0, sizeof( client->lastcmd ) );

	tv_bitflags = SV_BITFLAGS_TVSERVER;
	if( client->reliable )
		tv_bitflags |= SV_BITFLAGS_RELIABLE;

	MSG_WriteByte( &message, tv_bitflags ); // sv_bitflags

	// purelist
	if( !client->relay )
	{
		MSG_WriteShort( &message, 0 );
	}
	else
	{
		numpure = Com_CountPureListFiles( client->relay->purelist );

		MSG_WriteShort( &message, numpure );
		iter = client->relay->purelist;
		while( iter )
		{
			MSG_WriteString( &message, iter->filename );
			MSG_WriteLong( &message, iter->checksum );
			iter = iter->next;
		}
	}

	TV_Downstream_ClientResetCommandBuffers( client, true );

	TV_Downstream_SendMessageToClient( client, &message );

	Netchan_PushAllFragments( &client->netchan );

	// don't let it send reliable commands until we get the first configstring request
	client->state = CS_CONNECTING;
}
Example #7
0
/*
* TV_Downstream_Baselines_f
*/
static void TV_Downstream_Baselines_f( client_t *client )
{
	int start;
	entity_state_t nullstate;
	msg_t message;
	uint8_t messageData[MAX_MSGLEN];

	if( client->state != CS_CONNECTED )
		return;

	// relay is not ready yet
	if( client->relay && client->relay->state < CA_ACTIVE )
	{
		TV_Downstream_SendServerCommand( client, "reconnect" );
		return;
	}

	// handle the case of a level changing while a client was connecting
	if( atoi( Cmd_Argv( 1 ) ) != ( client->relay ? client->relay->servercount : tvs.lobby.spawncount ) )
	{
		TV_Downstream_New_f( client );
		return;
	}

	if( !client->relay )
	{
		TV_Downstream_SendServerCommand( client, "precache %i", tvs.lobby.spawncount );
		return;
	}

	start = atoi( Cmd_Argv( 2 ) );
	if( start < 0 )
		start = 0;

	memset( &nullstate, 0, sizeof( nullstate ) );

	// write a packet full of data
	TV_Downstream_InitClientMessage( client, &message, messageData, sizeof( messageData ) );

	while( message.cursize < FRAGMENT_SIZE * 3 && start < MAX_EDICTS )
	{
		if( client->relay->baselines[start].number )
		{
			MSG_WriteByte( &message, svc_spawnbaseline );
			MSG_WriteDeltaEntity( &nullstate, &client->relay->baselines[start], &message, true, true );
		}
		start++;
	}

	// send next command
	if( start == MAX_EDICTS )
	{
		TV_Downstream_SendServerCommand( client, "precache %i", client->relay->servercount );
	}
	else
	{
		TV_Downstream_SendServerCommand( client, "cmd baselines %i %i", client->relay->servercount, start );
	}

	TV_Downstream_AddReliableCommandsToMessage( client, &message );
	TV_Downstream_SendMessageToClient( client, &message );
}