#include "pch.h"
#include "MessageCore.h"
#define GETSORC const char* sOrC = m_pDirectPlayClient == 0 ? "S" : "C"
#define DPNGETLOCALHOSTADDRESSES_COMBINED 0x0001
const MsgClsPrio FedMessaging::c_mcpDefault = 1000;
static GUID g_guidApplication;
static bool g_fConnectionDeleted = false;
void DumpMemory()
{
_CrtDumpMemoryLeaks();
}
template< class T > class SafeReleaser
{
public:
SafeReleaser( T* t = 0 )
: m_toRelease( t )
{}
~SafeReleaser()
{
if ( m_toRelease )
m_toRelease->Release();
}
private:
SafeReleaser( const SafeReleaser& );
SafeReleaser& operator = ( const SafeReleaser& );
T* m_toRelease;
};
static const char* g_dpMsgids[] = {
"unknown",
"DPN_MSGID_ADD_PLAYER_TO_GROUP",
"DPN_MSGID_APPLICATION_DESC",
"DPN_MSGID_ASYNC_OP_COMPLETE",
"DPN_MSGID_CLIENT_INFO",
"DPN_MSGID_CONNECT_COMPLETE",
"DPN_MSGID_CREATE_GROUP",
"DPN_MSGID_CREATE_PLAYER",
"DPN_MSGID_DESTROY_GROUP",
"DPN_MSGID_DESTROY_PLAYER",
"DPN_MSGID_ENUM_HOSTS_QUERY",
"DPN_MSGID_ENUM_HOSTS_RESPONSE",
"DPN_MSGID_GROUP_INFO",
"DPN_MSGID_HOST_MIGRATE",
"DPN_MSGID_INDICATE_CONNECT",
"DPN_MSGID_INDICATED_CONNECT_ABORTED",
"DPN_MSGID_PEER_INFO",
"DPN_MSGID_RECEIVE",
"DPN_MSGID_REMOVE_PLAYER_FROM_GROUP",
"DPN_MSGID_RETURN_BUFFER",
"DPN_MSGID_SEND_COMPLETE",
"DPN_MSGID_SERVER_INFO",
"DPN_MSGID_TERMINATE_SESSION",
"DPN_MSGID_CREATE_THREAD",
"DPN_MSGID_DESTROY_THREAD"
};
static const char* getMessageString( DWORD id )
{
DWORD myMsgid = id & 0xFF;
if ( myMsgid > 0x18 )
myMsgid = 0;
return g_dpMsgids[myMsgid];
}
static WCHAR* constChar2Wchar( const char* from )
{
if( from == 0 )
return 0;
WCHAR* to = 0;
int n = MultiByteToWideChar( CP_ACP, 0, from, -1, to, 0 );
if( n == 0 )
return 0;
to = new WCHAR[n];
MultiByteToWideChar( CP_ACP, 0, from, -1, to, n );
return to;
}
static char* wChar2ConstChar( WCHAR* from )
{
if( from == 0 )
return 0;
char* to = 0;
int n = WideCharToMultiByte( CP_ACP, 0, from, -1, to, 0, 0, 0 );
if( n == 0 )
return 0;
to = new char[n];
WideCharToMultiByte( CP_ACP, 0, from, -1, to, n, 0, 0 );
return to;
}
void VerifyMessage(LPBYTE pb, CB cbTotal)
{
#ifndef NO_MSG_CRC
#else
int cMsgs = 0;
CB cbRunning = 0;
while (cbRunning < cbTotal)
{
FEDMESSAGE * pfm = (FEDMESSAGE *) pb;
assert(pfm->cbmsg > 0);
assert(pfm->fmid > 0);
cbRunning += pfm->cbmsg;
pb += pfm->cbmsg;
cMsgs++;
}
assert(cbRunning == cbTotal);
#endif
}
void FedMessaging::EnumHostsCallback ( const DPNMSG_ENUM_HOSTS_RESPONSE& resp )
{
#ifdef DEBUG
char szBuff[128];
const DPN_APPLICATION_DESC* appDesc = resp.pApplicationDescription;
wsprintf(szBuff, "Found a session: {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x} for application {%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
appDesc->guidInstance.Data1, appDesc->guidInstance.Data2,
appDesc->guidInstance.Data3, appDesc->guidInstance.Data4[0],
appDesc->guidInstance.Data4[1], appDesc->guidInstance.Data4[2],
appDesc->guidInstance.Data4[3], appDesc->guidInstance.Data4[4],
appDesc->guidInstance.Data4[5], appDesc->guidInstance.Data4[6],
appDesc->guidInstance.Data4[7],
appDesc->guidApplication.Data1, appDesc->guidApplication.Data2,
appDesc->guidApplication.Data3, appDesc->guidApplication.Data4[0],
appDesc->guidApplication.Data4[1], appDesc->guidApplication.Data4[2],
appDesc->guidApplication.Data4[3], appDesc->guidApplication.Data4[4],
appDesc->guidApplication.Data4[5], appDesc->guidApplication.Data4[6],
appDesc->guidApplication.Data4[7]);
debugf(szBuff);
#endif
if ( IsEqualGUID( resp.pApplicationDescription->guidApplication, g_guidApplication ) )
{
FMSessionDesc fmSession( resp.pApplicationDescription );
m_guidInstance = resp.pApplicationDescription->guidInstance;
if ( m_pHostAddress != 0 )
m_pHostAddress->Release();
if ( m_pDeviceAddress != 0)
m_pDeviceAddress->Release();
ZSucceeded( resp.pAddressSender->QueryInterface( IID_IDirectPlay8Address,
(LPVOID*) &m_pHostAddress ) );
ZSucceeded( resp.pAddressDevice->QueryInterface( IID_IDirectPlay8Address,
(LPVOID*) &m_pDeviceAddress ) ); if ( m_fSessionCallback )
m_pfmSite->OnSessionFound( this, &fmSession );
}
}
HRESULT WINAPI DPlayMsgHandler( PVOID pvUserContext,
DWORD dwMessageId,
PVOID pMsgBuffer )
{
return ((FedMessaging*) pvUserContext)->MsgHandler( dwMessageId, pMsgBuffer );
}
FedMessaging::FedMessaging(IFedMessagingSite * pfmSite) :
m_pDirectPlayClient( 0 ),
m_pDirectPlayServer( 0 ),
m_cMsgsOdometer(0),
m_cBytesOdometer(0),
m_pbFMNext(m_rgbbuffOutPacket),
m_pfmSite(pfmSite),
m_fConnected(false),
m_precipDefault(NULL),
m_fmGuaranteedDefault(FM_GUARANTEED),
m_pcnxnServer(NULL),
m_pgrpEveryone(NULL),
m_pcnxnMe(NULL),
m_fSecondaryOut(false),
m_pbFMNextT(m_rgbbuffSecondaryOutPacket),
m_guidInstance(GUID_NULL),
m_guidApplication(GUID_NULL),
m_timeMsgLast(Time::Now()),
m_pHostAddress(NULL), m_pDeviceAddress(NULL) {
assert (pfmSite);
InitializeCriticalSection( &m_csMsgList );
}
FedMessaging::~FedMessaging()
{
Shutdown();
DeleteCriticalSection( &m_csMsgList );
}
void FedMessaging::SetDefaultRecipient(CFMRecipient * precip, FMGuaranteed fmg)
{
assert(0 == CbUsedSpaceInOutbox()); m_precipDefault = precip;
m_fmGuaranteedDefault = fmg;
}
CFMRecipient * FedMessaging::GetDefaultRecipient(FMGuaranteed * pfmg)
{
if (pfmg)
*pfmg = m_fmGuaranteedDefault;
return m_precipDefault;
}
void * FedMessaging::PFedMsgCreate(bool fQueueMsg, BYTE * pbFMBuff, FEDMSGID fmid, CB cbfm, ...)
{
va_list vl;
BYTE * pBlobSrc, * pBlobDst;
BYTE * pbFM;
assert (IsConnected());
StartOver: va_start(vl, cbfm); if (fQueueMsg && (cbfm > CbFreeSpaceInOutbox()))
SendToDefault(FM_FLUSH);
pbFM = fQueueMsg ? m_pbFMNext :
(pbFMBuff ? pbFMBuff : m_rgbbuffAlloc);
((FEDMESSAGE*)pbFM)->fmid = fmid;
pBlobDst = pbFM + cbfm; IB * pib = (IB*)(pbFM + sizeof(FEDMESSAGE)); CB * pcb;
CB cbBlob;
while (FM_END_VAR_PARMS != (pBlobSrc = va_arg(vl, BYTE *)))
{
pcb = pib + 1;
*pib = pBlobDst - pbFM;
*pcb = 0;
BYTE * pbLastNonSpace; cbBlob = va_arg(vl, CB);
if (CB_ZTS == cbBlob)
{
if (pBlobSrc) {
if (*pBlobSrc) {
int cbLen = lstrlen((char *)(pBlobSrc));
pbLastNonSpace = pBlobSrc + cbLen - 1;
while (cbLen > 0 && ' ' == *pbLastNonSpace)
{
pbLastNonSpace--;
cbLen--;
}
if (fQueueMsg && (pBlobDst + cbLen > BuffOut() + GetBuffOutSize()))
{
SendToDefault(FM_FLUSH);
goto StartOver;
}
CopyMemory(pBlobDst, pBlobSrc, cbLen);
*(pBlobDst + cbLen++) = 0;
pBlobDst += cbLen;
*pcb = cbLen;
}
}
}
else {
if (fQueueMsg && (pBlobDst + cbBlob > BuffOut() + GetBuffOutSize()))
{
SendToDefault(FM_FLUSH);
goto StartOver;
}
if (pBlobSrc)
CopyMemory(pBlobDst, pBlobSrc, cbBlob);
pBlobDst += cbBlob;
*pcb = cbBlob;
}
pib += 2; } va_end(vl);
((FEDMESSAGE *)pbFM)->cbmsg = pBlobDst - pbFM;
if (fQueueMsg || !pbFMBuff) {
if (fQueueMsg)
{
m_pbFMNext = pBlobDst;
assert(CbFreeSpaceInOutbox() <= GetBuffOutSize());
}
else {
assert (((FEDMESSAGE *)pbFM)->cbmsg <= sizeof(m_rgbbuffAlloc));
BYTE * pbMsg = (BYTE *) GlobalAllocPtr(GMEM_MOVEABLE, ((FEDMESSAGE *)pbFM)->cbmsg);
CopyMemory(pbMsg, pbFM, ((FEDMESSAGE *)pbFM)->cbmsg);
pbFM = pbMsg;
}
}
assert(((FEDMESSAGE*)pbFM)->cbmsg > 0 && ((FEDMESSAGE*)pbFM)->fmid > 0);
return pbFM;
}
FEDMESSAGE * FedMessaging::PfmGetNext(FEDMESSAGE * pfm)
{
BYTE * pfmNext = (BYTE*)pfm + pfm->cbmsg;
assert( pfmNext >= BuffIn() );
if (pfmNext - BuffIn() >= (int) PacketSize()) {
if (m_fConnected) assert((BYTE*)pfmNext == BuffIn() + PacketSize()); return NULL;
}
return (FEDMESSAGE *)pfmNext;
}
void FedMessaging::QueueExistingMsg(const FEDMESSAGE * pfm)
{
assert(m_fConnected);
assert(pfm->cbmsg > 0);
assert(pfm->fmid > 0);
if (CbFreeSpaceInOutbox() < pfm->cbmsg) {
assert(m_precipDefault);
SendToDefault(FM_FLUSH);
}
CopyMemory(m_pbFMNext, pfm, pfm->cbmsg);
m_pbFMNext += pfm->cbmsg;
assert(CbFreeSpaceInOutbox() <= GetBuffOutSize());
}
HRESULT FedMessaging::GenericSend(CFMRecipient * precip, const void * pv, CB cb, FMGuaranteed fmg)
{
DWORD dwFlags, dwTimeout;
HRESULT hr;
bool fGuaranteed = FM_GUARANTEED == fmg;
static DWORD s_guarenteedFlags = DPNSEND_GUARANTEED | DPNSEND_PRIORITY_HIGH | DPNSEND_COALESCE;
static DWORD s_normalFlags = DPNSEND_NOCOMPLETE | DPNSEND_NONSEQUENTIAL;
dwFlags = fGuaranteed ? s_guarenteedFlags : s_normalFlags;
dwTimeout = (fGuaranteed ? 0 : 500); #ifdef DUMPMSGS
GETSORC;
debugf("*** (FM=%8x %s) Sending message to %8x, %8x flags = 0x%x, "
"Timeout = %4d, length = %4d, thread = 0x%x\n", this, sOrC, precip->GetID(), this, dwFlags,
dwTimeout, cb, GetCurrentThreadId());
#endif
#ifndef NO_MSG_CRC
char crcbuff[sizeof(m_rgbbuffOutPacket)];
CopyMemory(crcbuff, pv, cb);
int crc = MemoryCRC(crcbuff, cb);
*(int*)(crcbuff + cb) = crc;
pv = crcbuff;
cb += sizeof(crc);
#endif
DPN_BUFFER_DESC sendBufDesc;
sendBufDesc.dwBufferSize = cb;
sendBufDesc.pBufferData = (BYTE*) pv;
DPNHANDLE handle;
static CTempTimer tt("in dplay Send", 0.05f);
tt.Start();
if ( m_pDirectPlayClient )
{
hr = m_pDirectPlayClient->Send( &sendBufDesc, 1, dwTimeout, this, &handle, dwFlags );
}
else
{
hr = m_pDirectPlayServer->SendTo( precip->GetID(), &sendBufDesc, 1, dwTimeout, this, &handle, dwFlags );
}
tt.Stop("dpidTo=%8x, guaranteed=%d, hr=%x, 1st message (fmid)=%u", precip->GetID(), fGuaranteed, hr,
((FEDMESSAGE*)pv)->fmid);
m_pfmSite->OnMessageSent(this, precip, pv, cb, fmg);
#ifdef DEBUG
if ( ! ( hr == DPNSUCCESS_PENDING || hr == S_OK ) )
{
debugf("Return code of Send was 0x%x to player with dpid %8x.\n",
hr, precip->GetID());
}
#endif return hr;
}
int FedMessaging::SendToDefault(FMFlush fmf)
{
return SendMessages(NULL, m_fmGuaranteedDefault, fmf);
}
int FedMessaging::SendMessages(CFMRecipient * precip, FMGuaranteed fmg, FMFlush fmf)
{
assert(m_fConnected);
assert (precip || m_precipDefault);
if (precip)
{
m_precipDefault = NULL;
}
else
{
precip = m_precipDefault;
fmg = m_fmGuaranteedDefault;
}
HRESULT hr;
hr = S_OK;
int cbToSend = CbUsedSpaceInOutbox();
assert(cbToSend <= GetBuffOutSize());
if (cbToSend > 0)
{
VerifyMessage(BuffOut(), cbToSend);
hr = GenericSend(precip, BuffOut(), cbToSend, fmg);
m_cMsgsOdometer++;
m_cBytesOdometer += cbToSend;
if (FM_FLUSH == fmf)
m_pbFMNext = BuffOut();
}
return cbToSend;
}
Time FedMessaging::CheckOdometer(float& flDTime, int& cMsgsOdometer, int& cBytesOdometer)
{
Time timeNow = Time::Now ();
flDTime = timeNow - m_timeOdometerStart;
cMsgsOdometer = m_cMsgsOdometer;
cBytesOdometer = m_cBytesOdometer;
m_timeOdometerStart = timeNow;
m_cMsgsOdometer = 0;
m_cBytesOdometer = 0;
return timeNow;
}
HRESULT FedMessaging::OnSysMessage( const DPlayMsg& msg )
{
static CTempTimer timerSysMsg("spent in OnSysMessage()", .01f);
timerSysMsg.Start();
Time timeNow = Time::Now();
m_pfmSite->OnSysMessage(this);
GETSORC;
if( msg.dwType == DPN_MSGID_CREATE_PLAYER )
{
static CTempTimer tt( "handling DPN_MSGID_CREATE_PLAYER", .01f);
tt.Start();
DPNMSG_CREATE_PLAYER* lp = (DPNMSG_CREATE_PLAYER*) msg.pData;
if ( lp->pvPlayerContext == (void*) 1 )
{
m_pcnxnMe = new CFMConnection( this, "<Server connection>", lp->dpnidPlayer );
tt.Stop();
return DPN_OK;
}
assert( m_pDirectPlayServer != 0 );
DPN_PLAYER_INFO* pPlayerInfo = 0;
DWORD dwSize = 0;
HRESULT hr = m_pDirectPlayServer->GetClientInfo( lp->dpnidPlayer, pPlayerInfo,
&dwSize, 0);
assert( hr == DPNERR_BUFFERTOOSMALL );
pPlayerInfo = (DPN_PLAYER_INFO*) new BYTE[dwSize];
ZeroMemory( pPlayerInfo, dwSize );
pPlayerInfo->dwSize = sizeof( DPN_PLAYER_INFO );
hr = m_pDirectPlayServer->GetClientInfo( lp->dpnidPlayer, pPlayerInfo,
&dwSize, 0 );
if ( hr != DPN_OK )
{
debugf( "m_pDirectPlayServer->GetClientInfo failed\n");
return hr;
}
char* name = wChar2ConstChar( pPlayerInfo->pwszName );
CFMConnection * pcnxn = CreateConnection( name, lp->dpnidPlayer );
char szRemoteAddress[16];
GetIPAddress( *pcnxn, szRemoteAddress );
debugf(" ip=%s\n", szRemoteAddress );
delete[] name;
delete[] pPlayerInfo;
tt.Stop();
}
else if( msg.dwType == DPN_MSGID_CREATE_GROUP )
{
}
else if ( msg.dwType == DPN_MSGID_DESTROY_PLAYER )
{
static CTempTimer tt("handling DPN_MSGID_DESTROY_PLAYER", .01f);
tt.Start();
DPNMSG_DESTROY_PLAYER* lp = (DPNMSG_DESTROY_PLAYER *) msg.pData;
CFMConnection * pcnxn = GetConnectionFromDpid( lp->dpnidPlayer );
if ( pcnxn && ( m_pcnxnMe == pcnxn || m_pcnxnServer == pcnxn) )
{
m_pfmSite->OnSessionLost(this);
Shutdown();
}
else if (pcnxn)
{
DeleteConnection(*pcnxn);
}
tt.Stop();
}
else if ( msg.dwType == DPN_MSGID_SEND_COMPLETE )
{
static CTempTimer tt("handling DPN_MSGID_SEND_COMPLETE", .01f);
tt.Start();
DPNMSG_SEND_COMPLETE* lp = (DPNMSG_SEND_COMPLETE *) msg.pData;
CFMRecipient * prcp = NULL;
DPID to;
HandleIDMap::iterator it = m_handleMap.find( lp->hAsyncOp );
if ( it != m_handleMap.end() )
{
to = it->second;
m_handleMap.erase( it );
prcp = GetGroupFromDpid( to );
}
if ( !prcp )
{
CFMConnection * pcnxn = GetConnectionFromDpid( to );
if ( pcnxn )
{
prcp = pcnxn;
if ( DPN_OK == lp->hResultCode )
pcnxn->SetLastComplete( timeNow.clock() );
}
}
if ( DPN_OK != lp->hResultCode )
{
if ( prcp )
m_pfmSite->OnMessageNAK( this, lp->dwSendTime, prcp );
}
tt.Stop();
}
else if ( msg.dwType == DPN_MSGID_ADD_PLAYER_TO_GROUP )
{
DPNMSG_ADD_PLAYER_TO_GROUP* lp = (DPNMSG_ADD_PLAYER_TO_GROUP*) msg.pData;
CFMGroup * pgrp = GetGroupFromDpid( lp->dpnidGroup );
CFMConnection * pcnxn = GetConnectionFromDpid(lp->dpnidPlayer);
if ( pgrp )
pgrp->PlayerAdded( pcnxn );
}
else if ( msg.dwType == DPN_MSGID_REMOVE_PLAYER_FROM_GROUP )
{
DPNMSG_REMOVE_PLAYER_FROM_GROUP* lp = (DPNMSG_REMOVE_PLAYER_FROM_GROUP*) msg.pData;
CFMGroup * pgrp = GetGroupFromDpid( lp->dpnidGroup );
CFMConnection * pcnxn = GetConnectionFromDpid(lp->dpnidPlayer);
if ( pgrp )
pgrp->PlayerDeleted( pcnxn );
}
else if( msg.dwType == DPN_MSGID_TERMINATE_SESSION )
{
m_pfmSite->OnSessionLost(this);
}
timerSysMsg.Stop();
return(S_OK);
}
template< class T > T* allocAndCopyStruct( const T& data )
{
return new T(data);
}
HRESULT FedMessaging::MsgHandler( DWORD dwMessageId, PVOID pMsgBuffer )
{
DPlayMsg msg;
msg.dwType = dwMessageId;
msg.pData = 0;
HRESULT result = DPN_OK;
const char* sOrC = m_pDirectPlayClient == 0 ? "S" : "C";
switch( dwMessageId )
{
case DPN_MSGID_CREATE_PLAYER:
msg.pData = allocAndCopyStruct( *((DPNMSG_CREATE_PLAYER*) pMsgBuffer) );
break;
case DPN_MSGID_CREATE_GROUP:
msg.pData = allocAndCopyStruct( *((DPNMSG_CREATE_GROUP*) pMsgBuffer) );
{
DPNMSG_CREATE_GROUP* lp = (DPNMSG_CREATE_GROUP*) msg.pData;
CFMGroup* grp = (CFMGroup*) lp->pvGroupContext;
grp->m_dpid = lp->dpnidGroup;
}
break;
case DPN_MSGID_DESTROY_PLAYER:
msg.pData = allocAndCopyStruct( *((DPNMSG_DESTROY_PLAYER*) pMsgBuffer) );
break;
case DPN_MSGID_SEND_COMPLETE:
msg.pData = allocAndCopyStruct( *((DPNMSG_SEND_COMPLETE*) pMsgBuffer) );
break;
case DPN_MSGID_ADD_PLAYER_TO_GROUP:
msg.pData = allocAndCopyStruct( *((DPNMSG_ADD_PLAYER_TO_GROUP*) pMsgBuffer) );
break;
case DPN_MSGID_REMOVE_PLAYER_FROM_GROUP:
msg.pData = allocAndCopyStruct( *((DPNMSG_REMOVE_PLAYER_FROM_GROUP*) pMsgBuffer) );
break;
case DPN_MSGID_TERMINATE_SESSION:
msg.pData = allocAndCopyStruct( *((DPNMSG_TERMINATE_SESSION*) pMsgBuffer) );
break;
case DPN_MSGID_RECEIVE:
msg.pData = allocAndCopyStruct( *((DPNMSG_RECEIVE*) pMsgBuffer ) );
result = DPNSUCCESS_PENDING;
break;
case DPN_MSGID_ENUM_HOSTS_RESPONSE:
EnumHostsCallback( *((DPNMSG_ENUM_HOSTS_RESPONSE*) pMsgBuffer) );
return DPN_OK;
default:
return DPN_OK;
}
EnterCriticalSection( &m_csMsgList );
m_msgList.push_back( msg );
LeaveCriticalSection( &m_csMsgList );
return result;
}
HRESULT FedMessaging::ReceiveMessages()
{
while ( IsConnected() )
{
DPlayMsg msg;
int msgCount;
EnterCriticalSection( &m_csMsgList );
msgCount = m_msgList.size();
if ( msgCount > 0 )
{
msg = m_msgList.front();
m_msgList.pop_front();
}
LeaveCriticalSection( &m_csMsgList );
GETSORC;
if ( msgCount != 0 )
{
if ( msg.dwType != DPN_MSGID_RECEIVE )
{
OnSysMessage( msg );
}
else
{
DPNMSG_RECEIVE* p_dpMsg = (DPNMSG_RECEIVE*) msg.pData;
CFMConnection * pcnxnFrom = GetConnectionFromDpid( p_dpMsg->dpnidSender );
if ( pcnxnFrom != 0 ) {
m_rgbbuffInPacket = p_dpMsg->pReceiveData;
FEDMESSAGE* pfm = (FEDMESSAGE *) p_dpMsg->pReceiveData;
m_dwcbPacket = p_dpMsg->dwReceiveDataSize;
int cMsgs = 0;
#ifndef NO_MSG_CRC
int crc = MemoryCRC(m_rgbbuffInPacket, PacketSize());
if (crc == *(int*)(m_rgbbuffInPacket + PacketSize()))
{
#endif
static CTempTimer tt("spent looping through message queue", .1f);
tt.Start();
g_fConnectionDeleted = false;
CB cb = pfm->cbmsg;
FEDMSGID id = pfm->fmid;
while (pfm && !g_fConnectionDeleted)
{
if(pfm->fmid > 0 && pfm->cbmsg >= sizeof(FEDMESSAGE) && pfm->cbmsg <= PacketSize())
{
m_pfmSite->OnAppMessage(this, *pcnxnFrom, pfm);
pfm = PfmGetNext(pfm);
cMsgs++;
}
else
{
debugf("HACKER?? message from %s(%8x).\ncbmsg=%d, fmid=%d, total packet size=%d\n",
pcnxnFrom ? pcnxnFrom->GetName() : "<unknown>", p_dpMsg->dpnidSender,
cb, id, m_dwcbPacket );
#ifndef NO_MSG_CRC
m_pfmSite->OnBadCRC(this, *pcnxnFrom, m_rgbbuffInPacket, m_dwcbPacket);
#endif
}
}
#ifndef NO_MSG_CRC
}
else
{
m_pfmSite->OnBadCRC(this, *pcnxnFrom, m_rgbbuffInPacket, m_dwcbPacket);
}
#endif
}
else
{
}
if ( m_pDirectPlayClient != 0 )
{
m_pDirectPlayClient->ReturnBuffer( p_dpMsg->hBufferHandle, 0 );
}
else
{
if (m_pDirectPlayServer)
m_pDirectPlayServer->ReturnBuffer( p_dpMsg->hBufferHandle, 0 );
}
m_timeMsgLast = Time::Now();
}
delete msg.pData;
}
else
{
break; }
}
return DPN_OK;
}
HRESULT FedMessaging::ConnectToDPAddress(LPVOID pvAddress)
{
assert(0);
return DPN_OK;
}
HRESULT FedMessaging::Connect(const char * szAddress)
{
assert(0);
return DPN_OK;
}
bool FedMessaging::KillSvr()
{
PROCESS_INFORMATION pi;
STARTUPINFO si;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
Shutdown();
BOOL fCreated = CreateProcess(NULL, "KillSvr.exe", NULL, NULL, FALSE,
CREATE_NO_WINDOW, NULL, NULL, &si, &pi);
if (fCreated)
{
DWORD exitcode = STILL_ACTIVE;
int i = 0;
const int cRetries = 50; while (STILL_ACTIVE == exitcode && i > cRetries)
{
GetExitCodeProcess(pi.hProcess, &exitcode);
Sleep(100);
i++;
}
if (i > cRetries)
fCreated = false;
else
debugf("Slept (100ms) %d times waiting for killsvr\n", i);
Sleep(1000); }
else
{
LPVOID lpMsgBuf;
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf,
0,
NULL
);
m_pfmSite->OnMessageBox(this, (LPCTSTR)lpMsgBuf, "Couldn't run killsvr.exe.", MB_OK | MB_ICONINFORMATION);
LocalFree( lpMsgBuf );
}
return !!fCreated;
}
HRESULT FedMessaging::InitDPlayClient()
{
HRESULT hr = E_FAIL;
assert( !m_fConnected);
assert( !m_pDirectPlayClient );
assert( !m_pDirectPlayServer );
m_pfmSite->OnPreCreate(this);
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Client, NULL,
CLSCTX_INPROC_SERVER, IID_IDirectPlay8Client,
(LPVOID*) &m_pDirectPlayClient ) ) )
{
m_pfmSite->OnMessageBox(this, "Failed to Create DirectPlayClient in DirectX 8/9", "Allegiance", MB_OK);
return hr;
}
const DWORD dwInitFlags = 0;
if( FAILED( hr = m_pDirectPlayClient->Initialize( this, DPlayMsgHandler, dwInitFlags ) ) )
{
m_pfmSite->OnMessageBox(this, "Failed to initialize DirectX 8/9", "Allegiance", MB_OK);
return hr;
}
return S_OK;
}
HRESULT FedMessaging::InitDPlayServer()
{
HRESULT hr = E_FAIL;
assert( !m_fConnected);
assert( !m_pDirectPlayClient );
assert( !m_pDirectPlayServer );
m_pfmSite->OnPreCreate(this);
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Server, NULL,
CLSCTX_INPROC_SERVER, IID_IDirectPlay8Server,
(LPVOID*) &m_pDirectPlayServer ) ) )
{
m_pfmSite->OnMessageBox(this, "Failed to Create DirectPlaySever in DirectX 8/9", "Allegiance", MB_OK);
return hr;
}
const DWORD dwInitFlags = 0;
if( FAILED( hr = m_pDirectPlayServer->Initialize( this, DPlayMsgHandler, dwInitFlags ) ) )
{
m_pfmSite->OnMessageBox(this, "Failed to initialize DirectX 8/9", "Allegiance", MB_OK);
return hr;
}
return S_OK;
}
HRESULT FedMessaging::HostSession( GUID guidApplication, bool fKeepAlive, HANDLE hEventServer, bool fProtocol, DWORD dwPort ) {
HRESULT hr = E_FAIL;
assert(!m_fConnected);
if (false) {
if (!KillSvr())
{
m_pfmSite->OnMessageBox(this, "Failed to successfully run killsvr.exe (or it failed to complete), which kills dplaysvr.exe. If we can't veryify that dplaysvr starts out clean, we're in for trouble, so I'm aborting.",
"Allegiance", MB_OK);
return E_FAIL;
}
}
if( m_pDirectPlayServer == 0 )
{
hr = InitDPlayServer();
if ( FAILED(hr) )
return hr;
}
DPN_APPLICATION_DESC dpnAppDesc;
IDirectPlay8Address* pDP8AddressLocal = 0;
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
CLSCTX_ALL, IID_IDirectPlay8Address,
(LPVOID*) &pDP8AddressLocal ) ) )
{
m_pfmSite->OnMessageBox( this, "Failed to create DPlay server local address", "Allegiance", MB_OK );
return hr;
}
SafeReleaser<IDirectPlay8Address> r1( pDP8AddressLocal );
if( FAILED( hr = pDP8AddressLocal->SetSP( &CLSID_DP8SP_TCPIP ) ) )
{
m_pfmSite->OnMessageBox( this, "Failed to create DPlay server local SP", "Allegiance", MB_OK );
return hr;
}
if( dwPort )
if(FAILED(hr = pDP8AddressLocal->AddComponent(DPNA_KEY_PORT, &dwPort, sizeof(DWORD), DPNA_DATATYPE_DWORD)))
{
m_pfmSite->OnMessageBox( this, "Failed to set DPlay server port", "Allegiance", MB_OK );
return hr;
}
ZeroMemory( &dpnAppDesc, sizeof( DPN_APPLICATION_DESC ) );
dpnAppDesc.dwSize = sizeof( DPN_APPLICATION_DESC );
dpnAppDesc.dwFlags = DPNSESSION_CLIENT_SERVER;
dpnAppDesc.guidApplication = guidApplication;
dpnAppDesc.pwszSessionName = L"FedSrv";
dpnAppDesc.dwMaxPlayers = 0;
hr = m_pDirectPlayServer->Host( &dpnAppDesc, &pDP8AddressLocal, 1, NULL, NULL, (void *) 1, 0 );
m_guidApplication = guidApplication;
m_fConnected = true;
ZVerify(m_pgrpEveryone = CreateGroup("Everyone"));
ResetOutBuffer();
if ( FAILED(hr) )
Shutdown();
return hr;
}
void FedMessaging::Shutdown()
{
static CTempTimer tt("In FedMessaging::Shutdown", 0.1f);
tt.Start();
if ( m_pDirectPlayClient )
{
m_pDirectPlayClient->Close(0);
m_pDirectPlayClient->Release();
m_pDirectPlayClient = NULL;
}
if ( m_pDirectPlayServer )
{
m_pDirectPlayServer->Close(0);
m_pDirectPlayServer->Release();
m_pDirectPlayServer = NULL;
}
if( m_pcnxnMe )
{
delete m_pcnxnMe;
m_pcnxnMe = NULL;
}
if (m_pcnxnServer)
{
delete m_pcnxnServer;
m_pcnxnServer = NULL;
}
ResetOutBuffer();
m_listCnxns.SetEmpty();
m_cnxnsMap.clear();
m_groupMap.clear();
m_msgList.clear();
m_guidInstance = GUID_NULL;
m_fConnected = false;
tt.Stop();
}
HRESULT FedMessaging::JoinSession(GUID guidApplication, const char * szServer, const char * szCharName, DWORD dwPort) {
HRESULT hr = E_FAIL;
Time timeStart = Time::Now();
m_fSessionCallback = false; hr = InitDPlayClient();
if ( FAILED(hr) )
return hr;
hr = EnumHostsInternal(guidApplication, szServer, dwPort);
if ( FAILED(hr) )
return hr;
int i = 0;
while(IsEqualGUID(GUID_NULL, m_guidInstance) && i < 150) {
Sleep(100); i++;
}
if (IsEqualGUID(GUID_NULL, m_guidInstance))
hr = E_FAIL; else
hr = JoinSessionInstance( guidApplication, m_guidInstance, m_pHostAddress, m_pDeviceAddress, szCharName);
ResetOutBuffer();
if (FAILED(hr))
{
m_pDirectPlayClient->CancelAsyncOperation(NULL, DPNCANCEL_ENUM); Shutdown();
}
return hr;
}
HRESULT FedMessaging::JoinSessionInstance( GUID guidApplication, GUID guidInstance, IDirectPlay8Address* addr, IDirectPlay8Address* device, const char * szName) {
if ( !m_pDirectPlayClient ) InitDPlayClient(); assert (m_pDirectPlayClient );
if ( !m_pDirectPlayClient )
return E_FAIL;
DPN_APPLICATION_DESC dpnAppDesc;
ZeroMemory( &dpnAppDesc, sizeof( DPN_APPLICATION_DESC ) );
dpnAppDesc.dwSize = sizeof( DPN_APPLICATION_DESC );
dpnAppDesc.guidApplication = guidApplication;
dpnAppDesc.guidInstance = guidInstance;
addr->AddRef();
device->AddRef();
SafeReleaser<IDirectPlay8Address> r1( addr );
DPN_PLAYER_INFO playerInfo;
ZeroMemory( &playerInfo, sizeof( DPN_PLAYER_INFO ) );
playerInfo.dwSize = sizeof( DPN_PLAYER_INFO );
playerInfo.dwInfoFlags = DPNINFO_NAME;
playerInfo.pwszName = constChar2Wchar( szName );
HRESULT hr = m_pDirectPlayClient->SetClientInfo( &playerInfo, 0, 0 , DPNSETCLIENTINFO_SYNC );
if (FAILED(hr))
return hr;
hr = m_pDirectPlayClient->Connect( &dpnAppDesc, addr, device, NULL, NULL, NULL, 0, NULL, NULL, DPNOP_SYNC ); delete[] playerInfo.pwszName;
if (FAILED(hr))
return hr;
m_guidInstance = guidInstance;
m_fConnected = true;
m_pcnxnMe = new CFMConnection( this, szName, 0);
m_pcnxnServer = new CFMConnection(this, "Server", 1);
return hr;
}
HRESULT FedMessaging::JoinSessionInstance(GUID guidInstance, const char * szName)
{
return JoinSessionInstance( GUID_NULL, m_guidInstance, m_pHostAddress, m_pDeviceAddress, szName);
}
CFMConnection * FedMessaging::GetConnectionFromDpid(DPID dpid)
{
CFMConnection * pcnxn = NULL;
if ( m_pcnxnMe && ( m_pcnxnMe->GetDPID() == dpid ) )
{
return m_pcnxnMe;
}
if ( m_pcnxnServer && ( m_pcnxnServer->GetDPID() == dpid) )
{
return m_pcnxnServer;
}
ConnectionMap::iterator it = m_cnxnsMap.find( dpid );
if ( it != m_cnxnsMap.end() )
return it->second;
return 0;
}
CFMGroup * FedMessaging::GetGroupFromDpid(DPID dpid)
{
GroupMap::iterator it = m_groupMap.find( dpid );
if ( it != m_groupMap.end() )
return it->second;
return 0;
}
HRESULT FedMessaging::GetIPAddress(CFMConnection & cnxn, char szRemoteAddress[16])
{
IDirectPlay8Address* pAddress;
if (m_pDirectPlayServer)
ZSucceeded( m_pDirectPlayServer->GetClientAddress( cnxn.GetDPID(), &pAddress, 0 ) );
if (m_pDirectPlayClient)
ZSucceeded( m_pDirectPlayClient->GetServerAddress(&pAddress, 0 ) );
WCHAR add[200];
DWORD cnt = 200;
DWORD type;
HRESULT hr = pAddress->GetComponentByName( DPNA_KEY_HOSTNAME, (void*)add, &cnt, &type );
if ( FAILED( hr ) )
{
strcpy( szRemoteAddress, "0.0.0.0" );
}
else
{
char* aadd = wChar2ConstChar( add );
strcpy( szRemoteAddress, aadd );
delete[] aadd;
}
pAddress->Release();
return S_OK;
}
HRESULT FedMessaging::GetListeningPort(DWORD* dwPort) {
assert(m_pDirectPlayServer);
if(!m_pDirectPlayServer)
return E_FAIL; IDirectPlay8Address* pAddress;
HRESULT hr;
DWORD dwAddySize = 1;
hr = m_pDirectPlayServer->GetLocalHostAddresses(&pAddress, &dwAddySize, DPNGETLOCALHOSTADDRESSES_COMBINED);
if (ZFailed(hr)) return hr;
DWORD dwBuffSize = sizeof(DWORD);
DWORD dwDataType;
DWORD dwPortGot;
hr = pAddress->GetComponentByName(DPNA_KEY_PORT, &dwPortGot, &dwBuffSize, &dwDataType);
if (ZFailed(hr)) return hr;
*dwPort = dwPortGot;
return S_OK;
}
HRESULT FedMessaging::EnumSessions(GUID guidApplication, const char * szServer)
{
if (!m_pDirectPlayClient)
{
HRESULT hr;
hr = InitDPlayClient();
if ( FAILED(hr) )
return hr;
}
m_fSessionCallback = true;
return EnumHostsInternal(guidApplication, szServer);
}
HRESULT FedMessaging::EnumHostsInternal(GUID guidApplication, const char * szServer, DWORD dwPort) {
if (!m_pDirectPlayClient)
{
HRESULT hr;
hr = InitDPlayClient();
if ( FAILED(hr) )
return hr;
}
DWORD dwSize = 0;
Time timeStart = Time::Now();
static CTempTimer tt("in FedMessaging::EnumSessionsInternal", 1.0f);
tt.Start();
SetCursor(LoadCursor(NULL, IDC_WAIT));
assert( m_pDirectPlayClient ); DPN_APPLICATION_DESC dpnAppDesc;
IDirectPlay8Address* pDP8AddressHost = 0;
IDirectPlay8Address* pDP8AddressLocal = 0;
WCHAR* wszHostName = 0;
HRESULT hr;
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
CLSCTX_ALL, IID_IDirectPlay8Address,
(LPVOID*) &pDP8AddressLocal ) ) )
{
m_pfmSite->OnMessageBox( this, "Failed to create DPlay client local address", "Allegiance", MB_OK );
return hr;
}
SafeReleaser<IDirectPlay8Address> r1( pDP8AddressLocal );
if( FAILED( hr = pDP8AddressLocal->SetSP( &CLSID_DP8SP_TCPIP ) ) )
{
m_pfmSite->OnMessageBox( this, "Failed to create DPlay local SP", "Allegiance", MB_OK );
return hr;
}
if( FAILED( hr = CoCreateInstance( CLSID_DirectPlay8Address, NULL,
CLSCTX_ALL, IID_IDirectPlay8Address,
(LPVOID*) &pDP8AddressHost ) ) )
{
m_pfmSite->OnMessageBox( this, "Failed to create DPlay client remote address", "Allegiance", MB_OK );
return hr;
}
SafeReleaser<IDirectPlay8Address> r2( pDP8AddressHost );
if( FAILED( hr = pDP8AddressHost->SetSP( &CLSID_DP8SP_TCPIP ) ) )
{
m_pfmSite->OnMessageBox( this, "Failed to create DPlay remote SP", "Allegiance", MB_OK );
return hr;
}
if(dwPort != 6073 && FAILED(hr = pDP8AddressHost->AddComponent(DPNA_KEY_PORT, &dwPort, sizeof(DWORD), DPNA_DATATYPE_DWORD)))
{
m_pfmSite->OnMessageBox( this, "Failed to set DPlay client remote port", "Allegiance", MB_OK );
return hr;
}
if( szServer != 0 )
{
wszHostName = constChar2Wchar( szServer );
hr = pDP8AddressHost->AddComponent( DPNA_KEY_HOSTNAME, wszHostName,
(wcslen(wszHostName)+1)*sizeof(WCHAR),
DPNA_DATATYPE_STRING );
delete[] wszHostName;
if( FAILED(hr) )
{
m_pfmSite->OnMessageBox( this, "Failed to set DPlay server", "Allegiance", MB_OK );
return hr;
}
}
ZeroMemory( &dpnAppDesc, sizeof( DPN_APPLICATION_DESC ) );
dpnAppDesc.dwSize = sizeof( DPN_APPLICATION_DESC );
dpnAppDesc.guidApplication = guidApplication;
g_guidApplication = guidApplication;
if (IsEqualGUID(FEDSRV_STANDALONE_PRIVATE_GUID, guidApplication)) {
hr = m_pDirectPlayClient->EnumHosts( &dpnAppDesc, pDP8AddressHost,
pDP8AddressLocal, NULL,
0, 0, 0, 0, NULL, 0 , DPNOP_SYNC );
} else {
DPNHANDLE fillerHandle; hr = m_pDirectPlayClient->EnumHosts( &dpnAppDesc, pDP8AddressHost,
pDP8AddressLocal, NULL,
0, INFINITE, 0, 0, NULL,
&fillerHandle, 0 );
}
if( FAILED(hr) )
{
m_pfmSite->OnMessageBox( this, "Failed to set Enumerate Hosts", "Allegiance", MB_OK );
return hr;
}
return hr;
}
CFMConnection * FedMessaging::CreateConnection(const char * szName, DPID dpid) {
static CTempTimer tt("in CreateConnection", .01f);
tt.Start();
CFMConnection * pcnxn = new CFMConnection(this, szName, dpid);
m_listCnxns.PushFront(pcnxn);
m_cnxnsMap[dpid] = pcnxn;
m_pgrpEveryone->AddConnection(this, pcnxn); m_pfmSite->OnNewConnection(this, *pcnxn);
tt.Stop();
return pcnxn;
}
void FedMessaging::SetSessionDetails(char * szDetails) {
DWORD size = 0;
assert( m_pDirectPlayServer );
HRESULT hr = m_pDirectPlayServer->GetApplicationDesc( 0, &size, 0 );
if( hr != DPNERR_BUFFERTOOSMALL )
{
ZSucceeded( hr );
}
DPN_APPLICATION_DESC* pAppDesc = (DPN_APPLICATION_DESC*) new BYTE[size];
ZeroMemory( pAppDesc, size );
pAppDesc->dwSize = sizeof( DPN_APPLICATION_DESC );
ZSucceeded( m_pDirectPlayServer->GetApplicationDesc( pAppDesc, &size, 0 ) );
WCHAR* wDetails = constChar2Wchar( szDetails );
pAppDesc->pwszSessionName = wDetails;
m_pDirectPlayServer->SetApplicationDesc( pAppDesc, 0 );
delete[] wDetails;
delete[] pAppDesc;
}
DWORD FedMessaging::GetCountConnections()
{
DWORD size = 0; assert( m_pDirectPlayServer );
HRESULT hr2 = m_pDirectPlayServer->GetApplicationDesc( 0, &size, 0 );
DPN_APPLICATION_DESC* pAppDesc = (DPN_APPLICATION_DESC*) new BYTE[size];
ZeroMemory( pAppDesc, size );
pAppDesc->dwSize = sizeof( DPN_APPLICATION_DESC );
HRESULT hr = m_pDirectPlayServer->GetApplicationDesc( pAppDesc, &size, 0 );
DWORD dwConnections = pAppDesc->dwCurrentPlayers;
delete[] pAppDesc;
return dwConnections;
}
HRESULT FedMessaging::GetLinkDetails(CFMConnection * pcnxn, OUT DWORD * pdwHundredbpsG, OUT DWORD * pdwmsLatencyG,
OUT DWORD * pdwHundredbpsU, OUT DWORD * pdwmsLatencyU)
{
*pdwHundredbpsG = 0;
*pdwmsLatencyG = 0;
*pdwHundredbpsU = 0;
*pdwmsLatencyU = 0;
return S_OK;
}
CFMConnection::CFMConnection(FedMessaging * pfm, const char * szName, DPID dpid) : CFMRecipient(szName, dpid),
m_cAbsentCount(0),
m_dwPrivate(0)
{
assert(GetDPID() == dpid);
}
void CFMConnection::Delete(FedMessaging * pfm) {
static CTempTimer tt("in DestroyPlayer/SetPlayerData", 0.02f);
tt.Start();
HRESULT hr = pfm->GetDPlayServer()->DestroyClient(GetDPID(), 0, 0, 0);
debugf("DestroyPlayer=0x%08x\n", hr);
tt.Stop();
delete this;
g_fConnectionDeleted = true;
}
void CFMGroup::AddConnection(FedMessaging * pfm, CFMConnection * pcnxn)
{
DPNHANDLE hand;
pfm->GetDPlayServer()->AddPlayerToGroup( GetDPID(), pcnxn->GetDPID(), 0, &hand, 0 );
}
void CFMGroup::DeleteConnection(FedMessaging * pfm, CFMConnection * pcnxn)
{
DPNHANDLE hand;
pfm->GetDPlayServer()->RemovePlayerFromGroup(GetDPID(), pcnxn->GetDPID(), 0, &hand, 0);
}
CFMGroup::CFMGroup(FedMessaging * pfm, const char * szName)
: m_cPlayers(0), CFMRecipient(szName, 0) {
DPN_GROUP_INFO dpn;
ZeroMemory( &dpn, sizeof( DPN_GROUP_INFO ) );
dpn.dwSize = sizeof( DPN_GROUP_INFO );
dpn.dwInfoFlags = DPNINFO_NAME;
dpn.pwszName = constChar2Wchar( szName );
ZSucceeded( pfm->GetDPlayServer()->CreateGroup( &dpn, this, NULL, NULL, DPNOP_SYNC ) );
delete[] dpn.pwszName;
}
void CFMGroup::Delete (FedMessaging * pfm)
{
DPNHANDLE hand;
pfm->GetDPlayServer()->DestroyGroup(GetDPID(), 0, 0, DPNOP_SYNC );
delete this;
}
void CFMGroup::PlayerAdded(CFMConnection * pcnxn)
{
m_cPlayers++;
}
void CFMGroup::PlayerDeleted(CFMConnection * pcnxn)
{
m_cPlayers--;
}
FMSessionDesc::FMSessionDesc( const DPN_APPLICATION_DESC* appDesc)
{
char* szName = 0;
char* szValue = 0;
m_nNumPlayers = 0;
m_nMaxPlayers = 1;
char* sessionName = wChar2ConstChar( appDesc->pwszSessionName );
szName = strtok( sessionName , "\t");
while(szName)
{
if (!lstrcmp(szName, "GAM"))
{
szValue = strtok(NULL, "\n");
m_strGameName = szValue;
}
else if (!lstrcmp(szName, "PLR"))
{
szValue = strtok(NULL, "\n");
m_nNumPlayers = (short)atoi(szValue);
}
else if (!lstrcmp(szName, "LIM"))
{
szValue = strtok(NULL, "\n");
m_nMaxPlayers = (short)atoi(szValue);
}
else {
szValue = strtok(NULL, "\n");
}
szName = strtok(NULL, "\t");
}
m_guidInstance = appDesc->guidInstance;
delete[] sessionName;
}
HRESULT FedMessaging::GetSendQueue(DWORD * pcMsgs, DWORD * pcBytes)
{
if( m_pDirectPlayClient != 0 )
return m_pDirectPlayClient->GetSendQueueInfo( pcMsgs, pcBytes, 0 );
*pcMsgs = 0;
*pcBytes = 0;
return S_OK;
}
HRESULT FedMessaging::GetReceiveQueue(DWORD * pcMsgs, DWORD * pcBytes)
{
*pcMsgs = 0;
*pcBytes = 0;
return S_OK;
}
HRESULT FedMessaging::GetConnectionSendQueue(CFMConnection * pcnxn, DWORD * pcMsgs, DWORD * pcBytes)
{
if ( m_pDirectPlayServer != 0 )
return m_pDirectPlayServer->GetSendQueueInfo( pcnxn->GetID(), pcMsgs, pcBytes, 0 );
*pcMsgs = 0;
*pcBytes = 0;
return S_OK;
}
HRESULT FedMessaging::GetConnectionInfo(CFMConnection * pcnxn, DPN_CONNECTION_INFO & ConnectionInfo)
{
if ( m_pDirectPlayServer != 0 )
return m_pDirectPlayServer->GetConnectionInfo(pcnxn->GetID(),&ConnectionInfo,0);
return S_FALSE;
}