You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
337 lines
11 KiB
337 lines
11 KiB
//========= Copyright Valve Corporation, All rights reserved. ============// |
|
// |
|
// Purpose: steam state machine that handles authenticating steam users |
|
// |
|
//=============================================================================// |
|
#ifdef _WIN32 |
|
#if !defined( _X360 ) |
|
#include "winlite.h" |
|
#include <winsock2.h> // INADDR_ANY defn |
|
#endif |
|
#elif POSIX |
|
#include <netinet/in.h> |
|
#endif |
|
|
|
#include <utlbuffer.h> |
|
#include "cl_steamauth.h" |
|
#include "interface.h" |
|
#include "filesystem_engine.h" |
|
#include "tier0/icommandline.h" |
|
#include "tier0/vprof.h" |
|
#include "host.h" |
|
#include "cmd.h" |
|
#include "common.h" |
|
#ifndef SWDS |
|
#include "vgui_baseui_interface.h" |
|
#endif |
|
|
|
#pragma warning( disable: 4355 ) // disables ' 'this' : used in base member initializer list' |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: singleton accessor |
|
//----------------------------------------------------------------------------- |
|
static CSteam3Client s_Steam3Client; |
|
CSteam3Client &Steam3Client() |
|
{ |
|
return s_Steam3Client; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Constructor |
|
//----------------------------------------------------------------------------- |
|
CSteam3Client::CSteam3Client() |
|
#if !defined(NO_STEAM) |
|
: |
|
m_CallbackClientGameServerDeny( this, &CSteam3Client::OnClientGameServerDeny ), |
|
m_CallbackGameServerChangeRequested( this, &CSteam3Client::OnGameServerChangeRequested ), |
|
m_CallbackGameOverlayActivated( this, &CSteam3Client::OnGameOverlayActivated ), |
|
m_CallbackPersonaStateChanged( this, &CSteam3Client::OnPersonaUpdated ), |
|
m_CallbackLowBattery( this, &CSteam3Client::OnLowBattery ) |
|
#endif |
|
{ |
|
m_bActive = false; |
|
m_bGSSecure = false; |
|
m_hAuthTicket = k_HAuthTicketInvalid; |
|
m_unIP = 0; |
|
m_usPort = 0; |
|
m_nTicketSize = 0; |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Destructor |
|
//----------------------------------------------------------------------------- |
|
CSteam3Client::~CSteam3Client() |
|
{ |
|
Shutdown(); |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Unload the steam3 engine |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::Shutdown() |
|
{ |
|
if ( !m_bActive ) |
|
return; |
|
|
|
m_bActive = false; |
|
#if !defined( NO_STEAM ) |
|
SteamAPI_Shutdown(); |
|
Clear(); // clear our interface pointers now they are invalid |
|
#endif |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Initialize the steam3 connection |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::Activate() |
|
{ |
|
if ( m_bActive ) |
|
return; |
|
|
|
m_bActive = true; |
|
m_bGSSecure = false; |
|
|
|
#if !defined( NO_STEAM ) |
|
SteamAPI_InitSafe(); // ignore failure, that will fall out later when they don't get a valid logon cookie |
|
SteamAPI_SetTryCatchCallbacks( false ); // We don't use exceptions, so tell steam not to use try/catch in callback handlers |
|
Init(); // Steam API context init |
|
#endif |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Get the steam3 logon cookie to use |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::GetAuthSessionTicket( void *pTicket, int cbMaxTicket, uint32 *pcbTicket, uint32 unIP, uint16 usPort, uint64 unGSSteamID, bool bSecure ) |
|
{ |
|
#ifdef NO_STEAM |
|
m_bGSSecure = bSecure; |
|
#else |
|
CSteamID steamIDGS( unGSSteamID ); |
|
|
|
// Assume failure |
|
*pcbTicket = 0; |
|
|
|
// We must have interface pointers |
|
if ( !SteamUser() ) |
|
{ |
|
Warning( "No SteamUser interface. Cannot perform steam authentication\n" ); |
|
return; |
|
} |
|
|
|
// Make sure we have a valid Steam ID |
|
CSteamID steamID = SteamUser()->GetSteamID(); |
|
if ( !steamID.IsValid() ) |
|
{ |
|
Warning( "Our steam ID %s is not valid. Steam must be running and you must be logged in\n", steamID.Render() ); |
|
return; |
|
} |
|
|
|
// Get a new ticket, if we don't already have one for this server |
|
if ( m_hAuthTicket == k_HAuthTicketInvalid |
|
|| m_unIP != unIP |
|
|| m_usPort != usPort |
|
|| m_bGSSecure != bSecure |
|
|| m_steamIDGS != steamIDGS |
|
|| m_nTicketSize <= 0 ) |
|
{ |
|
|
|
// Cancel any previously issues ticket |
|
if ( m_hAuthTicket != k_HAuthTicketInvalid ) |
|
SteamUser()->CancelAuthTicket( m_hAuthTicket ); |
|
|
|
// Shove the GS ID in the first bits |
|
*(uint64*)m_arbTicketData = SteamUser()->GetSteamID().ConvertToUint64(); |
|
|
|
// Ask Steam for a ticket |
|
m_nTicketSize = 0; |
|
m_hAuthTicket = SteamUser()->GetAuthSessionTicket( m_arbTicketData+sizeof(uint64), sizeof(m_arbTicketData)-sizeof(uint64), &m_nTicketSize ); |
|
if ( m_hAuthTicket == k_HAuthTicketInvalid || m_nTicketSize <= 0 ) |
|
{ |
|
// Failed! |
|
Assert( m_hAuthTicket != k_HAuthTicketInvalid ); |
|
Assert( m_nTicketSize > 0 ); |
|
m_hAuthTicket = k_HAuthTicketInvalid; |
|
m_nTicketSize = 0; |
|
Warning( "ISteamUser::GetAuthSessionTicket failed to return a valid ticket\n" ); |
|
} |
|
else |
|
{ |
|
// Got valid ticket. Remember its properties |
|
m_nTicketSize += sizeof(uint64); |
|
m_unIP = unIP; |
|
m_usPort = usPort; |
|
m_bGSSecure = bSecure; |
|
m_steamIDGS = steamIDGS; |
|
} |
|
} |
|
|
|
// Give them back the ticket data, if we were able to get one, and it will fit |
|
*pcbTicket = 0; |
|
if ( m_nTicketSize > 0 ) |
|
{ |
|
if ( cbMaxTicket >= (int)m_nTicketSize ) |
|
{ |
|
memcpy( pTicket, m_arbTicketData, m_nTicketSize ); |
|
*pcbTicket = m_nTicketSize; |
|
} |
|
else |
|
{ |
|
Assert( cbMaxTicket >= (int)m_nTicketSize ); |
|
} |
|
} |
|
|
|
// Tell the steam backend about the server we are playing on - so that it can broadcast this to our friends and they can join. |
|
// This may be something that you should NOT do if you are on a listen server - or you know that the game is not joinable |
|
// for some reason. |
|
#ifdef _DEBUG |
|
Msg( "Sending AdvertiseGame %s %s (%s)\n", steamIDGS.Render(), netadr_t(unIP, usPort).ToString(), m_bGSSecure ? "secure" : "insecure" ); |
|
#endif |
|
SteamUser()->AdvertiseGame( steamIDGS, unIP, usPort ); |
|
#endif |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Tell steam that we are leaving a server |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::CancelAuthTicket() |
|
{ |
|
m_bGSSecure = false; |
|
if ( !SteamUser() ) |
|
return; |
|
|
|
#if !defined( NO_STEAM ) |
|
if ( m_hAuthTicket != k_HAuthTicketInvalid ) |
|
SteamUser()->CancelAuthTicket( m_hAuthTicket ); |
|
#ifdef _DEBUG |
|
Msg( "Clearing auth ticket, sending void AdvertiseGame\n" ); |
|
#endif |
|
CSteamID steamIDGS; // invalid steamID means not playing anywhere |
|
SteamUser()->AdvertiseGame( steamIDGS, 0, 0 ); |
|
m_hAuthTicket = k_HAuthTicketInvalid; |
|
#endif |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: Process any callbacks we may have |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::RunFrame() |
|
{ |
|
#if !defined( NO_STEAM ) |
|
VPROF_BUDGET( "CSteam3Client::RunFrame", VPROF_BUDGETGROUP_STEAM ); |
|
SteamAPI_RunCallbacks(); |
|
#endif |
|
} |
|
|
|
|
|
#if !defined(NO_STEAM) |
|
//----------------------------------------------------------------------------- |
|
// Purpose: Disconnect the user from their current server |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::OnClientGameServerDeny( ClientGameServerDeny_t *pClientGameServerDeny ) |
|
{ |
|
if ( pClientGameServerDeny->m_uAppID == GetSteamAppID() ) |
|
{ |
|
const char *pszReason = "Unknown"; |
|
switch ( pClientGameServerDeny->m_uReason ) |
|
{ |
|
case ( k_EDenyInvalidVersion ) : pszReason = "Invalid version"; break; |
|
case ( k_EDenyGeneric ) : pszReason = "Kicked"; break; |
|
case ( k_EDenyNotLoggedOn ) : pszReason = "Not logged on"; break; |
|
case ( k_EDenyNoLicense ) : pszReason = "No license"; break; |
|
case ( k_EDenyCheater ) : pszReason = "VAC banned "; break; |
|
case ( k_EDenyLoggedInElseWhere ) : pszReason = "Dropped from server"; break; |
|
case ( k_EDenyUnknownText ) : pszReason = "Unknown"; break; |
|
case ( k_EDenyIncompatibleAnticheat ) : pszReason = "Incompatible Anti Cheat"; break; |
|
case ( k_EDenyMemoryCorruption ) : pszReason = "Memory corruption"; break; |
|
case ( k_EDenyIncompatibleSoftware ) : pszReason = "Incompatible software"; break; |
|
case ( k_EDenySteamConnectionLost ) : pszReason = "Steam connection lost"; break; |
|
case ( k_EDenySteamConnectionError ) : pszReason = "Steam connection error"; break; |
|
case ( k_EDenySteamResponseTimedOut ) : pszReason = "Response timed out"; break; |
|
case ( k_EDenySteamValidationStalled ) : pszReason = "Verification failed"; break; |
|
} |
|
|
|
Warning( "Disconnect: %s\n", pszReason ); |
|
|
|
Host_Disconnect( true ); |
|
} |
|
|
|
} |
|
|
|
|
|
extern ConVar password; |
|
//----------------------------------------------------------------------------- |
|
// Purpose: Disconnect the user from their current server |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::OnGameServerChangeRequested( GameServerChangeRequested_t *pGameServerChangeRequested ) |
|
{ |
|
password.SetValue( pGameServerChangeRequested->m_rgchPassword ); |
|
Msg( "Connecting to %s\n", pGameServerChangeRequested->m_rgchServer ); |
|
Cbuf_AddText( va( "connect %s steam\n", pGameServerChangeRequested->m_rgchServer ) ); |
|
} |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::OnGameOverlayActivated( GameOverlayActivated_t *pGameOverlayActivated ) |
|
{ |
|
#ifndef SWDS |
|
if ( Host_IsSinglePlayerGame() ) |
|
{ |
|
if ( !EngineVGui()->IsGameUIVisible() && |
|
!EngineVGui()->IsConsoleVisible() ) |
|
{ |
|
if ( pGameOverlayActivated->m_bActive ) |
|
Cbuf_AddText( "setpause" ); |
|
else |
|
Cbuf_AddText( "unpause" ); |
|
} |
|
} |
|
#endif |
|
} |
|
|
|
extern void UpdateNameFromSteamID( IConVar *pConVar, CSteamID *pSteamID ); |
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::OnPersonaUpdated( PersonaStateChange_t *pPersonaStateChanged ) |
|
{ |
|
if ( pPersonaStateChanged->m_nChangeFlags & k_EPersonaChangeName ) |
|
{ |
|
if ( SteamUtils() && SteamFriends() && SteamUser() ) |
|
{ |
|
CSteamID steamID = SteamUser()->GetSteamID(); |
|
IConVar *pConVar = g_pCVar->FindVar( "name" ); |
|
UpdateNameFromSteamID( pConVar, &steamID ); |
|
} |
|
} |
|
} |
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
// Purpose: |
|
//----------------------------------------------------------------------------- |
|
void CSteam3Client::OnLowBattery( LowBatteryPower_t *pLowBat ) |
|
{ |
|
// on the 9min, 5 min and 1 min warnings tell the engine to fire off a save |
|
switch( pLowBat->m_nMinutesBatteryLeft ) |
|
{ |
|
case 9: |
|
case 5: |
|
case 1: |
|
Cbuf_AddText( "save LowBattery_AutoSave" ); |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
} |
|
|
|
#endif
|
|
|