コード例 #1
0
/*
========================
idLobby::BecomeHost
========================
*/
void idLobby::BecomeHost()
{

	if( !verify( migrationInfo.state == MIGRATE_PICKING_HOST ) )
	{
		idLib::Printf( "BecomeHost: Must be called from PickNewHost.\n" );
		EndMigration();
		return;
	}
	
	if( IsHost() )
	{
		idLib::Printf( "BecomeHost: Already host of session.\n" );
		EndMigration();
		return;
	}
	
	if( !sessionCB->BecomingHost( *this ) )
	{
		EndMigration();
		return;
	}
	
	idLib::Printf( "BecomeHost: Sending %i invites on %s.\n", migrationInfo.invites.Num(), GetLobbyName() );
	
	migrationInfo.state					= MIGRATE_BECOMING_HOST;
	migrationInfo.migrationStartTime	= Sys_Milliseconds();
	
	if( lobbyBackend == NULL )
	{
		// If we don't have a lobbyBackend, then just create one
		Shutdown();
		StartCreating();
		return;
	}
	
	// Shutdown the current lobby, but keep the lobbyBackend (we'll migrate it)
	Shutdown( true );
	
	// Migrate the lobbyBackend to host
	lobbyBackend->BecomeHost( migrationInfo.invites.Num() );
	
	// Wait for it to complete
	SetState( STATE_CREATE_LOBBY_BACKEND );
}
コード例 #2
0
/*
========================
idLobby::UpdateHostMigration
========================
*/
void idLobby::UpdateHostMigration()
{

	int time = Sys_Milliseconds();
	
	// If we are picking a new host, then update that
	if( migrationInfo.state == MIGRATE_PICKING_HOST )
	{
		const int MIGRATION_PICKING_HOST_TIMEOUT_IN_SECONDS = 20;		// FIXME: set back to 5 // Give other hosts 5 seconds
		
		if( time - migrationInfo.migrationStartTime > session->GetTitleStorageInt( "MIGRATION_PICKING_HOST_TIMEOUT_IN_SECONDS", MIGRATION_PICKING_HOST_TIMEOUT_IN_SECONDS ) * 1000 )
		{
			// Just become the host if we haven't heard from a host in awhile
			BecomeHost();
		}
		else
		{
			return;
		}
	}
	
	// See if we are a new migrated host that needs to invite the original members back
	if( migrationInfo.state != MIGRATE_BECOMING_HOST )
	{
		return;
	}
	
	if( lobbyBackend == NULL || lobbyBackend->GetState() != idLobbyBackend::STATE_READY )
	{
		return;
	}
	
	if( state != STATE_IDLE )
	{
		return;
	}
	
	if( !IsHost() )
	{
		return;
	}
	
	const int MIGRATION_TIMEOUT_IN_SECONDS		= 30; // FIXME: setting to 30 for dev purposes. 10 seems more reasonable. Need to make unloading game / loading lobby async
	const int MIGRATION_INVITE_TIME_IN_SECONDS	= 2;
	
	if( migrationInfo.invites.Num() == 0 || time - migrationInfo.migrationStartTime > session->GetTitleStorageInt( "MIGRATION_TIMEOUT_IN_SECONDS", MIGRATION_TIMEOUT_IN_SECONDS ) * 1000 )
	{
		// Either everyone acked, or we timed out, just keep who we have, and stop sending invites
		EndMigration();
		return;
	}
	
	// Send invites to anyone who hasn't responded
	for( int i = 0; i < migrationInfo.invites.Num(); i++ )
	{
		if( time - migrationInfo.invites[i].lastInviteTime < session->GetTitleStorageInt( "MIGRATION_INVITE_TIME_IN_SECONDS", MIGRATION_INVITE_TIME_IN_SECONDS ) * 1000 )
		{
			continue;		// Not enough time passed
		}
		
		// Mark the time
		migrationInfo.invites[i].lastInviteTime = time;
		
		byte buffer[ idPacketProcessor::MAX_PACKET_SIZE - 2 ];
		idBitMsg outmsg( buffer, sizeof( buffer ) );
		
		// Have lobbyBackend fill out msg with connection info
		lobbyConnectInfo_t connectInfo = lobbyBackend->GetConnectInfo();
		connectInfo.WriteToMsg( outmsg );
		
		// Let them know whether or not this was from in game
		outmsg.WriteBool( migrationInfo.persistUntilGameEndsData.wasMigratedGame );
		
		NET_VERBOSE_PRINT( "NET: Sending migration invite to %s\n", migrationInfo.invites[i].address.ToString() );
		
		// Send the migration invite
		SendConnectionLess( migrationInfo.invites[i].address, OOB_MIGRATE_INVITE, outmsg.GetReadData(), outmsg.GetSize() );
	}
}
コード例 #3
0
//-----------------------------------------------------------------------------
// Purpose: Handle a migration message from our new host
//-----------------------------------------------------------------------------
bool CMatchmaking::ProcessMigrate( MM_Migrate *pMsg )
{
	MM_Migrate reply;
	int type = pMsg->m_MsgType;

	if ( m_CurrentState == MMSTATE_HOSTMIGRATE_WAITINGFORHOST )
	{
		if ( type == MM_Migrate::MESSAGE_HOSTING )
		{
			// Make sure this is the host we were expecting
			if ( !Q_memcmp( &pMsg->m_xnaddr, &m_Host.m_xnaddr, sizeof( m_Host.m_xnaddr ) ) )
			{
				// Reply to the host
				reply.m_MsgType = MM_Migrate::MESSAGE_MIGRATED;
				reply.m_xnaddr = m_Local.m_xnaddr;
				SendMessage( &reply, &m_Host.m_adr );

				XSESSION_INFO info;
				info.sessionID = pMsg->m_sessionId;
				info.hostAddress = pMsg->m_xnaddr;
				info.keyExchangeKey = pMsg->m_key;

				m_Session.SetNewSessionInfo( &info );
				m_Session.SetOwnerId( XUSER_INDEX_NONE );

				if ( !m_Session.MigrateHost() )
				{
					Warning( "Session migrate failed!\n" );

					SessionNotification( SESSION_NOTIFY_FAIL_MIGRATE );
					return true;
				}

				SwitchToState( MMSTATE_HOSTMIGRATE_MIGRATING );
			}
			else
			{
				// Someone else is trying to host
				reply.m_MsgType = MM_Migrate::MESSAGE_STANDBY;
				SendMessage( &reply, &m_Host.m_adr );
			}
		}
	}
	else if ( m_CurrentState == MMSTATE_HOSTMIGRATE_WAITINGFORCLIENTS )
	{
		if ( type == MM_Migrate::MESSAGE_MIGRATED )
		{
			// Flag the client as having migrated
			bool bClientsOutstanding = false;

			for ( int i = 0; i < m_Remote.Count(); ++i )
			{
				if ( m_Remote[i]->m_id == pMsg->m_Id )
				{
					m_Remote[i]->m_bMigrated = true;
				}

				bClientsOutstanding = bClientsOutstanding && m_Remote[i]->m_bMigrated;
			}

			if ( !bClientsOutstanding )
			{
				// Everyone's migrated!
				EndMigration();
			}
		}

		if ( type == MM_Migrate::MESSAGE_STANDBY )
		{
			// Someone requested a standby
			--m_nSendCount;
		}
	}

	return true;
}