engine: client: implement steam broker client side

This commit is contained in:
Alibek Omarov
2026-01-15 12:53:45 +05:00
parent 5cb5e76872
commit e5d3f180dc
3 changed files with 215 additions and 33 deletions

View File

@@ -1056,13 +1056,6 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
return;
}
//if( !Q_strcmp( cl_ticket_generator.string, "steam" )
//{
// i = SteamBroker_InitiateGameConnection( buf, sizeof( buf ));
// MSG_WriteBytes( send, buf, i );
// return;
//}
s = ID_GetMD5();
CRC32_Init( &crc );
CRC32_ProcessBuffer( &crc, s, Q_strlen( s ));
@@ -1075,6 +1068,40 @@ static void CL_WriteSteamTicket( sizebuf_t *send )
*(uint32_t*)(cls.steamid + 4) = LittleLong( ((uint32_t*)buf)[5] );
}
void CL_SendGoldSrcConnectPacket( netadr_t adr, int challenge, const void *ticket, size_t ticketlen )
{
const char *name;
sizebuf_t send;
byte send_buf[2048];
char protinfo[MAX_INFO_STRING];
protinfo[0] = 0;
Info_SetValueForKey( protinfo, "prot", "3", sizeof( protinfo )); // steam auth type
Info_SetValueForKeyf( protinfo, "unique", sizeof( protinfo ), "%i", 0xffffffff );
Info_SetValueForKey( protinfo, "raw", "steam", sizeof( protinfo ));
CL_GetCDKey( protinfo, sizeof( protinfo ));
name = Info_ValueForKey( cls.userinfo, "name" );
if( cl_advertise_engine_in_name.value && Q_strnicmp( name, "[Xash3D]", 8 ))
Info_SetValueForKeyf( cls.userinfo, "name", sizeof( cls.userinfo ), "[Xash3D]%s", name );
MSG_Init( &send, "GoldSrcConnect", send_buf, sizeof( send_buf ));
MSG_WriteLong( &send, NET_HEADER_OUTOFBANDPACKET );
MSG_WriteStringf( &send, C2S_CONNECT" %i %i \"%s\" \"%s\"\n",
PROTOCOL_GOLDSRC_VERSION, challenge, protinfo, cls.userinfo );
MSG_SeekToBit( &send, -8, SEEK_CUR ); // rewrite null terminator
if( ticket == NULL )
CL_WriteSteamTicket( &send );
else
MSG_WriteBytes( &send, ticket, ticketlen );
if( MSG_CheckOverflow( &send ))
Con_Printf( S_ERROR "%s: %s overflow!\n", __func__, MSG_GetName( &send ) );
NET_SendPacket( NS_CLIENT, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), adr );
Con_Printf( "Trying to connect with GoldSrc 48 protocol\n" );
}
/*
=======================
CL_SendConnectPacket
@@ -1117,33 +1144,24 @@ static void CL_SendConnectPacket( connprotocol_t proto, int challenge )
Info_SetValueForKey( protinfo, "a", Q_buildarch(), sizeof( protinfo ) );
}
cls.broker_wait = false;
if( proto == PROTO_GOLDSRC )
{
const char *name;
sizebuf_t send;
byte send_buf[2048];
// if the cl_ticket_generator is set to "steam" we need to get ticket
// from steam broker, which is asynchronous process by nature
if( !Q_stricmp( cl_ticket_generator.string, "steam" ))
{
if( SteamBroker_InitiateGameConnection( adr, challenge ))
{
// we are waiting for the broker response...
cls.broker_wait = true;
cls.timestart = Platform_DoubleTime();
return;
}
}
Info_SetValueForKey( protinfo, "prot", "3", sizeof( protinfo )); // steam auth type
Info_SetValueForKeyf( protinfo, "unique", sizeof( protinfo ), "%i", 0xffffffff );
Info_SetValueForKey( protinfo, "raw", "steam", sizeof( protinfo ));
CL_GetCDKey( protinfo, sizeof( protinfo ));
name = Info_ValueForKey( cls.userinfo, "name" );
if( cl_advertise_engine_in_name.value && Q_strnicmp( name, "[Xash3D]", 8 ))
Info_SetValueForKeyf( cls.userinfo, "name", sizeof( cls.userinfo ), "[Xash3D]%s", name );
MSG_Init( &send, "GoldSrcConnect", send_buf, sizeof( send_buf ));
MSG_WriteLong( &send, NET_HEADER_OUTOFBANDPACKET );
MSG_WriteStringf( &send, C2S_CONNECT" %i %i \"%s\" \"%s\"\n",
PROTOCOL_GOLDSRC_VERSION, challenge, protinfo, cls.userinfo );
MSG_SeekToBit( &send, -8, SEEK_CUR ); // rewrite null terminator
CL_WriteSteamTicket( &send );
if( MSG_CheckOverflow( &send ))
Con_Printf( S_ERROR "%s: %s overflow!\n", __func__, MSG_GetName( &send ) );
NET_SendPacket( NS_CLIENT, MSG_GetNumBytesWritten( &send ), MSG_GetData( &send ), adr );
Con_Printf( "Trying to connect with GoldSrc 48 protocol\n" );
CL_SendGoldSrcConnectPacket( adr, challenge, NULL, 0 );
}
else
{
@@ -1320,7 +1338,7 @@ static void CL_CheckForResend( void )
else
CL_SendBandwidthTest( adr, false );
}
else
else if( !cls.broker_wait )
{
Con_Printf( "Connecting to %s... (retry #%i)\n", cls.servername, cls.connect_retry );
CL_SendGetChallenge( adr );
@@ -1686,6 +1704,7 @@ void CL_Disconnect( void )
// send a disconnect message to the server
CL_SendDisconnectMessage( cls.legacymode );
SteamBroker_TerminateGameConnection();
CL_ClearState ();
S_StopBackgroundTrack ();
@@ -2373,8 +2392,21 @@ static void CL_Challenge( const char *c, netadr_t from )
// try to autodetect protocol by challenge response
if( !Q_strcmp( c, S2C_GOLDSRC_CHALLENGE ))
{
cls.legacymode = PROTO_GOLDSRC;
cls.steam_auth = Q_atoi( Cmd_Argv( 2 )) == 3;
if( Cmd_Argc( ) == 5 && cls.steam_auth )
{
// arg 2 auth protocol, we only support steam
// arg 3 if steam is server's steam id
// arg 4 if steam is server's VAC status
cls.server_steamid = strtoull( Cmd_Argv( 3 ), NULL, 10 );
cls.vac2_secure = Q_atoi( Cmd_Argv( 4 ));
}
}
cls.bandwidth_test.challenge = Q_atoi( Cmd_Argv( 1 ));
if( cls.legacymode == PROTO_CURRENT && cl_test_bandwidth.value && !cls.bandwidth_test.passed )
@@ -2537,6 +2569,10 @@ static void CL_ConnectionlessPacket( netadr_t from, sizebuf_t *msg )
Con_Reportf( "%s: %s : %s\n", __func__, NET_AdrToString( from ), c );
// server connection
if( !Q_strcmp( c, "sb_connect" ))
{
SteamBroker_HandlePacket( from, msg );
}
if( !Q_strcmp( c, S2C_GOLDSRC_CONNECTION ) || !Q_strcmp( c, S2C_CONNECTION ))
{
CL_ClientConnect( cls.legacymode, c, from );
@@ -3637,6 +3673,7 @@ void CL_Init( void )
Host_Error( "can't initialize %s: %s\n", libpath, COM_GetLibraryError( ));
ID_Init();
SteamBroker_Init();
cls.build_num = 0;
cls.initialized = true;
@@ -3668,6 +3705,7 @@ void CL_Shutdown( void )
Mobile_Shutdown ();
SCR_Shutdown ();
CL_UnloadProgs ();
SteamBroker_Shutdown();
cls.initialized = false;
// for client-side VGUI support we use other order
@@ -3681,5 +3719,4 @@ void CL_Shutdown( void )
R_Shutdown ();
Con_Shutdown ();
}