| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- /*
- ** 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 <http://www.gnu.org/licenses/>.
- */
- /******************************************************************************
- *
- * FILE
- * $Archive: /Commando/Code/WWOnline/PingProfile.cpp $
- *
- * DESCRIPTION
- *
- * PROGRAMMER
- * $Author: Denzil_l $
- *
- * VERSION INFO
- * $Revision: 8 $
- * $Modtime: 1/11/02 5:45p $
- *
- ******************************************************************************/
- #include "always.h"
- #include "PingProfile.h"
- #include <WWOnline\WOLSession.h>
- #include <WWOnline\WOLServer.h>
- #include <WWOnline\WOLString.h>
- #include <WWLib\WideString.h>
- #include <WWDebug\WWDebug.h>
- #include <limits.h>
- #include <math.h>
- using namespace WWOnline;
- static PingProfile gPingProfile;
- /******************************************************************************
- *
- * NAME
- * RecalculatePingProfile
- *
- * DESCRIPTION
- * Calculate ping profile based on the current session ping times.
- *
- * INPUTS
- * Session - WWOnline session
- *
- * RESULT
- * True if ping times are valid
- *
- ******************************************************************************/
- bool RecalculatePingProfile(const RefPtr<Session>& session)
- {
- memset(gPingProfile.Pings, 0xFF, sizeof(gPingProfile.Pings));
- if (session.IsValid())
- {
- const PingServerList& pingers = session->GetPingServerList();
- // The ping profile holds up to eight pings.
- unsigned int count = min<unsigned int>(8, pingers.size());
- // If there aren't any ping servers then fail.
- if (count > 0)
- {
- for (unsigned int index = 0; index < count; index++)
- {
- int pingTime = pingers[index]->GetPingTime();
- // If a ping time is invalid then fail.
- if (pingTime < 0)
- {
- return false;
- }
- // Clamp pings time to a maximum of 1000 ms
- pingTime = min<int>(pingTime, 1000);
- // Scale ping time to from 0-1000 to 0-255
- gPingProfile.Pings[index] = (((unsigned long)pingTime * 255) / 1000);
- }
- return true;
- }
- }
- return false;
- }
- /******************************************************************************
- *
- * NAME
- * GetLocalPingProfile
- *
- * DESCRIPTION
- * Get the ping profile for this client.
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * Profile - Ping profile to for current session.
- *
- ******************************************************************************/
- const PingProfile& GetLocalPingProfile(void)
- {
- return gPingProfile;
- }
- /******************************************************************************
- *
- * NAME
- * ComparePingProfile
- *
- * DESCRIPTION
- * Calcualte the best time between two ping profiles.
- *
- * INPUTS
- * Profile1 - Ping profile
- * Profile2 - Ping profile
- *
- * RESULT
- * Weight - Smallest time between two profiles.
- *
- ******************************************************************************/
- long ComparePingProfile(const PingProfile& ping1, const PingProfile& ping2)
- {
- long minWeight = LONG_MAX;
- for (int index = 0; index < 8; index++)
- {
- long a = ping1.Pings[index];
- long b = ping2.Pings[index];
- long weight = (a * a) + (b * b);
- minWeight = min<long>(weight, minWeight);
- }
- return minWeight;
- }
- /******************************************************************************
- *
- * NAME
- * EncodePingProfile
- *
- * DESCRIPTION
- * Encode the ping profile into a clear text string that can be transmited
- * via chat.
- *
- * INPUTS
- * Pings - Ping profile to encode.
- * Buffer - Buffer to encode pings into.
- *
- * RESULT
- * Length - Number of characters used to encode the profile.
- *
- ******************************************************************************/
- int EncodePingProfile(const PingProfile& pings, char* buffer)
- {
- assert(buffer != NULL);
- if (buffer == NULL)
- {
- return 0;
- }
- char temp[18];
- int count = sprintf(temp, "%02X%02X%02X%02X%02X%02X%02X%02X",
- pings.Pings[0], pings.Pings[1], pings.Pings[2], pings.Pings[3],
- pings.Pings[4], pings.Pings[5], pings.Pings[6], pings.Pings[7]);
- strcat(buffer, temp);
- return count;
- }
- /******************************************************************************
- *
- * NAME
- * DecodePingProfile
- *
- * DESCRIPTION
- * Decode the ping profile from clear text string.
- *
- * INPUTS
- * String - Encode ping profile.
- * Pings - Ping profile structure.
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void DecodePingProfile(const char* buffer, PingProfile& pings)
- {
- if (buffer)
- {
- unsigned long ping[8];
- sscanf(buffer, "%02X%02X%02X%02X%02X%02X%02X%02X",
- &ping[0], &ping[1], &ping[2], &ping[3], &ping[4], &ping[5], &ping[6], &ping[7]);
- pings.Pings[0] = ping[0];
- pings.Pings[1] = ping[1];
- pings.Pings[2] = ping[2];
- pings.Pings[3] = ping[3];
- pings.Pings[4] = ping[4];
- pings.Pings[5] = ping[5];
- pings.Pings[6] = ping[6];
- pings.Pings[7] = ping[7];
- }
- else
- {
- memset(&pings, 0xFF, sizeof(pings));
- }
- }
- /******************************************************************************
- *
- * NAME
- * PingProfileWait::Create
- *
- * DESCRIPTION
- * Create a wait condition to obtain an update ping profile.
- *
- * INPUTS
- * Session - WWOnline session
- *
- * RESULT
- * Wait - Wait condition to process.
- *
- ******************************************************************************/
- RefPtr<PingProfileWait> PingProfileWait::Create(void)
- {
- return new PingProfileWait;
- }
- /******************************************************************************
- *
- * NAME
- * PingProfileWait::PingProfileWait
- *
- * DESCRIPTION
- * Constructor
- *
- * INPUTS
- *
- * RESULT
- *
- ******************************************************************************/
- PingProfileWait::PingProfileWait() :
- SingleWait(WOLSTRING("WOL_PINGPROFILEREQUEST")),
- mCount(0)
- {
- WWDEBUG_SAY(("WOL: PingProfileWait Instantiated\n"));
- mWOLSession = Session::GetInstance(false);
- }
- /******************************************************************************
- *
- * NAME
- * PingProfileWait::~PingProfileWait
- *
- * DESCRIPTION
- * Destructor
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- PingProfileWait::~PingProfileWait()
- {
- WWDEBUG_SAY(("WOL: PingProfileWait Destroyed\n"));
- }
- /******************************************************************************
- *
- * NAME
- * PingProfileWait::WaitBeginning
- *
- * DESCRIPTION
- * Begin wait condition
- *
- * INPUTS
- * NONE
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void PingProfileWait::WaitBeginning(void)
- {
- WWDEBUG_SAY(("WOL: PingProfileWait Beginning\n"));
- if (mWOLSession.IsValid() == false)
- {
- EndWait(Error, WOLSTRING("WOL_NOTINITIALIZED"));
- return;
- }
- const PingServerList& pingers = mWOLSession->GetPingServerList();
- // Handle up to eight servers
- mCount = min<unsigned int>(8, pingers.size());
- if (mCount == 0)
- {
- EndWait(Error, WOLSTRING("WOL_NOPINGSERVER"));
- return;
- }
- Observer<RawPing>::NotifyMe(*mWOLSession);
- bool pingsValid = true;
- for (unsigned int index = 0; index < mCount; index++)
- {
- int pingTime = pingers[index]->GetPingTime();
- // If a ping time is invalid then request it.
- if (pingTime == -1)
- {
- pingsValid = false;
- const char* address = pingers[index]->GetHostAddress();
- mWOLSession->RequestPing(address);
- }
- }
- if (pingsValid)
- {
- RecalculatePingProfile(mWOLSession);
- EndWait(ConditionMet, WOLSTRING("WOL_PINGPROFILERECEIVED"));
- }
- }
- /******************************************************************************
- *
- * NAME
- * PingProfileWait::HandleNotification(RawPing)
- *
- * DESCRIPTION
- *
- * INPUTS
- *
- * RESULT
- * NONE
- *
- ******************************************************************************/
- void PingProfileWait::HandleNotification(RawPing& ping)
- {
- if ((mEndResult == Waiting) && (mCount > 0))
- {
- const char* address = ping.GetHostAddress();
- const PingServerList& pingers = mWOLSession->GetPingServerList();
- for (unsigned int index = 0; index < pingers.size(); index++)
- {
- const char* pinger = pingers[index]->GetHostAddress();
- if (stricmp(address, pinger) == 0)
- {
- WWDEBUG_SAY(("WOL: PingProfileWait received ping for '%s'\n", pingers[index]->GetData().name));
- mCount--;
- break;
- }
- }
- if (mCount == 0)
- {
- RecalculatePingProfile(mWOLSession);
- EndWait(ConditionMet, WOLSTRING("WOL_PINGPROFILERECEIVED"));
- }
- }
- }
|