mirror of
https://github.com/electronicarts/CnC_Renegade.git
synced 2025-12-16 07:31:40 -05:00
Initial commit of Command & Conquer Renegade source code.
This commit is contained in:
648
Code/WWOnline/WOLNetUtilObserver.cpp
Normal file
648
Code/WWOnline/WOLNetUtilObserver.cpp
Normal file
@@ -0,0 +1,648 @@
|
||||
/*
|
||||
** 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/WOLNetUtilObserver.cpp $
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* PROGRAMMER
|
||||
* $Author: Denzil_l $
|
||||
*
|
||||
* VERSION INFO
|
||||
* $Revision: 25 $
|
||||
* $Modtime: 2/21/02 5:36p $
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
#include <atlbase.h>
|
||||
#include "WOLNetUtilObserver.h"
|
||||
#include "WOLSession.h"
|
||||
#include "WOLLadder.h"
|
||||
#include "WOLServer.h"
|
||||
#include "WOLErrorUtil.h"
|
||||
|
||||
namespace WWOnline {
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::NetUtilObserver
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Constructor
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
NetUtilObserver::NetUtilObserver() :
|
||||
mRefCount(1),
|
||||
mOuter(NULL)
|
||||
{
|
||||
WWDEBUG_SAY(("WOL: NetUtilObserver Instantiated\n"));
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::~NetUtilObserver
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Destructor
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
NetUtilObserver::~NetUtilObserver()
|
||||
{
|
||||
WWDEBUG_SAY(("WOL: NetUtilObserver Destroyed\n"));
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::Init
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Initialize Net utility observer
|
||||
*
|
||||
* INPUTS
|
||||
* WOLSession - Outer session
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void NetUtilObserver::Init(Session& outer)
|
||||
{
|
||||
mOuter = &outer;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* IUnknown::QueryInterface
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
STDMETHODIMP NetUtilObserver::QueryInterface(const IID& iid, void** ppv)
|
||||
{
|
||||
if ((iid == IID_IUnknown) || (iid == WOL::IID_INetUtilEvent))
|
||||
{
|
||||
*ppv = static_cast<WOL::INetUtilEvent*>(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
*ppv = NULL;
|
||||
return E_NOINTERFACE;
|
||||
}
|
||||
|
||||
static_cast<IUnknown*>(*ppv)->AddRef();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* IUnknown::AddRef
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ULONG STDMETHODCALLTYPE NetUtilObserver::AddRef(void)
|
||||
{
|
||||
InterlockedIncrement((LPLONG)&mRefCount);
|
||||
return mRefCount;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* IUnknown::Release
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
* NONE
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
ULONG STDMETHODCALLTYPE NetUtilObserver::Release(void)
|
||||
{
|
||||
InterlockedDecrement((LPLONG)&mRefCount);
|
||||
|
||||
if (mRefCount == 0)
|
||||
{
|
||||
delete this;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return mRefCount;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::OnPing
|
||||
*
|
||||
* DESCRIPTION
|
||||
* Handle ping result response to a ping request
|
||||
*
|
||||
* INPUTS
|
||||
* Result - Error / Status code
|
||||
* Time - Ping time
|
||||
* IP - IP Address
|
||||
* Handle - Ping request handle
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
STDMETHODIMP NetUtilObserver::OnPing(HRESULT result, int time, unsigned long ip, int handle)
|
||||
{
|
||||
if (mOuter == NULL)
|
||||
{
|
||||
WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
|
||||
WWASSERT(mOuter && "Session not initialized");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
WWDEBUG_SAY(("WOLERROR: OnPing '%s'\n", GetNetUtilErrorString(result)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Find the ping request
|
||||
int pingIndex = -1;
|
||||
|
||||
for (unsigned int index = 0; index < mOuter->mPingRequests.size(); index++)
|
||||
{
|
||||
if (mOuter->mPingRequests[index].GetHandle() == handle)
|
||||
{
|
||||
pingIndex = index;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ((pingIndex >= 0) && ((unsigned)pingIndex < mOuter->mPingRequests.size()))
|
||||
{
|
||||
RawPing* ping = &mOuter->mPingRequests[pingIndex];
|
||||
ping->SetTime(time);
|
||||
ping->SetIPAddress(ip);
|
||||
|
||||
WWDEBUG_SAY(("WOL: OnPing %s = %d\n", ping->GetHostAddress(), time));
|
||||
|
||||
// Automatically update ping time for ping servers.
|
||||
mOuter->UpdatePingServerTime(ping->GetHostAddress(), time);
|
||||
|
||||
// Notify others about the ping result.
|
||||
mOuter->NotifyObservers(*ping);
|
||||
|
||||
// Remove ping from request list.
|
||||
std::vector<RawPing>::iterator iter = mOuter->mPingRequests.begin();
|
||||
|
||||
while (iter != mOuter->mPingRequests.end())
|
||||
{
|
||||
if (iter == ping)
|
||||
{
|
||||
mOuter->mPingRequests.erase(iter);
|
||||
mOuter->mPingsPending--;
|
||||
break;
|
||||
}
|
||||
|
||||
iter++;
|
||||
}
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::OnLadderList
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
STDMETHODIMP NetUtilObserver::OnLadderList(HRESULT result, WOL::Ladder* list,
|
||||
int rungCount, long timeStamp, int keyRung)
|
||||
{
|
||||
if (mOuter == NULL)
|
||||
{
|
||||
WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
|
||||
WWASSERT(mOuter && "Session not initialized");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (FAILED(result) || (list == NULL))
|
||||
{
|
||||
WWDEBUG_SAY(("WOLERROR: OnLadderList '%s'\n", GetNetUtilErrorString(result)));
|
||||
|
||||
// Clear the ladder type we requested (in order)
|
||||
if (mOuter->mLadderPending & LadderType_Individual)
|
||||
{
|
||||
mOuter->mLadderPending &= ~LadderType_Individual;
|
||||
}
|
||||
else if (mOuter->mLadderPending & LadderType_Team)
|
||||
{
|
||||
mOuter->mLadderPending &= ~LadderType_Team;
|
||||
}
|
||||
else if (mOuter->mLadderPending & LadderType_Clan)
|
||||
{
|
||||
mOuter->mLadderPending &= ~LadderType_Clan;
|
||||
}
|
||||
else
|
||||
{
|
||||
mOuter->mLadderPending &= ~LADDERTYPE_MASK;
|
||||
}
|
||||
|
||||
// If there are no pending ladders then remove the satisfied requests
|
||||
if ((mOuter->mLadderPending & LADDERTYPE_MASK) == 0)
|
||||
{
|
||||
for (unsigned int count = 0; count < mOuter->mLadderPending; count++)
|
||||
{
|
||||
mOuter->mLadderRequests.pop_front();
|
||||
}
|
||||
|
||||
mOuter->mLadderPending = 0;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Handle ladder information for individual users.
|
||||
//---------------------------------------------------------------------------
|
||||
if (keyRung == -1)
|
||||
{
|
||||
ProcessLadderListResults(list, timeStamp);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Handle ladder search results
|
||||
//---------------------------------------------------------------------------
|
||||
LadderList ladders;
|
||||
|
||||
WOL::Ladder* wolLadder = list;
|
||||
|
||||
while (wolLadder)
|
||||
{
|
||||
RefPtr<LadderData> data = LadderData::Create(*wolLadder, timeStamp);
|
||||
|
||||
if (data.IsValid())
|
||||
{
|
||||
ladders.push_back(data);
|
||||
}
|
||||
|
||||
wolLadder = wolLadder->next;
|
||||
}
|
||||
|
||||
mOuter->NotifyObservers(ladders);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::ProcessLadderListResults
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
* NONE
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
void NetUtilObserver::ProcessLadderListResults(WOL::Ladder* list, long timeStamp)
|
||||
{
|
||||
if (mOuter->mLadderPending)
|
||||
{
|
||||
// Within a given request, ladder results are guaranteed to be in order.
|
||||
WOL::Ladder* wolLadder = list;
|
||||
|
||||
// Extract the ladder request type from the hiword of the SKU
|
||||
LadderType type = (LadderType)(wolLadder->sku & LADDERTYPE_MASK);
|
||||
|
||||
if (type == 0)
|
||||
{
|
||||
type = LadderType_Individual;
|
||||
}
|
||||
|
||||
Session::LadderRequestList::iterator request = mOuter->mLadderRequests.begin();
|
||||
unsigned int ladderCount = 0;
|
||||
|
||||
while (wolLadder)
|
||||
{
|
||||
// Get the name of the user we requested information for.
|
||||
const WCHAR* requestName = wcschr(*request, L':');
|
||||
WWASSERT(requestName != NULL && "Invalid ladder request");
|
||||
requestName++;
|
||||
|
||||
wchar_t ladderName[64];
|
||||
mbstowcs(ladderName, (const char*)wolLadder->login_name, sizeof(wolLadder->login_name));
|
||||
|
||||
WWDEBUG_SAY(("WOL: LadderInfo [%08lX] Requested '%S', Received '%S'\n", type, requestName, ladderName));
|
||||
|
||||
// If the ladder name matches the requested name then there is ladder info available.
|
||||
bool hasLadderData = (wcsicmp(requestName, ladderName) == 0);
|
||||
|
||||
if (type == LadderType_Clan)
|
||||
{
|
||||
RefPtr<SquadData> squad = SquadData::FindByAbbr(requestName);
|
||||
|
||||
if (squad.IsValid())
|
||||
{
|
||||
// Update / create ladder information for this clan
|
||||
RefPtr<LadderData> ladderData = squad->GetLadder();
|
||||
|
||||
if (ladderData.IsValid())
|
||||
{
|
||||
ladderData->UpdateData(*wolLadder, timeStamp);
|
||||
}
|
||||
else if (hasLadderData)
|
||||
{
|
||||
ladderData = LadderData::Create(*wolLadder, timeStamp);
|
||||
WWASSERT(ladderData.IsValid());
|
||||
squad->SetLadder(ladderData);
|
||||
}
|
||||
|
||||
// Notify others about updated clan ladder information
|
||||
NotifyClanLadderUpdate(mOuter->mUsers, squad);
|
||||
NotifyClanLadderUpdate(mOuter->mBuddies, squad);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RefPtr<UserData> user = mOuter->GetUserOrBuddy(requestName);
|
||||
|
||||
// Update users with new ladder information.
|
||||
if (user.IsValid())
|
||||
{
|
||||
RefPtr<LadderData> ladderData = user->GetLadderFromType(type);
|
||||
|
||||
if (ladderData.IsValid())
|
||||
{
|
||||
ladderData->UpdateData(*wolLadder, timeStamp);
|
||||
}
|
||||
else if (hasLadderData)
|
||||
{
|
||||
ladderData = LadderData::Create(*wolLadder, timeStamp);
|
||||
WWASSERT(ladderData.IsValid());
|
||||
|
||||
if (ladderData.IsValid())
|
||||
{
|
||||
user->SetLadderFromType(ladderData, type);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify others that the ladder information for this user has changed.
|
||||
UserEvent event(UserEvent::LadderInfo, user);
|
||||
mOuter->NotifyObservers(event);
|
||||
}
|
||||
}
|
||||
|
||||
// Notify others about the raw ladder information
|
||||
LadderInfoEvent ladderEvent(ladderName, *wolLadder, timeStamp);
|
||||
mOuter->NotifyObservers(ladderEvent);
|
||||
|
||||
request++;
|
||||
ladderCount++;
|
||||
wolLadder = wolLadder->next;
|
||||
}
|
||||
|
||||
// Clear the ladder type we received
|
||||
mOuter->mLadderPending &= ~type;
|
||||
|
||||
// If there are no pending ladders then remove the satisfied requests
|
||||
if ((mOuter->mLadderPending & LADDERTYPE_MASK) == 0)
|
||||
{
|
||||
WWASSERT(ladderCount == mOuter->mLadderPending && "LadderInfo received doesn't match number requested");
|
||||
|
||||
for (unsigned int count = 0; count < mOuter->mLadderPending; ++count)
|
||||
{
|
||||
mOuter->mLadderRequests.pop_front();
|
||||
}
|
||||
|
||||
mOuter->mLadderPending = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NetUtilObserver::NotifyClanLadderUpdate(const UserList& users, const RefPtr<SquadData>& squad)
|
||||
{
|
||||
const unsigned int userCount = users.size();
|
||||
|
||||
for (unsigned int index = 0; index < userCount; ++index)
|
||||
{
|
||||
const RefPtr<UserData>& user = users[index];
|
||||
|
||||
if (user.IsValid() && (user->GetSquadID() == squad->GetID()))
|
||||
{
|
||||
// Notify others that this user received squad information
|
||||
UserEvent event(UserEvent::LadderInfo, user);
|
||||
mOuter->NotifyObservers(event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::OnGameresSent
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
STDMETHODIMP NetUtilObserver::OnGameresSent(HRESULT)
|
||||
{
|
||||
WWDEBUG_SAY(("WOLWARNING: OnGameresSent() not implemented\n"));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::OnNewNick
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
STDMETHODIMP NetUtilObserver::OnNewNick(HRESULT result, LPCSTR message, LPCSTR nickname, LPCSTR password)
|
||||
{
|
||||
if (mOuter == NULL)
|
||||
{
|
||||
WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
|
||||
WWASSERT(mOuter && "Session not initialized");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
WWDEBUG_SAY(("WOLERROR: OnNewNick '%s'\n", GetNetUtilErrorString(result)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
RefPtr<LoginInfo> login;
|
||||
|
||||
if (result == S_OK)
|
||||
{
|
||||
login = LoginInfo::Create(nickname, password, true);
|
||||
}
|
||||
|
||||
NewLoginInfoEvent event(login, message);
|
||||
mOuter->NotifyObservers(event);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::OnAgeCheck
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
STDMETHODIMP NetUtilObserver::OnAgeCheck(HRESULT result, int years, int consent)
|
||||
{
|
||||
if (mOuter == NULL)
|
||||
{
|
||||
WWDEBUG_SAY(("WOLERROR: Session not initialized\n"));
|
||||
WWASSERT(mOuter && "Session not initialized");
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
if (FAILED(result))
|
||||
{
|
||||
WWDEBUG_SAY(("WOLERROR: OnAgeCheck '%s'\n", GetNetUtilErrorString(result)));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
AgeCheckEvent event(years, consent != 0);
|
||||
mOuter->NotifyObservers(event);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::OnWDTState
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
STDMETHODIMP NetUtilObserver::OnWDTState(HRESULT result, unsigned char* , int )
|
||||
{
|
||||
WWDEBUG_SAY(("WOLWARNING: OnWDTState not implemented\n"));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* NAME
|
||||
* NetUtilObserver::OnHighscore
|
||||
*
|
||||
* DESCRIPTION
|
||||
*
|
||||
* INPUTS
|
||||
*
|
||||
* RESULT
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
STDMETHODIMP NetUtilObserver::OnHighscore(HRESULT result, WOL::Highscore* list,
|
||||
int count, long time, int keyRung)
|
||||
{
|
||||
WWDEBUG_SAY(("WOLWARNING: OnHighscore not implemented\n"));
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
} // namespace WWOnline
|
||||
Reference in New Issue
Block a user