diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/matchmakingmigrate.cpp | |
| download | archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip | |
Diffstat (limited to 'engine/matchmakingmigrate.cpp')
| -rw-r--r-- | engine/matchmakingmigrate.cpp | 249 |
1 files changed, 249 insertions, 0 deletions
diff --git a/engine/matchmakingmigrate.cpp b/engine/matchmakingmigrate.cpp new file mode 100644 index 0000000..a667bb0 --- /dev/null +++ b/engine/matchmakingmigrate.cpp @@ -0,0 +1,249 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Handles host migration for a session (not for the game server) +// +//=============================================================================// + +#include "matchmaking.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +//----------------------------------------------------------------------------- +// Purpose: Start a Matchmaking session as the host +//----------------------------------------------------------------------------- +CClientInfo *CMatchmaking::SelectNewHost() +{ + // For now, just grab the first guy in the list + CClientInfo *pClient = &m_Local; + for ( int i = 0; i < m_Remote.Count(); ++i ) + { + if ( m_Remote[i]->m_id > pClient->m_id ) + { + pClient = m_Remote[i]; + } + } + return pClient; +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMatchmaking::StartHostMigration() +{ + SwitchToState( MMSTATE_HOSTMIGRATE_STARTINGMIGRATION ); + + m_pNewHost = SelectNewHost(); + if ( m_pNewHost == &m_Local ) + { + // We're the new host, so start hosting + Msg( "Starting new host" ); + BeginHosting(); + } + else + { + Msg( "Waiting for a new host" ); + SwitchToNewHost(); + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMatchmaking::BeginHosting() +{ + m_Session.SetIsHost( true ); + m_Host = m_Local; + + // Move into private slots + if ( !m_Local.m_bInvited ) + { + RemovePlayersFromSession( &m_Local ); + m_Local.m_bInvited = true; + AddPlayersToSession( &m_Local ); + } + + if ( !m_Session.MigrateHost() ) + { + Warning( "Session migrate failed!\n" ); + + SessionNotification( SESSION_NOTIFY_FAIL_MIGRATE ); + return; + } + + SwitchToState( MMSTATE_HOSTMIGRATE_MIGRATING ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMatchmaking::TellClientsToMigrate() +{ + Msg( "Sending migrate request\n" ); + + XSESSION_INFO info; + m_Session.GetNewSessionInfo( &info ); + + MM_Migrate msg; + msg.m_MsgType = MM_Migrate::MESSAGE_HOSTING; + msg.m_Id = m_Local.m_id; + msg.m_sessionId = info.sessionID; + msg.m_xnaddr = info.hostAddress; + msg.m_key = info.keyExchangeKey; + + for ( int i = 0; i < m_Remote.Count(); ++i ) + { + if ( m_Remote[i]->m_bMigrated ) + { + continue; + } + + SendMessage( &msg, &m_Remote[i]->m_adr ); + } + + m_fSendTimer = GetTime(); + ++m_nSendCount; +} + +//----------------------------------------------------------------------------- +// 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; +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMatchmaking::SwitchToNewHost() +{ + // Set a timer to wait for the host to contact us + m_fWaitTimer = GetTime(); + + // Get rid of the current host net channel + MarkChannelForRemoval( &m_Host.m_adr ); + + AddRemoteChannel( &m_pNewHost->m_adr ); + + SwitchToState( MMSTATE_HOSTMIGRATE_WAITINGFORHOST ); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMatchmaking::EndMigration() +{ + Msg( "Migration complete\n" ); + + if ( m_Session.IsHost() ) + { + // Drop any clients that failed to migrate + for ( int i = m_Remote.Count()-1; i >= 0; --i ) + { + ClientDropped( m_Remote[i] ); + } + + // Update the lobby to show the new host + SendPlayerInfoToLobby( &m_Local, 0 ); + + // X360TBD: Figure out what state we should be in + int newState = m_PreMigrateState; + switch( m_PreMigrateState ) + { + case MMSTATE_SESSION_CONNECTING: + newState = MMSTATE_ACCEPTING_CONNECTIONS; + break; + + default: + Warning( "Unhandled post-migrate state transition" ); + } + + // Don't use SwitchToState() to set our new state because when changing + // from a client to a host the state transition is usually invalid. + m_CurrentState = newState; + } + else + { + // Still a client, just restore our previous state + m_CurrentState = m_PreMigrateState; + } +} + +void CMatchmaking::TestStats() +{ + +} |