/* ** Command & Conquer Renegade(tm) ** Copyright 2025 Electronic Arts Inc. ** ** This program is free software: you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation, either version 3 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program. If not, see . */ /*********************************************************************************************** *** Confidential - Westwood Studios *** *********************************************************************************************** * * * Project Name : Commando * * * * $Archive:: /Commando/Code/Commando/gamespyauthmgr.cpp $* * * * $Author:: Tom_s $* * * * $Modtime:: 2/22/02 5:41p $* * * * $Revision:: 3 $* * * *---------------------------------------------------------------------------------------------* * Functions: * * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ #include "gamespyauthmgr.h" #include "gamespyscchallengeevent.h" #include "playermanager.h" #include "cnetwork.h" #include "gamespyadmin.h" #include "cdkeyauth.h" #include "sctextobj.h" #include "translatedb.h" #include "string_ids.h" // // Class statics // //----------------------------------------------------------------------------- void cGameSpyAuthMgr::Think ( void ) { WWASSERT(cNetwork::I_Am_Server()); WWASSERT(cGameSpyAdmin::Is_Gamespy_Game()); // // Process all the players // WWASSERT(cPlayerManager::Get_Player_Object_List() != NULL); for ( SLNode * player_node = cPlayerManager::Get_Player_Object_List()->Head(); player_node != NULL; player_node = player_node->Next()) { cPlayer * p_player = player_node->Data(); WWASSERT(p_player != NULL); if (!p_player->Is_Alive_And_Kicking()) { continue; } switch (p_player->Get_GameSpy_Auth_State()) { case GAMESPY_AUTH_STATE_INITIAL: { if (cNetwork::I_Am_Client() && p_player->Get_Id() == cNetwork::Get_My_Id()) { // // Do not bother authenticating the server's local client. // p_player->Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_ACCEPTED); } else { // // Challenge this player // StringClass challenge_string; challenge_string.Format("%s", CCDKeyAuth::GenChallenge(8)); p_player->Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_CHALLENGED); p_player->Set_GameSpy_Challenge_String(challenge_string); cGameSpyScChallengeEvent * p_event = new cGameSpyScChallengeEvent; p_event->Init(p_player->Get_Id(), challenge_string); } break; } case GAMESPY_AUTH_STATE_CHALLENGED: { DWORD time_now_ms = TIMEGETTIME(); if (time_now_ms - p_player->Get_GameSpy_Auth_State_Entry_Time_Ms() > CHALLENGE_RESPONSE_TIMEOUT_MS) { // // We challenged this guy and he hasn't responded in the required // time. We are going to have to boot him out. // int player_id = p_player->Get_Id(); WWDEBUG_SAY(("cGameSpyAuthMgr::Think: player %d timed out on challenge response.\n", player_id)); //p_player->Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_REJECTING); //Evict_Player(player_id); cGameSpyAuthMgr::Initiate_Auth_Rejection(player_id); } break; } case GAMESPY_AUTH_STATE_VALIDATING: { // // At this stage I am not implementing any timeout for GameSpy to // authenticate this user. // break; } case GAMESPY_AUTH_STATE_ACCEPTED: { // // The only peaceful, harmonious state. // break; } case GAMESPY_AUTH_STATE_REJECTING: { DWORD time_now_ms = TIMEGETTIME(); if (time_now_ms - p_player->Get_GameSpy_Auth_State_Entry_Time_Ms() > REJECTION_DELAY_MS) { p_player->Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_REJECTED); Evict_Player(p_player->Get_Id()); } break; } case GAMESPY_AUTH_STATE_REJECTED: { // // Do nothing // break; } default: DIE; } } } //----------------------------------------------------------------------------- void cGameSpyAuthMgr::Initiate_Auth_Rejection ( int player_id ) { WWDEBUG_SAY(("cGameSpyAuthMgr::Initiate_Auth_Rejection(%d)\n", player_id)); WWASSERT(cNetwork::I_Am_Server()); WWASSERT(cGameSpyAdmin::Is_Gamespy_Game()); cPlayer * p_player = cPlayerManager::Find_Player(player_id); if (p_player != NULL) { cScTextObj * p_message = new cScTextObj; //p_message->Init(L"CD Authentication failed. Please quit.", TEXT_MESSAGE_PRIVATE, true, HOST_TEXT_SENDER, player_id); p_message->Init(TRANSLATE(IDS_MP_CD_AUTH_FAILED), TEXT_MESSAGE_PRIVATE, true, HOST_TEXT_SENDER, player_id); p_player->Set_GameSpy_Auth_State(GAMESPY_AUTH_STATE_REJECTING); } } //----------------------------------------------------------------------------- void cGameSpyAuthMgr::Evict_Player ( int player_id ) { WWDEBUG_SAY(("cGameSpyAuthMgr::Evict_Player(%d)\n", player_id)); WWASSERT(cNetwork::I_Am_Server()); WWASSERT(cGameSpyAdmin::Is_Gamespy_Game()); // // The behaviour presently is fairly brutal - no feedback to evicted player. // This is fine if he is a cracker, but other cases exist. TODO_AUTH. // cNetwork::Server_Kill_Connection(player_id); cNetwork::Cleanup_After_Client(player_id); } //----------------------------------------------------------------------------- LPCSTR cGameSpyAuthMgr::Describe_Auth_State ( GAMESPY_AUTH_STATE_ENUM state ) { switch (state) { case GAMESPY_AUTH_STATE_INITIAL: return "INITIAL"; case GAMESPY_AUTH_STATE_CHALLENGED: return "CHALLENGED"; case GAMESPY_AUTH_STATE_VALIDATING: return "VALIDATING"; case GAMESPY_AUTH_STATE_ACCEPTED: return "ACCEPTED"; case GAMESPY_AUTH_STATE_REJECTING: return "REJECTING"; case GAMESPY_AUTH_STATE_REJECTED: return "REJECTED"; default: DIE; return "bollocks"; // avoid compiler warning; } }