mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3393 lines
96 KiB
3393 lines
96 KiB
// =================================================================
|
|
//
|
|
// Direct Play Network Methods
|
|
//
|
|
// Functions to manage communications over a network.
|
|
//
|
|
//
|
|
// =================================================================
|
|
#ifndef WIN32_LEAN_AND_MEAN
|
|
#define WIN32_LEAN_AND_MEAN
|
|
#endif
|
|
#include <windows.h>
|
|
#include <windowsx.h>
|
|
#include <winsock.h>
|
|
#ifndef _MT
|
|
#define _MT
|
|
#endif
|
|
#include <process.h>
|
|
#include <string.h>
|
|
|
|
#include "dpspimp.h"
|
|
#include "logit.h"
|
|
|
|
#define lmalloc(a) LocalAlloc(LMEM_FIXED, (a))
|
|
#define lfree(a) LocalFree((HLOCAL)(a))
|
|
|
|
CImpIDP_SP *pDirectPlayObject = NULL; // We only allow one object
|
|
// to be created currently - see below.
|
|
|
|
HANDLE hOnlyOneTCP = NULL;
|
|
HANDLE hOnlyOneIPX = NULL;
|
|
|
|
extern "C" VOID InternalCleanUp()
|
|
{
|
|
if (pDirectPlayObject)
|
|
pDirectPlayObject->Close(DPLAY_CLOSE_INTERNAL);
|
|
|
|
pDirectPlayObject = NULL;
|
|
}
|
|
|
|
extern BOOL CreateQueue(DWORD dwElements, DWORD dwmaxMsg, DWORD dwMaxPlayers);
|
|
extern BOOL DeleteQueue();
|
|
|
|
GUID DPLAY_NETWORK_TCP = { /* 8cab4650-b1b6-11ce-920c-00aa006c4972 */
|
|
0x8cab4650,
|
|
0xb1b6,
|
|
0x11ce,
|
|
{0x92, 0x0c, 0x00, 0xaa, 0x00, 0x6c, 0x49, 0x72}
|
|
};
|
|
GUID DPLAY_NETWORK_IPX = { /* 8cab4651-b1b6-11ce-920c-00aa006c4972 */
|
|
0x8cab4651,
|
|
0xb1b6,
|
|
0x11ce,
|
|
{0x92, 0x0c, 0x00, 0xaa, 0x00, 0x6c, 0x49, 0x72}
|
|
};
|
|
|
|
GUID NULL_GUID = {
|
|
0x00000000,
|
|
0x0000,
|
|
0x0000,
|
|
{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
|
|
};
|
|
extern BOOL bNetIsUp;
|
|
|
|
|
|
|
|
HRESULT CImpIDP_SP::Initialize(LPGUID lpguid)
|
|
{
|
|
TSHELL_INFO(TEXT("Already Initialized."));
|
|
return(DPERR_ALREADYINITIALIZED);
|
|
}
|
|
|
|
void *CImpIDP_SP::operator new( size_t size )
|
|
{
|
|
return(LocalAlloc(LMEM_FIXED, size));
|
|
}
|
|
void CImpIDP_SP::operator delete( void *ptr )
|
|
{
|
|
LocalFree((HLOCAL)ptr);
|
|
}
|
|
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// CImpIDP_SP constructor - create a new DCO object
|
|
// along with a queue of receive buffers.
|
|
// ----------------------------------------------------------
|
|
USHORT CImpIDP_SP::NextSequence()
|
|
{
|
|
m_usSeq %= 51001;
|
|
m_usSeq++;
|
|
return(m_usSeq);
|
|
}
|
|
|
|
USHORT CImpIDP_SP::UpdateSequence(USHORT us)
|
|
{
|
|
if (us > m_usSeq)
|
|
m_usSeq = us;
|
|
|
|
return(NextSequence());
|
|
}
|
|
|
|
|
|
CImpIDP_SP::CImpIDP_SP()
|
|
{
|
|
m_bConnected = FALSE;
|
|
m_bPlayer0 = FALSE;
|
|
|
|
m_dwPingSent = 0;
|
|
m_hBlockingEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
m_hEnumBlkEventMain = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
m_hEnumBlkEventRead = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
m_hPlayerBlkEventMain = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
m_hPlayerBlkEventRead = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
m_dwNextPlayer = 1;
|
|
m_bEnablePlayerAdd = TRUE;
|
|
|
|
m_fpEnumSessions = NULL;
|
|
m_bRunEnumReceiveLoop = FALSE;
|
|
m_fpEnumPlayers = NULL;
|
|
m_lpvSessionContext = NULL;
|
|
m_lpvPlayersContext = NULL;
|
|
memset( m_aPlayer, 0x00, sizeof(PLAYER_RECORD) * MAX_PLAYERS);
|
|
m_iPlayerIndex = -1;
|
|
memset(&m_dpDesc, 0x00, sizeof(DPSESSIONDESC));
|
|
|
|
// Initialize ref count
|
|
m_refCount = 1;
|
|
InitializeCriticalSection( &m_critSection );
|
|
InitializeCriticalSection( &m_critSectionPlayer );
|
|
InitializeCriticalSection( &m_critSectionParanoia );
|
|
memset(&m_dpcaps, 0x00, sizeof(DPCAPS));
|
|
m_dpcaps.dwSize = sizeof(DPCAPS);
|
|
m_dpcaps.dwFlags = 0;
|
|
m_dpcaps.dwMaxQueueSize = 64;
|
|
m_dpcaps.dwMaxPlayers = MAX_PLAYERS;
|
|
m_dpcaps.dwHundredBaud = 100000;
|
|
|
|
m_hNewPlayerEvent = NULL;
|
|
m_ppSessionArray = 0;
|
|
m_dwSessionPrev = 0;
|
|
m_dwSessionAlloc = 0;
|
|
m_af = 0;
|
|
|
|
m_remoteaddrlen = 0;
|
|
m_chComputerName[0] = '\0';
|
|
m_bShutDown = FALSE;
|
|
m_hNSThread = NULL;
|
|
m_dwNSId = 0;
|
|
m_usGamePort = 0;
|
|
m_usGameCookie = 0;
|
|
m_hClientThread = NULL;
|
|
m_dwClientId = 0;
|
|
m_hEnumThread = NULL;
|
|
m_dwEnumId = 0;
|
|
|
|
m_ServerSocket = INVALID_SOCKET;
|
|
m_bClientSocket = FALSE; m_EnumSocket = INVALID_SOCKET;
|
|
m_bEnumSocket = FALSE; m_ClientSocket = INVALID_SOCKET;
|
|
|
|
m_dwSession = 0;
|
|
memset( (LPVOID) &m_NSSockAddr, 0x00, sizeof(SOCKADDR));
|
|
m_SessionAddrLen = 0;
|
|
memset( (LPVOID) &m_GameSockAddr, 0x00, sizeof(SOCKADDR));
|
|
|
|
m_usSeq = 1;
|
|
m_usSeqSys = 0;
|
|
|
|
m_aMachineAddr = NULL;
|
|
m_cMachines = 0;
|
|
m_dwUnique = 1;
|
|
|
|
memset( (LPVOID) &m_spmsgEnum, 0x00, sizeof(SPMSG_ENUM));
|
|
memset( (LPVOID) &m_spmsgAddPlayer, 0x00, sizeof(SPMSG_ADDPLAYER));
|
|
}
|
|
|
|
DWORD WINAPI StartClientThreadProc(LPVOID lpvParam)
|
|
{
|
|
CImpIDP_SP *pIDP = (CImpIDP_SP *) lpvParam;
|
|
|
|
return(pIDP->ClientThreadProc());
|
|
}
|
|
|
|
|
|
CImpIDP_SP *CImpIDP_SP::NewCImpIDP_SP(int af)
|
|
{
|
|
CImpIDP_SP *pImp = NULL;
|
|
HANDLE hEvent = NULL;
|
|
|
|
|
|
if (InitializeWinSock() != 0)
|
|
{
|
|
TSHELL_INFO( TEXT("DPWsock failed initializing winsock."));
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
if (!CreateQueue(64, MAX_MSG, MAX_PLAYERS))
|
|
{
|
|
TSHELL_INFO(TEXT("Couldn't initialize queue."));
|
|
return(NULL);
|
|
}
|
|
|
|
pImp = new CImpIDP_SP;
|
|
|
|
if (!pImp)
|
|
return(NULL);
|
|
|
|
pImp->m_dpcaps.dwMaxBufferSize = 512;
|
|
pImp->m_af = af;
|
|
|
|
return(pImp);
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// CreateNewDirectPlay - DCO object creation entry point
|
|
// called by the DCO interface functions to create a new
|
|
// DCO object.
|
|
// ----------------------------------------------------------
|
|
IDirectPlaySP * _cdecl CreateNewDirectPlay( LPGUID lpGuid )
|
|
{
|
|
|
|
int af;
|
|
|
|
//
|
|
// One object at a time, please.
|
|
//
|
|
if (pDirectPlayObject != NULL)
|
|
{
|
|
TSHELL_INFO(TEXT("We already have an object."));
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
if (IsEqualGUID((REFGUID) DPLAY_NETWORK_TCP, (REFGUID) *lpGuid))
|
|
af = AF_INET;
|
|
else if (IsEqualGUID((REFGUID) DPLAY_NETWORK_IPX, (REFGUID) *lpGuid))
|
|
af = AF_IPX;
|
|
else
|
|
return(NULL);
|
|
|
|
|
|
pDirectPlayObject = CImpIDP_SP::NewCImpIDP_SP(af);
|
|
|
|
if (!pDirectPlayObject)
|
|
return(NULL);
|
|
else
|
|
return(pDirectPlayObject);
|
|
}
|
|
|
|
|
|
// Begin: IUnknown interface implementation
|
|
HRESULT CImpIDP_SP::QueryInterface(
|
|
REFIID iid,
|
|
LPVOID *ppvObj
|
|
)
|
|
{
|
|
HRESULT retVal = DPERR_GENERIC;
|
|
|
|
//
|
|
// BUGBUG
|
|
//
|
|
if (ppvObj && ! IsBadWritePtr(ppvObj, 4))
|
|
{
|
|
AddRef();
|
|
*ppvObj = this;
|
|
return(DP_OK);
|
|
}
|
|
else
|
|
return(DPERR_INVALIDPARAM);
|
|
|
|
}
|
|
|
|
ULONG CImpIDP_SP::AddRef( void)
|
|
{
|
|
ULONG newRefCount;
|
|
|
|
m_refCount++;
|
|
newRefCount = m_refCount;
|
|
|
|
DBG_INFO((DBGARG, TEXT("newRefCount = %lu"), newRefCount));
|
|
|
|
return( newRefCount );
|
|
}
|
|
|
|
ULONG CImpIDP_SP::Release( void )
|
|
{
|
|
ULONG newRefCount;
|
|
|
|
m_refCount--;
|
|
newRefCount = m_refCount;
|
|
|
|
if (newRefCount == 0)
|
|
{
|
|
Close(DPLAY_CLOSE_INTERNAL);
|
|
delete this;
|
|
}
|
|
|
|
DBG_INFO((DBGARG, TEXT("newRefCount = %lu"), newRefCount));
|
|
|
|
return( newRefCount );
|
|
}
|
|
|
|
// End : IUnknown interface implementation
|
|
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// CImpDirectPlay destructor -
|
|
// ----------------------------------------------------------
|
|
CImpIDP_SP::~CImpIDP_SP()
|
|
{
|
|
|
|
DWORD ii;
|
|
|
|
if (m_ppSessionArray)
|
|
{
|
|
for (ii = 0; ii < m_dwSessionPrev; ii++)
|
|
lfree(m_ppSessionArray[ii]);
|
|
lfree(m_ppSessionArray);
|
|
m_dwSessionPrev = 0;
|
|
m_dwSessionAlloc = 0;
|
|
}
|
|
|
|
if (m_aMachineAddr)
|
|
lfree(m_aMachineAddr);
|
|
|
|
DeleteCriticalSection( &m_critSection );
|
|
DeleteCriticalSection( &m_critSectionPlayer );
|
|
DeleteCriticalSection( &m_critSectionParanoia );
|
|
CloseHandle(m_hBlockingEvent);
|
|
CloseHandle(m_hEnumBlkEventMain);
|
|
CloseHandle(m_hEnumBlkEventRead);
|
|
CloseHandle(m_hPlayerBlkEventMain);
|
|
CloseHandle(m_hPlayerBlkEventRead);
|
|
ShutdownWinSock();
|
|
pDirectPlayObject = NULL;
|
|
DeleteQueue();
|
|
}
|
|
|
|
|
|
void CImpIDP_SP::EnumDataLock( void )
|
|
{
|
|
EnterCriticalSection( &m_critSection );
|
|
}
|
|
|
|
void CImpIDP_SP::EnumDataUnlock( void )
|
|
{
|
|
LeaveCriticalSection( &m_critSection );
|
|
}
|
|
|
|
void CImpIDP_SP::PlayerDataLock( void )
|
|
{
|
|
EnterCriticalSection( &m_critSectionPlayer );
|
|
}
|
|
|
|
void CImpIDP_SP::PlayerDataUnlock( void )
|
|
{
|
|
LeaveCriticalSection( &m_critSectionPlayer );
|
|
}
|
|
|
|
void CImpIDP_SP::ParanoiaLock( void )
|
|
{
|
|
EnterCriticalSection( &m_critSectionParanoia );
|
|
}
|
|
|
|
void CImpIDP_SP::ParanoiaUnlock( void )
|
|
{
|
|
LeaveCriticalSection( &m_critSectionParanoia );
|
|
}
|
|
|
|
DWORD WINAPI StartServerThreadProc(LPVOID lpvParam)
|
|
{
|
|
CImpIDP_SP *pIDP = (CImpIDP_SP *) lpvParam;
|
|
|
|
return(pIDP->ServerThreadProc());
|
|
}
|
|
|
|
|
|
BOOL CImpIDP_SP::GetSockAddress(SOCKADDR *pSAddr,
|
|
LPINT pSAddrLen,
|
|
USHORT usPort,
|
|
SOCKET *pSocket,
|
|
BOOL bBroadcast
|
|
)
|
|
{
|
|
PSOCKADDR_IN pSockAddrIn;
|
|
PSOCKADDR_IPX pSockAddrIPX;
|
|
UINT uErr;
|
|
|
|
memset(pSAddr, 0, sizeof(SOCKADDR));
|
|
pSAddr->sa_family = (USHORT)m_af;
|
|
|
|
switch (m_af)
|
|
{
|
|
case AF_INET:
|
|
|
|
pSockAddrIn = (PSOCKADDR_IN) pSAddr;
|
|
pSockAddrIn->sin_port = htons(usPort);
|
|
if (bBroadcast)
|
|
pSockAddrIn->sin_addr.s_addr = INADDR_BROADCAST;
|
|
break;
|
|
|
|
case AF_IPX:
|
|
|
|
pSockAddrIPX = (PSOCKADDR_IPX) pSAddr;
|
|
pSockAddrIPX->sa_socket = htons(usPort);
|
|
if (bBroadcast)
|
|
memset(&pSockAddrIPX->sa_nodenum, 0xff, sizeof(pSockAddrIPX->sa_nodenum));
|
|
break;
|
|
|
|
default:
|
|
|
|
return (FALSE);
|
|
|
|
}
|
|
|
|
if (!bBroadcast)
|
|
{
|
|
*pSAddrLen = sizeof(SOCKADDR);
|
|
if ((uErr = InitializeSocket(m_af, pSAddr, pSAddrLen, pSocket)) != 0)
|
|
{
|
|
DBG_INFO((DBGARG, TEXT("Init Socket Failed %8x"), uErr));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
DWORD CImpIDP_SP::ClientThreadProc()
|
|
{
|
|
HRESULT hr = DP_OK;
|
|
char chRBuffer[2048];
|
|
SOCKADDR SockAddr;
|
|
UINT BufferLen;
|
|
INT SockAddrLen;
|
|
BOOL bNoConnection = TRUE;
|
|
DPHDR *pHdr = (DPHDR *) chRBuffer;
|
|
UINT err;
|
|
const char ttl = 32;
|
|
|
|
TSHELL_INFO(TEXT("Client Thread starts."));
|
|
|
|
|
|
memset(&SockAddr, 0, sizeof(SOCKADDR));
|
|
SockAddr.sa_family = (USHORT)m_af;
|
|
|
|
if (m_fpEnumSessions == NULL && m_usGamePort == 0)
|
|
return(0);
|
|
|
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
|
|
|
|
if (m_usGamePort)
|
|
{
|
|
|
|
if (GetSockAddress(&SockAddr, &SockAddrLen, m_usGamePort, (SOCKET *)&m_ClientSocket, FALSE))
|
|
{
|
|
m_bClientSocket = TRUE;
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Thread Exit."));
|
|
SetEvent(m_hBlockingEvent);
|
|
return(0);
|
|
}
|
|
|
|
SetEvent(m_hBlockingEvent);
|
|
TSHELL_INFO(TEXT("Client Thread with game port looping."));
|
|
while (!m_bShutDown)
|
|
{
|
|
//
|
|
// Do a blocking receive from anyone. Once we return from here,
|
|
// we could either have a real request in our buffer, or our
|
|
// socket's been closed in which case we'll have an error in err.
|
|
//
|
|
|
|
BufferLen = sizeof(chRBuffer);
|
|
|
|
if (!(ReceiveAny(m_ClientSocket, &SockAddr, &SockAddrLen, chRBuffer, &BufferLen)))
|
|
{
|
|
|
|
// TSHELL_INFO(TEXT("Got a message in Client Game thread."));
|
|
|
|
|
|
if ( pHdr->dwConnect1 == DPSYS_KYRA
|
|
&& pHdr->dwConnect2 == DPSYS_HALL)
|
|
{
|
|
UpdateSequence(pHdr->usSeq);
|
|
// TSHELL_INFO(TEXT("Handle connect message."));
|
|
HandleConnect(pHdr, (DWORD) BufferLen, &SockAddr, SockAddrLen);
|
|
}
|
|
else if ( pHdr->usCookie == DPSYS_USER
|
|
|| pHdr->usCookie == DPSYS_SYS
|
|
|| pHdr->usCookie == DPSYS_HIGH)
|
|
{
|
|
UpdateSequence(pHdr->usSeq);
|
|
TSHELL_INFO(TEXT("Handle server message Client Thread."));
|
|
HandleMessage(pHdr, (DWORD) BufferLen, &SockAddr, SockAddrLen);
|
|
}
|
|
}
|
|
}
|
|
ParanoiaLock();
|
|
if (m_ClientSocket != INVALID_SOCKET)
|
|
CloseSocket(m_ClientSocket, 2);
|
|
m_ClientSocket = INVALID_SOCKET;
|
|
TSHELL_INFO(TEXT("Client Thread Exit."));
|
|
ParanoiaUnlock();
|
|
}
|
|
else
|
|
{
|
|
|
|
if ((err = InitializeSocket(m_af, NULL, NULL, (SOCKET *) &m_EnumSocket)) != 0)
|
|
{
|
|
DBG_INFO((DBGARG, TEXT("THREAD EXIT on ENUM INIT %d."), err));
|
|
SetEvent(m_hBlockingEvent);
|
|
return(0);
|
|
}
|
|
else
|
|
m_bEnumSocket = TRUE;
|
|
|
|
// if (setsockopt(m_EnumSocket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)))
|
|
// {
|
|
// DBG_INFO((DBGARG, TEXT("SetSocket Option for multicast failed. %d"), GetLastError()));
|
|
// }
|
|
|
|
SetEvent(m_hBlockingEvent);
|
|
// TSHELL_INFO(TEXT("Looping in EnumThread."));
|
|
|
|
SockAddrLen = sizeof(SockAddr);
|
|
getsockname(m_EnumSocket, &SockAddr, &SockAddrLen);
|
|
|
|
while (m_bRunEnumReceiveLoop)
|
|
{
|
|
BufferLen = sizeof(chRBuffer);
|
|
SockAddrLen = sizeof(SockAddr);
|
|
if (!(ReceiveAny(m_EnumSocket, &SockAddr, &SockAddrLen, chRBuffer, &BufferLen)))
|
|
{
|
|
// TSHELL_INFO(TEXT("Message in EnumThread."));
|
|
if ( pHdr->dwConnect1 == DPSYS_KYRA
|
|
&& pHdr->dwConnect2 == DPSYS_HALL)
|
|
{
|
|
UpdateSequence(pHdr->usSeq);
|
|
// TSHELL_INFO(TEXT("Handle connect message."));
|
|
HandleConnect((LPVOID) pHdr, (DWORD) BufferLen, &SockAddr, SockAddrLen);
|
|
#ifdef DEBUG
|
|
if (!m_fpEnumSessions)
|
|
TSHELL_INFO(TEXT("m_fpEnumSessions is NULL."));
|
|
#endif
|
|
}
|
|
else if ( pHdr->usCookie == DPSYS_SYS
|
|
&& pHdr->usCount == SIZE_ADDPLAYER
|
|
&& ((SPMSG_GENERIC *)pHdr)->sMsg.dwType == DPSYS_ENUMPLAYERRESP)
|
|
{
|
|
HandleMessage(pHdr, (DWORD) BufferLen, &SockAddr, SockAddrLen);
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Enum function got an illegal non-connect message."));
|
|
DBG_INFO((DBGARG, TEXT("Non-connect was %8x %8x Length %d"),
|
|
pHdr->dwConnect1,
|
|
pHdr->dwConnect2,
|
|
BufferLen));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
EnumDataLock();
|
|
|
|
if (m_EnumSocket != INVALID_SOCKET)
|
|
CloseSocket(m_EnumSocket, 2);
|
|
m_EnumSocket = INVALID_SOCKET;
|
|
|
|
EnumDataUnlock();
|
|
|
|
TSHELL_INFO(TEXT("Enum Thread Exit."));
|
|
}
|
|
|
|
|
|
|
|
|
|
return(hr);
|
|
|
|
}
|
|
|
|
DWORD CImpIDP_SP::ServerThreadProc()
|
|
{
|
|
SOCKADDR SockAddr;
|
|
HRESULT hr = DP_OK;
|
|
DWORD dw;
|
|
UINT BufferLen;
|
|
INT SockAddrLen;
|
|
char chRBuffer[2048];
|
|
DWORD dwTicks;
|
|
DWORD dwCountIt;
|
|
DWORD ii;
|
|
LPBYTE lpByte;
|
|
DPHDR *pHdr = (DPHDR *) chRBuffer;
|
|
UINT err;
|
|
|
|
|
|
TSHELL_INFO(TEXT("Server Thread Starts."));
|
|
|
|
m_bPlayer0 = FALSE;
|
|
|
|
memset(&SockAddr, 0, sizeof(SOCKADDR));
|
|
SockAddr.sa_family = (USHORT)m_af;
|
|
|
|
if (! GetSockAddress(&SockAddr, &SockAddrLen, DPNS_PORT, (SOCKET *) &m_ServerSocket, FALSE))
|
|
{
|
|
hr = DPERR_GENERIC;
|
|
m_hNSThread = NULL;
|
|
SetEvent(m_hBlockingEvent);
|
|
goto abort;
|
|
}
|
|
|
|
|
|
//
|
|
// Now let's initialize our SDB structure for use in the future.
|
|
// This includes stuff like computer name, address length, etc.
|
|
//
|
|
|
|
SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL);
|
|
|
|
m_remoteaddrlen = sizeof(SOCKADDR);
|
|
dw = sizeof(m_chComputerName);
|
|
GetComputerName(m_chComputerName, &dw);
|
|
|
|
SockAddrLen = m_remoteaddrlen;
|
|
|
|
m_bPlayer0 = TRUE;
|
|
|
|
lpByte = (LPBYTE) &m_dpDesc;
|
|
dwCountIt = 0;
|
|
for (ii = 0; ii < sizeof(m_dpDesc); ii++)
|
|
dwCountIt += lpByte[ii] & 0x000000ff;
|
|
|
|
dwTicks = GetCurrentTime();
|
|
m_usGamePort = (USHORT) (2000 + (((dwCountIt % 75) + 1) * ((dwTicks % 75) + 1)));
|
|
m_usGameCookie = (USHORT) (((dwCountIt % 235) + 1) * ((dwTicks % 235) + 1));
|
|
|
|
GetSockAddress(&m_GameSockAddr, NULL, m_usGamePort, NULL, TRUE);
|
|
|
|
// Let create function go ...
|
|
//
|
|
|
|
SetEvent(m_hBlockingEvent);
|
|
|
|
TSHELL_INFO(TEXT("Server Thread Looping."));
|
|
while (!m_bShutDown)
|
|
{
|
|
//
|
|
// Do a blocking receive from anyone. Once we return from here,
|
|
// we could either have a real request in our buffer, or our
|
|
// socket's been closed in which case we'll have an error in err.
|
|
//
|
|
|
|
BufferLen = sizeof(chRBuffer);
|
|
|
|
if (!(err = ReceiveAny(m_ServerSocket, &SockAddr, &SockAddrLen, chRBuffer, &BufferLen)))
|
|
{
|
|
|
|
TSHELL_INFO(TEXT("Got a NS message."));
|
|
|
|
|
|
if ( pHdr->dwConnect1 == DPSYS_KYRA
|
|
&& pHdr->dwConnect2 == DPSYS_HALL)
|
|
{
|
|
UpdateSequence(pHdr->usSeq);
|
|
TSHELL_INFO(TEXT("Handle connect message."));
|
|
HandleConnect(pHdr, (DWORD) BufferLen, &SockAddr, SockAddrLen);
|
|
}
|
|
else if ( pHdr->usCookie == DPSYS_USER
|
|
|| pHdr->usCookie == DPSYS_SYS
|
|
|| pHdr->usCookie == DPSYS_HIGH)
|
|
{
|
|
UpdateSequence(pHdr->usSeq);
|
|
TSHELL_INFO(TEXT("Handle server message."));
|
|
HandleMessage(pHdr, (DWORD) BufferLen, &SockAddr, SockAddrLen);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_bShutDown = TRUE;
|
|
ParanoiaLock();
|
|
DBG_INFO((DBGARG, TEXT("Server closeing down with value %d"), err));
|
|
if( m_ServerSocket == INVALID_SOCKET )
|
|
{
|
|
CloseSocket(m_ServerSocket, 2);
|
|
}
|
|
m_ServerSocket = INVALID_SOCKET;
|
|
ParanoiaUnlock();
|
|
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean up everything related to this thread and return
|
|
// to caller which will implicitly call ExitThread.
|
|
//
|
|
|
|
abort:
|
|
|
|
return(hr);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// GetCaps - return info about the connection media
|
|
// ----------------------------------------------------------
|
|
|
|
//
|
|
// Return our caps immediately if we have a valid latency value.
|
|
// if we haven't gotten latency yet, send a DPSYS_PING. Latency is
|
|
// the time it takes to get a response DPSYS_PING / 2.
|
|
//
|
|
HRESULT CImpIDP_SP::GetCaps(
|
|
LPDPCAPS lpDPCaps // buffer to receive capabilities
|
|
)
|
|
{
|
|
*lpDPCaps = m_dpcaps;
|
|
|
|
if (m_dpcaps.dwLatency == 0)
|
|
SendPing();
|
|
|
|
return(DP_OK);
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// Connect - establishes communications with underlying transport,
|
|
// and initializes name services and network entities
|
|
// ----------------------------------------------------------
|
|
BOOL CImpIDP_SP::SetSession(DWORD dw)
|
|
{
|
|
return(FALSE);
|
|
}
|
|
|
|
DWORD CImpIDP_SP::BlockNicely(DWORD dwTimeout)
|
|
{
|
|
DWORD dwStart;
|
|
DWORD dwEnd;
|
|
DWORD dwNow;
|
|
DWORD dwRet;
|
|
MSG msg;
|
|
|
|
if (m_hBlockingEvent)
|
|
{
|
|
dwStart = GetTickCount();
|
|
dwEnd = dwStart + dwTimeout;
|
|
dwNow = GetTickCount();
|
|
|
|
do
|
|
{
|
|
dwRet = MsgWaitForMultipleObjects(1,
|
|
&m_hBlockingEvent,
|
|
FALSE,
|
|
dwEnd - dwNow,
|
|
QS_ALLINPUT);
|
|
switch (dwRet)
|
|
{
|
|
case WAIT_OBJECT_0:
|
|
{
|
|
ResetEvent(m_hBlockingEvent);
|
|
return(WAIT_OBJECT_0);
|
|
}
|
|
|
|
case WAIT_TIMEOUT:
|
|
return(WAIT_TIMEOUT);
|
|
|
|
case WAIT_OBJECT_0 + 1:
|
|
{
|
|
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
if (dwEnd < (dwNow = GetTickCount()))
|
|
{
|
|
return(WAIT_TIMEOUT);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
dwNow = GetTickCount();
|
|
} while (dwNow < dwEnd);
|
|
dwRet = WaitForSingleObject(m_hBlockingEvent, 0);
|
|
ResetEvent(m_hBlockingEvent);
|
|
return(dwRet);
|
|
}
|
|
else
|
|
{
|
|
return(WAIT_ABANDONED);
|
|
}
|
|
}
|
|
|
|
HRESULT CImpIDP_SP::Open(
|
|
LPDPSESSIONDESC lpSDesc, HANDLE lpHandle
|
|
)
|
|
{
|
|
|
|
TSHELL_INFO(TEXT("SP Open"));
|
|
DWORD ii;
|
|
|
|
|
|
if (m_hEnumThread)
|
|
{
|
|
m_bRunEnumReceiveLoop = FALSE;
|
|
SetThreadPriority(m_hEnumThread, THREAD_PRIORITY_NORMAL);
|
|
TSHELL_INFO(TEXT("EnumSessions:: Closing Socket."));
|
|
|
|
EnumDataLock();
|
|
|
|
if (m_EnumSocket)
|
|
CloseSocket(m_EnumSocket, 2);
|
|
|
|
m_EnumSocket = INVALID_SOCKET;
|
|
|
|
EnumDataUnlock();
|
|
|
|
TSHELL_INFO(TEXT("EnumSessions:: Socket Closed."));
|
|
|
|
if (WaitForSingleObject(m_hEnumThread, 4000) == WAIT_TIMEOUT)
|
|
TerminateThread(m_hEnumThread, 0);
|
|
m_bEnumSocket = FALSE;
|
|
m_hEnumThread = NULL;
|
|
}
|
|
|
|
|
|
if (lpSDesc->dwFlags & DPOPEN_CREATESESSION)
|
|
{
|
|
if (hOnlyOneTCP || hOnlyOneIPX)
|
|
{
|
|
TSHELL_INFO(TEXT("We already have a server active!"));
|
|
return(DPERR_GENERIC);
|
|
}
|
|
else
|
|
{
|
|
if (m_af == AF_INET)
|
|
{
|
|
hOnlyOneTCP = CreateEvent(NULL, TRUE, TRUE, "KyraHallTCP");
|
|
|
|
if (hOnlyOneTCP == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
|
|
{
|
|
if (hOnlyOneTCP)
|
|
CloseHandle(hOnlyOneTCP);
|
|
|
|
hOnlyOneTCP = NULL;
|
|
return(DPERR_GENERIC);
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hOnlyOneIPX = CreateEvent(NULL, TRUE, TRUE, "KyraHallIPX");
|
|
|
|
if (hOnlyOneIPX == NULL || GetLastError() == ERROR_ALREADY_EXISTS)
|
|
{
|
|
if (hOnlyOneIPX)
|
|
CloseHandle(hOnlyOneIPX);
|
|
|
|
hOnlyOneIPX = NULL;
|
|
return(DPERR_GENERIC);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
if (m_hNSThread || m_aMachineAddr)
|
|
{
|
|
TSHELL_INFO(TEXT("Globals indicate we already have opened a game."));
|
|
return(DPERR_GENERIC);
|
|
}
|
|
|
|
m_aMachineAddr = (SOCKADDR *) lmalloc(sizeof(SOCKADDR) * MAX_PLAYERS);
|
|
m_cMachines = 0;
|
|
|
|
memcpy( &m_dpDesc, lpSDesc, sizeof(m_dpDesc));
|
|
m_dpDesc.dwCurrentPlayers = 0;
|
|
m_dpDesc.dwReserved1 = 0;
|
|
m_dpDesc.dwReserved2 = 0;
|
|
|
|
ResetEvent(m_hBlockingEvent);
|
|
|
|
m_hNSThread = CreateThread(NULL, 0, StartServerThreadProc,
|
|
(LPVOID) this, 0, &m_dwNSId);
|
|
|
|
if (m_hNSThread == NULL)
|
|
{
|
|
TSHELL_INFO(TEXT("StartServerThreadProc failed."));
|
|
return(DPERR_GENERIC);
|
|
}
|
|
|
|
if (WaitForSingleObject(m_hBlockingEvent, INFINITE) == WAIT_TIMEOUT)
|
|
{
|
|
TSHELL_INFO(TEXT("INFINITITY Reached. Notify Nobel Committee."));
|
|
return(DPERR_GENERIC);
|
|
}
|
|
|
|
ResetEvent(m_hBlockingEvent);
|
|
|
|
if (m_bPlayer0 != TRUE)
|
|
{
|
|
TSHELL_INFO(TEXT("We aren't player 0 for some reason."));
|
|
return(DPERR_GENERIC);
|
|
}
|
|
|
|
m_hClientThread = CreateThread(NULL, 0, StartClientThreadProc,
|
|
(LPVOID) this, 0, &m_dwClientId);
|
|
|
|
return(DP_OK);
|
|
}
|
|
else if (lpSDesc->dwFlags & DPOPEN_OPENSESSION)
|
|
{
|
|
if (GetSessionData(lpSDesc->dwSession))
|
|
{
|
|
SPMSG_ENUM Msg;
|
|
UINT BufferLen;
|
|
|
|
if (m_bPlayer0 || m_usGamePort == 0)
|
|
return(DPERR_GENERIC);
|
|
|
|
ResetEvent(m_hBlockingEvent);
|
|
|
|
m_hClientThread = CreateThread(NULL, 0, StartClientThreadProc,
|
|
(LPVOID) this, 0, &m_dwClientId);
|
|
|
|
if (WaitForSingleObject(m_hBlockingEvent, 9000) == WAIT_TIMEOUT)
|
|
return(DPERR_GENERIC);
|
|
|
|
Msg.dpHdr.dwConnect1 = DPSYS_KYRA;
|
|
Msg.dpHdr.dwConnect2 = DPSYS_HALL;
|
|
Msg.dpHdr.usSeq = NextSequence();
|
|
Msg.dwType = DPSYS_OPEN;
|
|
Msg.dpSessionDesc = *lpSDesc;
|
|
Msg.usPort = m_usGamePort;
|
|
Msg.dwUnique = m_dwUnique;
|
|
Msg.usVerMajor = DPVERSION_MAJOR;
|
|
Msg.usVerMinor = DPVERSION_MINOR;
|
|
|
|
BufferLen = sizeof(SPMSG_ENUM);
|
|
|
|
ResetEvent(m_hBlockingEvent);
|
|
if (SendTo(m_ClientSocket, &m_NSSockAddr,
|
|
m_SessionAddrLen, (char *) &Msg, &BufferLen) != 0)
|
|
{
|
|
TSHELL_INFO(TEXT("Enum SendTo failed."));
|
|
}
|
|
|
|
if (WaitForSingleObject(m_hBlockingEvent, 9000) == WAIT_TIMEOUT)
|
|
{
|
|
TSHELL_INFO(TEXT("We timed out."));
|
|
}
|
|
|
|
|
|
EnumDataLock();
|
|
|
|
if (m_ppSessionArray)
|
|
{
|
|
for (ii = 0; ii < m_dwSessionPrev; ii++)
|
|
lfree(m_ppSessionArray[ii]);
|
|
lfree(m_ppSessionArray);
|
|
m_ppSessionArray = NULL;
|
|
m_dwSessionPrev = 0;
|
|
m_dwSessionAlloc = 0;
|
|
}
|
|
|
|
EnumDataUnlock();
|
|
|
|
if (m_bConnected == FALSE)
|
|
return(DPERR_GENERIC);
|
|
|
|
|
|
|
|
return(DP_OK);
|
|
}
|
|
else
|
|
{
|
|
return(DPERR_UNAVAILABLE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Unhandled Open flags."));
|
|
return(DPERR_UNSUPPORTED);
|
|
}
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// CreatePlayer - registers new player, N.B. may fail if
|
|
// not currently connected to name server
|
|
// ----------------------------------------------------------
|
|
LONG CImpIDP_SP::FindInvalidIndex()
|
|
{
|
|
DWORD ii;
|
|
|
|
ParanoiaLock();
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
if (m_aPlayer[ii].bValid == FALSE)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(ii);
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
return(-1);
|
|
}
|
|
VOID CImpIDP_SP::LocalMsg(LONG iIndex, LPVOID lpv, DWORD dwSize)
|
|
{
|
|
|
|
LONG ii;
|
|
|
|
ParanoiaLock();
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
if ( ii != iIndex
|
|
&& m_aPlayer[ii].bValid
|
|
&& m_aPlayer[ii].bLocal
|
|
&& m_aPlayer[ii].bPlayer)
|
|
AddMessage(lpv, dwSize, m_aPlayer[ii].pid, 0, 0);
|
|
|
|
ParanoiaUnlock();
|
|
}
|
|
|
|
//
|
|
// Obsolete? [johnhall]
|
|
//
|
|
VOID CImpIDP_SP::RemoteMsg(LONG iIndex, LPVOID lpv, DWORD dwSize)
|
|
{
|
|
SPMSG_GENERIC Msg;
|
|
DWORD dwTotal = dwSize + sizeof(DPHDR);
|
|
DWORD ii;
|
|
|
|
|
|
if (!m_bConnected)
|
|
return;
|
|
|
|
Msg.dpHdr.usCookie = DPSYS_SYS;
|
|
Msg.dpHdr.to = 0;
|
|
Msg.dpHdr.from = 0;
|
|
Msg.dpHdr.usCount = (USHORT) dwSize;
|
|
Msg.dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
Msg.dpHdr.usSeq = NextSequence();
|
|
memcpy( (LPVOID) &Msg.sMsg, lpv, dwSize);
|
|
|
|
ParanoiaLock();
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
if ( ii != (DWORD) iIndex
|
|
&& m_aPlayer[ii].bValid
|
|
&& m_aPlayer[ii].bLocal == FALSE
|
|
&& m_aPlayer[ii].bPlayer)
|
|
{
|
|
PostPlayerMessage( (LONG) ii, (LPVOID) &Msg, dwTotal);
|
|
TSHELL_INFO(TEXT("Post Player Message in RemoteMsg."));
|
|
}
|
|
ParanoiaUnlock();
|
|
}
|
|
|
|
BOOL CImpIDP_SP::PostGameMessage(LPVOID lpv, DWORD dw)
|
|
{
|
|
|
|
DWORD ii;
|
|
|
|
ParanoiaLock();
|
|
for (ii = 0; ii < m_cMachines; ii++)
|
|
if (SendTo(m_ClientSocket, &m_aMachineAddr[ii], sizeof(SOCKADDR), (char *) lpv, (LPUINT) &dw) != 0)
|
|
{
|
|
TSHELL_INFO(TEXT("Send Failed"));
|
|
}
|
|
else
|
|
{
|
|
LPDWORD lpdw = (LPDWORD) &m_aMachineAddr[ii];
|
|
|
|
DBG_INFO((DBGARG, TEXT("Machine %d Addr %8x %8x %8x %8x"), ii,
|
|
lpdw[0], lpdw[1], lpdw[2], lpdw[3]));
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL CImpIDP_SP::PostPlayerMessage(LONG iIndex, LPVOID lpv, DWORD dw)
|
|
{
|
|
UINT err;
|
|
|
|
if ((err = SendTo(m_ClientSocket, &m_aPlayer[iIndex].sockaddr, sizeof(SOCKADDR), (char *) lpv, (LPUINT) &dw)) != 0)
|
|
{
|
|
DBG_INFO((DBGARG, TEXT("Send Failed %d"), err));
|
|
return(FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL CImpIDP_SP::PostNSMessage(LPVOID lpv, DWORD dw)
|
|
{
|
|
if (SendTo(m_ClientSocket, &m_NSSockAddr, sizeof(SOCKADDR), (char *) lpv, (LPUINT) &dw) != 0)
|
|
{
|
|
TSHELL_INFO(TEXT("Send Failed"));
|
|
return(FALSE);
|
|
}
|
|
return(TRUE);
|
|
}
|
|
extern BOOL SetupLocalPlayer(DPID pid, HANDLE hEvent);
|
|
HRESULT CImpIDP_SP::CreatePlayer(
|
|
LPDPID pPlayerID,
|
|
LPSTR pNickName,
|
|
LPSTR pFullName,
|
|
LPHANDLE lpReceiveEvent,
|
|
BOOL bPlayer
|
|
)
|
|
{
|
|
DWORD jj;
|
|
SPMSG_ADDPLAYER *pMsg;
|
|
HANDLE hEvent = NULL;
|
|
BOOL bb = TRUE;
|
|
HRESULT hr = DP_OK;
|
|
LONG iIndex;
|
|
DPMSG_ADDPLAYER dpAdd;
|
|
SPMSG_ADDPLAYER spmsg_addplayer;
|
|
USHORT usLocalSeq;
|
|
|
|
// TSHELL_INFO(TEXT("Enter Create Player"));
|
|
|
|
if (m_bConnected == FALSE)
|
|
if (m_bPlayer0 != TRUE)
|
|
return(DPERR_NOCONNECTION);
|
|
|
|
if (m_bEnablePlayerAdd == FALSE && bPlayer == TRUE)
|
|
return(DPERR_CANTCREATEPLAYER);
|
|
|
|
if (m_dpDesc.dwMaxPlayers <= m_dpDesc.dwCurrentPlayers)
|
|
{
|
|
DBG_INFO((DBGARG, TEXT("CreatePlayer: at max players already. %d"),
|
|
m_dpDesc.dwMaxPlayers));
|
|
return(DPERR_CANTADDPLAYER);
|
|
}
|
|
|
|
if (m_iPlayerIndex != -1)
|
|
{
|
|
TSHELL_INFO(TEXT("Player index not -1, create already in progress."));
|
|
return(DPERR_GENERIC);
|
|
}
|
|
|
|
if (m_hNewPlayerEvent)
|
|
return(DPERR_GENERIC);
|
|
|
|
if (!(hEvent = CreateEvent(NULL, TRUE, FALSE, NULL)))
|
|
{
|
|
TSHELL_INFO(TEXT("CreatePlayer: CreateEvent failure."));
|
|
return(DPERR_GENERIC);
|
|
}
|
|
else
|
|
{
|
|
; // DBG_INFO((DBGARG, TEXT("CreatePlayer %8x Event"), hEvent));
|
|
}
|
|
|
|
ParanoiaLock();
|
|
iIndex = FindInvalidIndex();
|
|
|
|
if (iIndex == -1)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(DPERR_GENERIC);
|
|
}
|
|
|
|
dpAdd.dwType = DPSYS_ADDPLAYER;
|
|
dpAdd.dwPlayerType = bPlayer;
|
|
dpAdd.dpId = 0;
|
|
dpAdd.dwCurrentPlayers = m_dpDesc.dwCurrentPlayers;
|
|
lstrcpy( dpAdd.szShortName, pNickName);
|
|
lstrcpy( dpAdd.szLongName , pFullName);
|
|
|
|
|
|
pMsg = &spmsg_addplayer;
|
|
usLocalSeq = NextSequence();
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = SIZE_ADDPLAYER;
|
|
pMsg->dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
pMsg->dpHdr.usSeq = usLocalSeq;
|
|
pMsg->dwUnique = m_dwUnique;
|
|
memset(&pMsg->sockaddr, 0x00, sizeof(SOCKADDR));
|
|
|
|
if (m_bPlayer0)
|
|
{
|
|
if (!bPlayer)
|
|
{
|
|
m_aPlayer[iIndex].aGroup = (DPID *) lmalloc(sizeof(DPID) * MAX_PLAYERS);
|
|
if (m_aPlayer[iIndex].aGroup == NULL)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(DPERR_NOMEMORY);
|
|
}
|
|
else
|
|
memset(m_aPlayer[iIndex].aGroup, 0x00, sizeof(DPID) * MAX_PLAYERS);
|
|
}
|
|
m_dpDesc.dwCurrentPlayers++;
|
|
|
|
m_aPlayer[iIndex].pid = (DPID) m_dwNextPlayer++;
|
|
lstrcpy( m_aPlayer[iIndex].chNickName, pNickName);
|
|
lstrcpy( m_aPlayer[iIndex].chFullName, pFullName);
|
|
m_aPlayer[iIndex].bValid = TRUE;
|
|
m_aPlayer[iIndex].bPlayer = bPlayer;
|
|
m_aPlayer[iIndex].hEvent = hEvent;
|
|
m_aPlayer[iIndex].bLocal = TRUE;
|
|
memset(&m_aPlayer[iIndex].sockaddr, 0x00, sizeof(SOCKADDR));
|
|
|
|
|
|
|
|
dpAdd.dpId = m_aPlayer[iIndex].pid;
|
|
dpAdd.dwCurrentPlayers = m_dpDesc.dwCurrentPlayers;
|
|
|
|
LocalMsg( iIndex, (LPVOID) &dpAdd, sizeof(DPMSG_ADDPLAYER));
|
|
memcpy( (LPVOID) &pMsg->sMsg, &dpAdd, sizeof(DPMSG_ADDPLAYER));
|
|
PostGameMessage((LPVOID) pMsg, sizeof(SPMSG_ADDPLAYER));
|
|
|
|
hEvent = NULL;
|
|
*pPlayerID = m_aPlayer[iIndex].pid;
|
|
if (lpReceiveEvent)
|
|
*lpReceiveEvent = m_aPlayer[iIndex].hEvent;
|
|
SetupLocalPlayer(m_aPlayer[iIndex].pid, m_aPlayer[iIndex].hEvent);
|
|
ParanoiaUnlock();
|
|
return(DP_OK);
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
|
|
m_hNewPlayerEvent = hEvent;
|
|
//
|
|
// BUGBUG for now, try once in Net provider.
|
|
//
|
|
for (jj = 0; jj < 1; jj++)
|
|
{
|
|
|
|
TSHELL_INFO(TEXT("Post AddPlayer message from a Client"));
|
|
memcpy( (LPVOID) &pMsg->sMsg, &dpAdd, sizeof(DPMSG_ADDPLAYER));
|
|
PostNSMessage( (LPVOID) pMsg, sizeof(SPMSG_ADDPLAYER));
|
|
pMsg = NULL;
|
|
|
|
if (WaitForSingleObject(m_hNewPlayerEvent, 1500) != WAIT_TIMEOUT)
|
|
{
|
|
if (m_iPlayerIndex != -1)
|
|
{
|
|
SetupLocalPlayer(m_aPlayer[m_iPlayerIndex].pid, m_hNewPlayerEvent);
|
|
m_aPlayer[m_iPlayerIndex].hEvent = m_hNewPlayerEvent;
|
|
if (lpReceiveEvent)
|
|
*lpReceiveEvent = m_aPlayer[m_iPlayerIndex].hEvent;
|
|
m_hNewPlayerEvent = NULL;
|
|
*pPlayerID = m_aPlayer[m_iPlayerIndex].pid;
|
|
m_iPlayerIndex = -1;
|
|
|
|
DBG_INFO((DBGARG, TEXT("Player Index %d Pid %d Current %d"),
|
|
iIndex, m_aPlayer[iIndex].pid, m_dpDesc.dwCurrentPlayers));
|
|
|
|
return(DP_OK);
|
|
}
|
|
}
|
|
|
|
ResetEvent(m_hNewPlayerEvent);
|
|
}
|
|
|
|
|
|
hr = DPERR_CANTADDPLAYER;
|
|
|
|
|
|
m_hNewPlayerEvent = NULL;
|
|
|
|
if (pMsg)
|
|
lfree((HLOCAL) pMsg);
|
|
if (hEvent)
|
|
CloseHandle(hEvent);
|
|
|
|
return(hr);
|
|
|
|
}
|
|
|
|
LONG CImpIDP_SP::GetPlayerIndex(DPID playerID)
|
|
{
|
|
DWORD ii;
|
|
DPID pid = playerID;
|
|
|
|
ParanoiaLock();
|
|
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if (m_aPlayer[ii].bValid)
|
|
if (m_aPlayer[ii].pid == pid)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(ii);
|
|
}
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
return(-1);
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// DestroyPlayer
|
|
// ----------------------------------------------------------
|
|
HRESULT CImpIDP_SP::DestroyPlayer( DPID playerID, BOOL bPlayer)
|
|
{
|
|
LONG iIndex;
|
|
DWORD ii, jj;
|
|
|
|
DPMSG_GETPLAYER dpGet;
|
|
|
|
SPMSG_GETPLAYER spmsg_getplayer;
|
|
SPMSG_GETPLAYER *pMsg;
|
|
HANDLE hEvent = NULL;
|
|
HRESULT hr = DP_OK;
|
|
|
|
ParanoiaLock();
|
|
|
|
if ( (iIndex = GetPlayerIndex(playerID)) == -1
|
|
|| m_aPlayer[iIndex].bPlayer != bPlayer)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(DPERR_INVALIDPLAYER);
|
|
}
|
|
|
|
if (bPlayer)
|
|
{
|
|
dpGet.dwType = DPSYS_DELETEPLAYER;
|
|
}
|
|
else
|
|
{
|
|
dpGet.dwType = DPSYS_DELETEGROUP;
|
|
}
|
|
|
|
dpGet.dpId = m_aPlayer[iIndex].pid;
|
|
|
|
if (m_aPlayer[iIndex].bLocal)
|
|
{
|
|
CloseHandle(m_aPlayer[iIndex].hEvent);
|
|
FlushQueue(playerID);
|
|
}
|
|
|
|
m_aPlayer[iIndex].bValid = FALSE;
|
|
m_dpDesc.dwCurrentPlayers--;
|
|
if (m_aPlayer[iIndex].aGroup)
|
|
lfree(m_aPlayer[iIndex].aGroup);
|
|
|
|
|
|
LocalMsg(iIndex, (LPVOID) &dpGet, sizeof(DPMSG_GETPLAYER));
|
|
pMsg = &spmsg_getplayer;
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = sizeof(DPMSG_GETPLAYER);
|
|
pMsg->dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
memcpy( (LPVOID) &pMsg->sMsg, (LPVOID) &dpGet, sizeof(DPMSG_GETPLAYER));
|
|
|
|
if (m_bPlayer0)
|
|
{
|
|
PostGameMessage((LPVOID) pMsg, sizeof(SPMSG_GETPLAYER));
|
|
}
|
|
else
|
|
{
|
|
PostNSMessage( (LPVOID) pMsg, sizeof(SPMSG_GETPLAYER));
|
|
}
|
|
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if ( m_aPlayer[ii].bValid == TRUE
|
|
&& m_aPlayer[ii].bPlayer == FALSE
|
|
&& m_aPlayer[ii].aGroup)
|
|
{
|
|
for (jj = 0; jj < MAX_PLAYERS; jj++)
|
|
{
|
|
if (m_aPlayer[ii].aGroup[jj] == playerID)
|
|
{
|
|
m_aPlayer[ii].aGroup[jj] = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
|
|
ParanoiaUnlock();
|
|
return(DP_OK);
|
|
|
|
}
|
|
|
|
|
|
// ----------------------------------------------------------
|
|
// Close - close the connection
|
|
// ----------------------------------------------------------
|
|
HRESULT CImpIDP_SP::Close( DWORD dwFlag)
|
|
{
|
|
DWORD ii;
|
|
DWORD dwTickBegin;
|
|
|
|
dwTickBegin = GetTickCount();
|
|
|
|
ParanoiaLock();
|
|
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if (m_aPlayer[ii].bValid)
|
|
{
|
|
if ( ( m_aPlayer[ii].bLocal && m_aPlayer[ii].bPlayer == TRUE))
|
|
{
|
|
DestroyPlayer(m_aPlayer[ii].pid, TRUE);
|
|
}
|
|
m_aPlayer[ii].bValid = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
m_bShutDown = TRUE;
|
|
m_bConnected = FALSE;
|
|
m_bPlayer0 = FALSE;
|
|
m_fpEnumSessions = NULL;
|
|
m_bRunEnumReceiveLoop = FALSE;
|
|
m_fpEnumPlayers = NULL;
|
|
|
|
TSHELL_INFO(TEXT("Close:: Closing Socket."));
|
|
if (m_hNSThread && m_ServerSocket != INVALID_SOCKET)
|
|
CloseSocket(m_ServerSocket, 2);
|
|
|
|
m_ServerSocket = INVALID_SOCKET;
|
|
|
|
if (m_hClientThread && m_ClientSocket != INVALID_SOCKET)
|
|
CloseSocket(m_ClientSocket, 2);
|
|
|
|
m_ClientSocket = INVALID_SOCKET;
|
|
|
|
TSHELL_INFO(TEXT("Close:: Socket Closed."));
|
|
ParanoiaUnlock();
|
|
|
|
if (m_aMachineAddr)
|
|
{
|
|
lfree(m_aMachineAddr);
|
|
m_aMachineAddr = NULL;
|
|
m_cMachines = 0;
|
|
}
|
|
|
|
if (m_hNSThread)
|
|
{
|
|
if (WaitForSingleObject(m_hNSThread, 4000) == WAIT_TIMEOUT)
|
|
{
|
|
TSHELL_INFO(TEXT("Terminating m_hNSThread"));
|
|
TerminateThread(m_hNSThread, 0);
|
|
}
|
|
m_hNSThread = NULL;
|
|
}
|
|
|
|
if (m_hEnumThread)
|
|
{
|
|
SetThreadPriority(m_hEnumThread, THREAD_PRIORITY_NORMAL);
|
|
TSHELL_INFO(TEXT("EnumSessions:: Closing Socket."));
|
|
|
|
EnumDataLock();
|
|
|
|
if (m_EnumSocket)
|
|
CloseSocket(m_EnumSocket, 2);
|
|
|
|
m_EnumSocket = INVALID_SOCKET;
|
|
|
|
EnumDataUnlock();
|
|
|
|
TSHELL_INFO(TEXT("EnumSessions:: Socket Closed."));
|
|
|
|
if (WaitForSingleObject(m_hEnumThread, 4000) == WAIT_TIMEOUT)
|
|
TerminateThread(m_hEnumThread, 0);
|
|
m_bEnumSocket = FALSE;
|
|
m_hEnumThread = NULL;
|
|
}
|
|
|
|
if (m_hClientThread)
|
|
{
|
|
SetThreadPriority(m_hClientThread, THREAD_PRIORITY_NORMAL);
|
|
if (WaitForSingleObject(m_hClientThread, 4000) == WAIT_TIMEOUT)
|
|
{
|
|
TSHELL_INFO(TEXT("Terminating m_hClientThread"));
|
|
TerminateThread(m_hClientThread, 0);
|
|
}
|
|
m_bClientSocket = FALSE;
|
|
m_hClientThread = NULL;
|
|
}
|
|
|
|
ShutdownWinSock();
|
|
|
|
_try
|
|
{
|
|
if (hOnlyOneTCP)
|
|
{
|
|
CloseHandle(hOnlyOneTCP);
|
|
}
|
|
|
|
if (hOnlyOneIPX)
|
|
{
|
|
CloseHandle(hOnlyOneIPX);
|
|
}
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
TSHELL_INFO(TEXT("Exception closing handle."));
|
|
}
|
|
|
|
hOnlyOneTCP = NULL;
|
|
hOnlyOneIPX = NULL;
|
|
|
|
if (dwFlag == DPLAY_CLOSE_USER)
|
|
{
|
|
InitializeWinSock();
|
|
m_bShutDown = FALSE;
|
|
}
|
|
|
|
DBG_INFO((DBGARG, TEXT("Close Took %d Ticks"), GetTickCount() - dwTickBegin));
|
|
|
|
return(DP_OK);
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// GetName -
|
|
// ----------------------------------------------------------
|
|
HRESULT CImpIDP_SP::GetPlayerName(
|
|
DPID dpID,
|
|
LPSTR lpNickName, // buffer to hold name
|
|
LPDWORD pdwNickNameLength, // length of name buffer
|
|
LPSTR lpFullName,
|
|
LPDWORD pdwFullNameLength
|
|
)
|
|
{
|
|
LONG iIndex;
|
|
|
|
HRESULT hr = DP_OK;
|
|
DPID pid = (DPID) dpID;
|
|
|
|
ParanoiaLock();
|
|
if ((iIndex = GetPlayerIndex(dpID)) != -1)
|
|
{
|
|
if (m_aPlayer[iIndex].pid == dpID)
|
|
{
|
|
lstrcpy( lpNickName, m_aPlayer[iIndex].chNickName);
|
|
lstrcpy( lpFullName, m_aPlayer[iIndex].chFullName);
|
|
*pdwNickNameLength = lstrlen(lpNickName) + 1;
|
|
*pdwFullNameLength = lstrlen(lpFullName) + 1;
|
|
}
|
|
else
|
|
hr = DPERR_INVALIDPID;
|
|
|
|
}
|
|
else
|
|
{
|
|
hr = DPERR_INVALIDPID;
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT CImpIDP_SP::EnumGroupPlayers(
|
|
DPID dwGroupPid,
|
|
LPDPENUMPLAYERSCALLBACK EnumCallback,
|
|
LPVOID pContext,
|
|
DWORD dwFlags)
|
|
{
|
|
|
|
DWORD ii;
|
|
HRESULT hr = DP_OK;
|
|
LONG iIndexG;
|
|
LONG iIndexP;
|
|
DPID pid;
|
|
|
|
ParanoiaLock();
|
|
|
|
iIndexG = GetPlayerIndex(dwGroupPid);
|
|
|
|
if (iIndexG == -1 || m_aPlayer[iIndexG].pid != dwGroupPid)
|
|
hr = DPERR_INVALIDPID;
|
|
|
|
if (m_aPlayer[iIndexG].bPlayer)
|
|
hr = DPERR_INVALIDPID;
|
|
|
|
if (hr == DP_OK)
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if ((pid = m_aPlayer[iIndexG].aGroup[ii]) != 0)
|
|
{
|
|
iIndexP = GetPlayerIndex(pid);
|
|
if (iIndexP != -1)
|
|
{
|
|
(EnumCallback)((DPID) m_aPlayer[iIndexP].pid,
|
|
m_aPlayer[iIndexP].chNickName,
|
|
m_aPlayer[iIndexP].chFullName,
|
|
((m_aPlayer[iIndexP].bLocal ) ? DPENUMPLAYERS_LOCAL : DPENUMPLAYERS_REMOTE)
|
|
| ((!m_aPlayer[iIndexP].bPlayer) ? DPENUMPLAYERS_GROUP : 0),
|
|
pContext);
|
|
}
|
|
else
|
|
{
|
|
m_aPlayer[iIndexG].aGroup[ii] = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
return(hr);
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// EnumPlayers - return info on peer connections.
|
|
// ----------------------------------------------------------
|
|
HRESULT CImpIDP_SP::EnumPlayers(
|
|
DWORD dwSessionId,
|
|
LPDPENUMPLAYERSCALLBACK EnumCallback,
|
|
LPVOID pContext,
|
|
DWORD dwFlags)
|
|
{
|
|
|
|
DWORD ii;
|
|
HRESULT hr = DP_OK;
|
|
BOOL bDone = FALSE;
|
|
BOOL bFound = FALSE;
|
|
DWORD dwTimeout;
|
|
|
|
if (dwFlags & DPENUMPLAYERS_PREVIOUS)
|
|
{
|
|
return(DPERR_UNSUPPORTED);
|
|
}
|
|
|
|
if (dwFlags & DPENUMPLAYERS_SESSION)
|
|
{
|
|
//
|
|
// We can't let them call us inside a enumsessions callback anymore.
|
|
//
|
|
if (m_bConnected || m_fpEnumSessions || m_bPlayer0 )
|
|
{
|
|
TSHELL_INFO(TEXT("EnumPlayers: Unsupported."));
|
|
return(DPERR_UNSUPPORTED);
|
|
}
|
|
|
|
if (GetSessionData(dwSessionId))
|
|
{
|
|
SPMSG_GENERIC pMsg;
|
|
UINT BufferLen = sizeof(SPMSG_GENERIC);
|
|
|
|
TSHELL_INFO(TEXT("We are trying to retrieve player info."));
|
|
|
|
m_fpEnumPlayers = EnumCallback;
|
|
m_lpvPlayersContext = pContext;
|
|
|
|
pMsg.dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg.dpHdr.to = 0;
|
|
pMsg.dpHdr.from = 0;
|
|
pMsg.dpHdr.usCount = (USHORT) sizeof(DPMSG_GENERIC);
|
|
pMsg.dpHdr.usGame = 0;
|
|
pMsg.dpHdr.usSeq = NextSequence();
|
|
pMsg.sMsg.dwType = DPSYS_ENUMALLPLAYERS;
|
|
|
|
if (SendTo(m_EnumSocket, &m_NSSockAddr,
|
|
m_SessionAddrLen, (char *) &pMsg, &BufferLen) != 0)
|
|
{
|
|
TSHELL_INFO(TEXT("Enum SendTo failed."));
|
|
}
|
|
|
|
|
|
memset( (LPVOID) &m_spmsgAddPlayer, 0x00, sizeof(SPMSG_ADDPLAYER));
|
|
ResetEvent(m_hPlayerBlkEventMain);
|
|
ResetEvent(m_hPlayerBlkEventRead);
|
|
|
|
//
|
|
// Hard code timeout.
|
|
//
|
|
dwTimeout = 1000;
|
|
while (!bDone)
|
|
{
|
|
DWORD dwRet;
|
|
|
|
|
|
//
|
|
// Wait for DPSYS_ENUMPLAYERRESP to wake us up.
|
|
//
|
|
dwRet = WaitForSingleObject(m_hPlayerBlkEventMain, dwTimeout);
|
|
|
|
//
|
|
// Prevent another DPSYS_ENUMPLAYERRESP before we've processed this one.
|
|
//
|
|
PlayerDataLock();
|
|
|
|
//
|
|
// Reset our wait, and tell DPSYS_ENUMPLAYERRESP it can continue and
|
|
// pick another reply packet up.
|
|
//
|
|
ResetEvent(m_hPlayerBlkEventMain);
|
|
SetEvent(m_hPlayerBlkEventRead);
|
|
|
|
//
|
|
// Only process if our enum sessions is still valid.
|
|
//
|
|
if (m_fpEnumPlayers)
|
|
{
|
|
if( dwRet == WAIT_TIMEOUT)
|
|
{
|
|
m_fpEnumPlayers = NULL;
|
|
bDone = TRUE;
|
|
TSHELL_INFO(TEXT("End EnumPlayers on Timeout."));
|
|
}
|
|
else
|
|
{
|
|
bFound = TRUE;
|
|
TSHELL_INFO(TEXT("Found a remote player."));
|
|
|
|
_try
|
|
{
|
|
if ((m_fpEnumPlayers)(m_spmsgAddPlayer.sMsg.dpId,
|
|
(LPSTR) m_spmsgAddPlayer.sMsg.szShortName,
|
|
(LPSTR) m_spmsgAddPlayer.sMsg.szLongName,
|
|
0,
|
|
m_lpvPlayersContext) == FALSE)
|
|
{
|
|
m_fpEnumPlayers = NULL;
|
|
bDone = TRUE;
|
|
TSHELL_INFO(TEXT("End EnumPlayers."));
|
|
}
|
|
else
|
|
dwTimeout = 250;
|
|
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
m_fpEnumPlayers = NULL;
|
|
bDone = TRUE;
|
|
TSHELL_INFO(TEXT("End EnumPlayers."));
|
|
}
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bDone = TRUE;
|
|
}
|
|
|
|
PlayerDataUnlock();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return(DP_OK);
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("EnumPlayers: bad session ID"));
|
|
return(DPERR_INVALIDOBJECT);
|
|
}
|
|
|
|
}
|
|
|
|
ParanoiaLock();
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
if (m_aPlayer[ii].bValid
|
|
&& ( (m_aPlayer[ii].bPlayer == FALSE && (dwFlags & DPENUMPLAYERS_GROUP))
|
|
|| (m_aPlayer[ii].bPlayer == TRUE && !(dwFlags & DPENUMPLAYERS_NOPLAYERS))))
|
|
{
|
|
|
|
if ((EnumCallback)((DPID) m_aPlayer[ii].pid,
|
|
m_aPlayer[ii].chNickName,
|
|
m_aPlayer[ii].chFullName,
|
|
((m_aPlayer[ii].bLocal ) ? DPENUMPLAYERS_LOCAL : DPENUMPLAYERS_REMOTE)
|
|
| ((!m_aPlayer[ii].bPlayer) ? DPENUMPLAYERS_GROUP : 0),
|
|
pContext) == FALSE)
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
|
|
return(DP_OK);
|
|
}
|
|
|
|
HRESULT CImpIDP_SP::EnumSessions(
|
|
|
|
LPDPSESSIONDESC lpSDesc,
|
|
DWORD dwTimeout,
|
|
LPDPENUMSESSIONSCALLBACK EnumCallback,
|
|
LPVOID lpvContext,
|
|
DWORD dwFlags)
|
|
{
|
|
SPMSG_ENUM Msg;
|
|
UINT BufferLen;
|
|
SOCKADDR SockAddr;
|
|
DWORD dwTimeBegin = GetTickCount();
|
|
DWORD dwTimeNow;
|
|
BOOL bFound = FALSE;
|
|
BOOL bDone = FALSE;
|
|
DWORD ii;
|
|
|
|
if (dwFlags & DPENUMSESSIONS_PREVIOUS)
|
|
return(DPERR_UNSUPPORTED);
|
|
|
|
if (m_bConnected || m_bPlayer0)
|
|
return(DPERR_UNSUPPORTED);
|
|
|
|
|
|
EnumDataLock();
|
|
|
|
if (m_ppSessionArray)
|
|
{
|
|
for (ii = 0; ii < m_dwSessionPrev; ii++)
|
|
lfree(m_ppSessionArray[ii]);
|
|
lfree(m_ppSessionArray);
|
|
m_ppSessionArray = NULL;
|
|
m_dwSessionPrev = 0;
|
|
m_dwSessionAlloc = 0;
|
|
}
|
|
|
|
if (m_bRunEnumReceiveLoop == FALSE)
|
|
{
|
|
m_usGamePort = 0;
|
|
memset(&m_NSSockAddr, 0x00, sizeof(SOCKADDR));
|
|
|
|
ResetEvent(m_hBlockingEvent);
|
|
|
|
m_fpEnumSessions = EnumCallback;
|
|
m_bRunEnumReceiveLoop = TRUE;
|
|
m_lpvSessionContext = lpvContext;
|
|
|
|
m_dwSession = 1;
|
|
|
|
|
|
m_hEnumThread = CreateThread(NULL, 0, StartClientThreadProc,
|
|
(LPVOID) this, 0, &m_dwEnumId);
|
|
|
|
|
|
if ( WaitForSingleObject(m_hBlockingEvent, 9000) == WAIT_TIMEOUT
|
|
|| !m_bEnumSocket)
|
|
{
|
|
EnumDataUnlock();
|
|
return(DPERR_GENERIC);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_fpEnumSessions = EnumCallback;
|
|
m_lpvSessionContext = lpvContext;
|
|
}
|
|
EnumDataUnlock();
|
|
|
|
|
|
Msg.dpHdr.dwConnect1 = DPSYS_KYRA;
|
|
Msg.dpHdr.dwConnect2 = DPSYS_HALL;
|
|
Msg.dwType = DPSYS_ENUM;
|
|
Msg.dpSessionDesc = *lpSDesc;
|
|
Msg.usPort = 0;
|
|
Msg.dwUnique = 0;
|
|
Msg.usVerMajor = DPVERSION_MAJOR;
|
|
Msg.usVerMinor = DPVERSION_MINOR;
|
|
|
|
memset(&SockAddr, 0, sizeof(SOCKADDR));
|
|
|
|
// Depending on the address family specified, we'll try to find the
|
|
// Name Server just a little differently.
|
|
//
|
|
if (GetSockAddress(&SockAddr, NULL, DPNS_PORT, NULL, TRUE))
|
|
{
|
|
BufferLen = sizeof(SPMSG_ENUM);
|
|
|
|
memset( (LPVOID) &m_spmsgEnum, 0x00, sizeof(SPMSG_ENUM));
|
|
ResetEvent(m_hEnumBlkEventMain);
|
|
ResetEvent(m_hEnumBlkEventRead);
|
|
|
|
if (SendTo(m_EnumSocket, &SockAddr, sizeof(SockAddr), (char *) &Msg, &BufferLen) != 0)
|
|
{
|
|
TSHELL_INFO(TEXT("Enum SendTo failed."));
|
|
}
|
|
|
|
// TSHELL_INFO(TEXT("Enum SendTo success."));
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Didn't get a proper sock address."));
|
|
return(DPERR_GENERIC);
|
|
}
|
|
|
|
while(!bDone)
|
|
{
|
|
DWORD dwRet;
|
|
//
|
|
// Wait for DPSYS_ENUM_REPLY to wake us up.
|
|
//
|
|
dwRet = WaitForSingleObject(m_hEnumBlkEventMain, dwTimeout);
|
|
|
|
//
|
|
// Prevent another DPSYS_ENUM_REPLY before we've processed this one.
|
|
//
|
|
EnumDataLock();
|
|
DBG_INFO((DBGARG, TEXT("Tick %d"), GetTickCount()));
|
|
|
|
//
|
|
// Reset our wait, and tell DPSYS_ENUM_REPLY it can continue and
|
|
// pick another reply packet up.
|
|
//
|
|
ResetEvent(m_hEnumBlkEventMain);
|
|
SetEvent(m_hEnumBlkEventRead);
|
|
|
|
|
|
//
|
|
// Only process if our enum sessions is still valid.
|
|
//
|
|
if (m_fpEnumSessions)
|
|
{
|
|
if( dwRet == WAIT_TIMEOUT)
|
|
{
|
|
memset( (LPVOID) &m_spmsgEnum, 0x00, sizeof(SPMSG_ENUM));
|
|
_try
|
|
{
|
|
if ((m_fpEnumSessions)(NULL, m_lpvSessionContext, &dwTimeout, DPESC_TIMEDOUT) == FALSE)
|
|
{
|
|
m_fpEnumSessions = NULL;
|
|
bDone = TRUE;
|
|
TSHELL_INFO(TEXT("End EnumSessions."));
|
|
}
|
|
else
|
|
{
|
|
dwTimeBegin = GetTickCount();
|
|
}
|
|
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
m_fpEnumSessions = NULL;
|
|
bDone = TRUE;
|
|
TSHELL_INFO(TEXT("Exception encountered."));
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
bFound = TRUE;
|
|
|
|
DBG_INFO((DBGARG, TEXT("Session %d Name %s"),
|
|
m_spmsgEnum.dpSessionDesc.dwSession,
|
|
m_spmsgEnum.dpSessionDesc.szSessionName));
|
|
|
|
_try
|
|
{
|
|
if ((m_fpEnumSessions)((LPDPSESSIONDESC) &m_spmsgEnum.dpSessionDesc,
|
|
m_lpvSessionContext, NULL, 0 ) == FALSE)
|
|
{
|
|
m_fpEnumSessions = NULL;
|
|
bDone = TRUE;
|
|
TSHELL_INFO(TEXT("End EnumSessions."));
|
|
}
|
|
else
|
|
{
|
|
if (dwTimeout != 0xffffffff)
|
|
{
|
|
dwTimeNow = GetTickCount();
|
|
if ( (dwTimeNow - dwTimeBegin) > dwTimeout)
|
|
dwTimeout = 0;
|
|
else
|
|
{
|
|
dwTimeout -= (dwTimeNow - dwTimeBegin);
|
|
dwTimeBegin = dwTimeNow;
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
_except(EXCEPTION_EXECUTE_HANDLER)
|
|
{
|
|
m_fpEnumSessions = NULL;
|
|
bDone = TRUE;
|
|
TSHELL_INFO(TEXT("Exception encountered."));
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
bDone = TRUE;
|
|
}
|
|
|
|
EnumDataUnlock();
|
|
DBG_INFO((DBGARG, TEXT("Tick %d"), GetTickCount()));
|
|
}
|
|
|
|
return((bFound) ? DP_OK : DPERR_NOSESSIONS);
|
|
}
|
|
|
|
VOID CImpIDP_SP::ISend(
|
|
LONG iFrom,
|
|
LONG iTo,
|
|
DWORD dwFlags,
|
|
LPVOID lpvBuffer,
|
|
DWORD dwBuffSize)
|
|
{
|
|
|
|
MSG_BUILDER *pMsg;
|
|
DWORD ii;
|
|
LONG iIndexT;
|
|
|
|
ParanoiaLock();
|
|
|
|
if (m_aPlayer[iTo].bPlayer == FALSE)
|
|
{
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if (m_aPlayer[iTo].aGroup[ii])
|
|
{
|
|
if ((iIndexT = GetPlayerIndex(m_aPlayer[iTo].aGroup[ii])) != -1)
|
|
ISend(iFrom, iIndexT, dwFlags, lpvBuffer, dwBuffSize);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (m_aPlayer[iTo].bLocal)
|
|
{
|
|
AddMessage(lpvBuffer,
|
|
dwBuffSize,
|
|
m_aPlayer[iTo].pid,
|
|
m_aPlayer[iFrom].pid,
|
|
dwFlags & DPSEND_HIGHPRIORITY);
|
|
|
|
}
|
|
else
|
|
{
|
|
char chBuffer[MAX_MSG];
|
|
|
|
pMsg = (MSG_BUILDER *) chBuffer;
|
|
pMsg->dpHdr.usCookie = (dwFlags & DPSEND_HIGHPRIORITY) ? DPSYS_HIGH : DPSYS_USER;
|
|
pMsg->dpHdr.to = (USHORT) m_aPlayer[iTo].pid;
|
|
pMsg->dpHdr.from = (USHORT) m_aPlayer[iFrom].pid;
|
|
pMsg->dpHdr.usCount = (USHORT) dwBuffSize;
|
|
pMsg->dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
memcpy( pMsg->chMsgCompose, lpvBuffer, dwBuffSize);
|
|
PostPlayerMessage( iTo, (LPVOID) pMsg, sizeof(DPHDR) + dwBuffSize);
|
|
}
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// Send - transmit data over socket.
|
|
// ----------------------------------------------------------
|
|
HRESULT CImpIDP_SP::Send(
|
|
DPID from,
|
|
DPID to,
|
|
DWORD dwFlags,
|
|
LPVOID lpvBuffer,
|
|
DWORD dwBuffSize)
|
|
{
|
|
DWORD ii;
|
|
LONG iFrom;
|
|
BOOL bSent = FALSE;
|
|
|
|
if (from == 0)
|
|
{
|
|
return(DPERR_INVALIDPID);
|
|
}
|
|
|
|
if (dwBuffSize > MAX_MSG)
|
|
return(DPERR_SENDTOOBIG);
|
|
|
|
ParanoiaLock();
|
|
iFrom = GetPlayerIndex(from);
|
|
|
|
#ifdef DEBUG
|
|
DBG_INFO((DBGARG, TEXT("Send From Pid %d Player Index %d"), from, iFrom));
|
|
|
|
if (iFrom == -1)
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
DBG_INFO((DBGARG, TEXT("Index %d Valid %d Pid %d Local %d"),
|
|
ii,
|
|
m_aPlayer[ii].bValid,
|
|
m_aPlayer[ii].pid,
|
|
m_aPlayer[ii].bLocal));
|
|
}
|
|
#endif
|
|
|
|
|
|
if (iFrom == -1 || ! m_aPlayer[iFrom].bLocal)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(DPERR_INVALIDPID);
|
|
}
|
|
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
if (m_aPlayer[ii].bValid && m_aPlayer[ii].pid != from)
|
|
{
|
|
if ( (to == 0 && m_aPlayer[ii].bPlayer == TRUE)
|
|
|| m_aPlayer[ii].pid == to)
|
|
{
|
|
ISend(iFrom, ii, dwFlags, lpvBuffer, dwBuffSize);
|
|
bSent = TRUE;
|
|
}
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
|
|
return(bSent ? DP_OK : DPERR_INVALIDPID);
|
|
}
|
|
|
|
// ----------------------------------------------------------
|
|
// Receive - receive message
|
|
// ----------------------------------------------------------
|
|
HRESULT CImpIDP_SP::Receive(
|
|
LPDPID pidfrom,
|
|
LPDPID pidto,
|
|
DWORD dwFlags,
|
|
LPVOID lpvBuffer,
|
|
LPDWORD lpdwSize)
|
|
{
|
|
HRESULT hr;
|
|
LONG iIndex;
|
|
BOOL bb;
|
|
|
|
ParanoiaLock();
|
|
|
|
bb = TRUE;
|
|
|
|
if (dwFlags & DPRECEIVE_TOPLAYER)
|
|
{
|
|
iIndex = GetPlayerIndex(*pidto);
|
|
|
|
if (iIndex == -1 || m_aPlayer[iIndex].bPlayer == FALSE)
|
|
bb = FALSE;
|
|
}
|
|
|
|
if ((dwFlags & DPRECEIVE_FROMPLAYER) && *pidfrom != 0)
|
|
{
|
|
iIndex = GetPlayerIndex(*pidfrom);
|
|
|
|
if (iIndex == -1 || m_aPlayer[iIndex].bPlayer == FALSE)
|
|
bb = FALSE;
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
|
|
if (bb == FALSE)
|
|
{
|
|
return(DPERR_INVALIDPID);
|
|
}
|
|
|
|
hr = GetQMessage(lpvBuffer, lpdwSize, pidto, pidfrom, dwFlags,
|
|
dwFlags & DPRECEIVE_PEEK);
|
|
return(hr);
|
|
}
|
|
|
|
|
|
HRESULT CImpIDP_SP::SetPlayerName(
|
|
DPID pid,
|
|
LPSTR lpFriendlyName,
|
|
LPSTR lpFormalName,
|
|
BOOL bPlayer)
|
|
{
|
|
SPMSG_ADDPLAYER spmsg_addplayer;
|
|
SPMSG_ADDPLAYER *pMsg;
|
|
|
|
|
|
//
|
|
// Send DPSYS_SETPLAYER to nameserver.
|
|
//
|
|
|
|
ParanoiaLock();
|
|
LONG iIndex = GetPlayerIndex(pid);
|
|
|
|
if (iIndex == -1 || m_aPlayer[iIndex].bPlayer != bPlayer)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(DPERR_INVALIDPLAYER);
|
|
}
|
|
|
|
|
|
lstrcpyn( m_aPlayer[iIndex].chNickName, lpFriendlyName, DPSHORTNAMELEN);
|
|
lstrcpyn( m_aPlayer[iIndex].chFullName, lpFormalName , DPLONGNAMELEN);
|
|
|
|
pMsg = &spmsg_addplayer;
|
|
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = SIZE_ADDPLAYER;
|
|
pMsg->dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
pMsg->sMsg.dwType = DPSYS_SETPLAYER;
|
|
pMsg->sMsg.dwPlayerType = bPlayer;
|
|
pMsg->sMsg.dpId = m_aPlayer[iIndex].pid;
|
|
pMsg->sMsg.dwCurrentPlayers = m_dpDesc.dwCurrentPlayers;
|
|
|
|
lstrcpy( pMsg->sMsg.szShortName, lpFriendlyName);
|
|
lstrcpy( pMsg->sMsg.szLongName, lpFormalName);
|
|
memcpy( &pMsg->sockaddr, &m_aPlayer[iIndex].sockaddr, sizeof(SOCKADDR));
|
|
|
|
if (m_bPlayer0)
|
|
{
|
|
LocalMsg( iIndex, (LPVOID) pMsg, sizeof(DPMSG_ADDPLAYER));
|
|
PostGameMessage( (LPVOID) pMsg, sizeof(SPMSG_ADDPLAYER));
|
|
}
|
|
else
|
|
{
|
|
PostNSMessage( pMsg, sizeof(SPMSG_ADDPLAYER));
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
return(DP_OK);
|
|
}
|
|
|
|
HRESULT CImpIDP_SP::SaveSession(LPVOID lpv, LPDWORD lpdw)
|
|
{
|
|
return(DPERR_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
HRESULT CImpIDP_SP::SetPrevSession(LPSTR lpName, LPVOID lpv, DWORD dw)
|
|
{
|
|
return(DPERR_UNSUPPORTED);
|
|
}
|
|
|
|
|
|
HRESULT CImpIDP_SP::SetPrevPlayer(LPSTR lpName, LPVOID lpv, DWORD dw)
|
|
{
|
|
//
|
|
//
|
|
// This doesn't make sense for a serial point to point SP.
|
|
//
|
|
TSHELL_INFO( TEXT("not currently supported") );
|
|
return(DPERR_UNSUPPORTED);
|
|
}
|
|
|
|
HRESULT CImpIDP_SP::EnableNewPlayers(BOOL bEnable)
|
|
{
|
|
//
|
|
// Implementation not set, and won't follow this calling convention.
|
|
// ignore for now.
|
|
//
|
|
SPMSG_ENABLEPLAYER spmsg_enableplayer;
|
|
SPMSG_ENABLEPLAYER *pMsg = &spmsg_enableplayer;
|
|
|
|
m_bEnablePlayerAdd = bEnable;
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = sizeof(DPMSG_ENABLEPLAYER);
|
|
pMsg->dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
pMsg->sMsg.dwType = DPSYS_ENABLEPLAYER;
|
|
pMsg->sMsg.bEnable = bEnable;
|
|
|
|
if (! m_bPlayer0)
|
|
PostNSMessage( pMsg, sizeof(SPMSG_ENABLEPLAYER));
|
|
else
|
|
PostGameMessage( pMsg, sizeof(SPMSG_ENABLEPLAYER));
|
|
|
|
|
|
return(DP_OK);
|
|
}
|
|
|
|
HRESULT CImpIDP_SP::GetPlayerCaps(
|
|
DPID pid,
|
|
LPDPCAPS lpDPCaps)
|
|
{
|
|
LONG iIndex = GetPlayerIndex(pid);
|
|
|
|
if (iIndex == -1 || m_aPlayer[iIndex].bPlayer == FALSE)
|
|
return(DPERR_INVALIDPID);
|
|
|
|
*lpDPCaps = m_dpcaps;
|
|
if (m_aPlayer[iIndex].bLocal)
|
|
lpDPCaps->dwLatency = 1;
|
|
|
|
return(DP_OK);
|
|
}
|
|
|
|
HRESULT CImpIDP_SP::GetMessageCount(DPID pid, LPDWORD lpdw )
|
|
{
|
|
//
|
|
// Return count for this pid, if it is a local player we have
|
|
// been tracking with Interlock calls.
|
|
//
|
|
LONG iIndex = GetPlayerIndex((DPID) pid);
|
|
|
|
if (iIndex == -1 || m_aPlayer[iIndex].bPlayer == FALSE)
|
|
return(DPERR_INVALIDPLAYER);
|
|
|
|
if (m_aPlayer[iIndex].bLocal == FALSE)
|
|
return(DPERR_INVALIDPLAYER);
|
|
|
|
*lpdw = GetPlayerCount((DPID) pid);
|
|
return(DP_OK);
|
|
|
|
}
|
|
HRESULT CImpIDP_SP::AddPlayerToGroup(
|
|
DPID dpIdGroup,
|
|
DPID dpIdPlayer)
|
|
{
|
|
DPMSG_GROUPADD dpGAdd;
|
|
LONG iIndexG;
|
|
LONG iIndexP;
|
|
DWORD ii;
|
|
SPMSG_GROUPADD spmsg_groupadd;
|
|
SPMSG_GROUPADD *pMsg = &spmsg_groupadd;
|
|
|
|
ParanoiaLock();
|
|
|
|
iIndexG = GetPlayerIndex(dpIdGroup);
|
|
iIndexP = GetPlayerIndex(dpIdPlayer);
|
|
|
|
if ( iIndexG == -1
|
|
|| m_aPlayer[iIndexG].bPlayer == TRUE
|
|
|| iIndexP == -1
|
|
|| m_aPlayer[iIndexP].bPlayer == FALSE)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(DPERR_INVALIDPID);
|
|
}
|
|
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if (m_aPlayer[iIndexG].aGroup[ii] == m_aPlayer[iIndexP].pid)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(DPERR_INVALIDPID);
|
|
}
|
|
}
|
|
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if (m_aPlayer[iIndexG].aGroup[ii] == 0)
|
|
{
|
|
dpGAdd.dwType = DPSYS_ADDPLAYERTOGROUP;
|
|
dpGAdd.dpIdGroup = m_aPlayer[iIndexG].pid;
|
|
dpGAdd.dpIdPlayer = m_aPlayer[iIndexP].pid;
|
|
|
|
ParanoiaUnlock();
|
|
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = sizeof(DPMSG_GROUPADD);
|
|
pMsg->dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
|
|
memcpy( (LPVOID) &pMsg->sMsg, (LPVOID) &dpGAdd, sizeof(DPMSG_GROUPADD));
|
|
|
|
if (m_bPlayer0)
|
|
{
|
|
m_aPlayer[iIndexG].aGroup[ii] = m_aPlayer[iIndexP].pid;
|
|
LocalMsg(iIndexG, (LPVOID) &dpGAdd, sizeof(DPMSG_GROUPADD));
|
|
PostGameMessage( (LPVOID) pMsg, sizeof(SPMSG_GROUPADD));
|
|
}
|
|
else
|
|
{
|
|
PostNSMessage( pMsg, sizeof(SPMSG_GROUPADD));
|
|
}
|
|
return(DP_OK);
|
|
}
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
return(DPERR_GENERIC);
|
|
}
|
|
|
|
HRESULT CImpIDP_SP::DeletePlayerFromGroup(
|
|
DPID dpIdGroup,
|
|
DPID dpIdPlayer)
|
|
{
|
|
DPMSG_GROUPADD dpGAdd;
|
|
LONG iIndexG;
|
|
LONG iIndexP;
|
|
DWORD ii;
|
|
SPMSG_GROUPADD spmsg_groupadd;
|
|
SPMSG_GROUPADD *pMsg = &spmsg_groupadd;
|
|
|
|
ParanoiaLock();
|
|
|
|
iIndexG = GetPlayerIndex(dpIdGroup);
|
|
iIndexP = GetPlayerIndex(dpIdPlayer);
|
|
|
|
if ( iIndexG == -1
|
|
|| m_aPlayer[iIndexG].bPlayer == TRUE
|
|
|| iIndexP == -1
|
|
|| m_aPlayer[iIndexP].bPlayer == FALSE)
|
|
{
|
|
ParanoiaUnlock();
|
|
return(DPERR_INVALIDPID);
|
|
}
|
|
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if (m_aPlayer[iIndexG].aGroup[ii] == m_aPlayer[iIndexP].pid)
|
|
{
|
|
dpGAdd.dwType = DPSYS_DELETEPLAYERFROMGRP;
|
|
dpGAdd.dpIdGroup = m_aPlayer[iIndexG].pid;
|
|
dpGAdd.dpIdPlayer = m_aPlayer[iIndexP].pid;
|
|
|
|
m_aPlayer[iIndexG].aGroup[ii] = 0;
|
|
|
|
ParanoiaUnlock();
|
|
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = sizeof(DPMSG_GROUPADD);
|
|
pMsg->dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
|
|
memcpy( (LPVOID) &pMsg->sMsg, (LPVOID) &dpGAdd, sizeof(DPMSG_GROUPADD));
|
|
|
|
if (m_bPlayer0)
|
|
{
|
|
LocalMsg(iIndexG, (LPVOID) &dpGAdd, sizeof(DPMSG_GROUPADD));
|
|
PostGameMessage( (LPVOID) pMsg, sizeof(SPMSG_GROUPADD));
|
|
}
|
|
else
|
|
{
|
|
PostNSMessage( pMsg, sizeof(SPMSG_GROUPADD));
|
|
}
|
|
return(DP_OK);
|
|
}
|
|
}
|
|
ParanoiaUnlock();
|
|
return(DPERR_INVALIDPID);
|
|
}
|
|
|
|
VOID CImpIDP_SP::HandleMessage(LPVOID lpv, DWORD dwSize, SOCKADDR *pSAddr, INT SockAddrLen)
|
|
{
|
|
DPHDR *pHdr;
|
|
BOOL bHigh = FALSE;
|
|
DPID pidTo, pidFrom;
|
|
DWORD ii;
|
|
SPMSG_ADDPLAYER *pAddPlayer;
|
|
LONG iIndex;
|
|
|
|
pHdr = (DPHDR *) lpv;
|
|
|
|
|
|
// TSHELL_INFO(TEXT("HandleMessage entered."));
|
|
|
|
switch(pHdr->usCookie)
|
|
{
|
|
default:
|
|
TSHELL_INFO(TEXT("Unknown message value"));
|
|
break;
|
|
|
|
case DPSYS_HIGH:
|
|
bHigh = TRUE;
|
|
//
|
|
// Fall Through!
|
|
//
|
|
case DPSYS_USER:
|
|
pidTo = 0x00ff & ((DPID) pHdr->to);
|
|
pidFrom = 0x00ff & ((DPID) pHdr->from);
|
|
dwSize = (DWORD) ((DPID) pHdr->usCount);
|
|
|
|
iIndex = GetPlayerIndex(pidTo);
|
|
|
|
if ( pidTo == 0
|
|
|| iIndex != -1)
|
|
{
|
|
AddMessage((LPVOID) (((LPBYTE) lpv) + sizeof(DPHDR)), dwSize,
|
|
pidTo, pidFrom, bHigh);
|
|
}
|
|
|
|
iIndex = GetPlayerIndex(pidFrom);
|
|
|
|
if ( pidFrom != 0
|
|
&& (iIndex == -1))
|
|
{
|
|
SPMSG_GETPLAYER spmsg_getplayer;
|
|
SPMSG_GETPLAYER *pMsg = &spmsg_getplayer;
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = sizeof(DPMSG_GETPLAYER);
|
|
pMsg->dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
pMsg->sMsg.dwType = DPSYS_GETPLAYER;
|
|
pMsg->sMsg.dpId = pidFrom;
|
|
PostNSMessage((LPVOID) pMsg, sizeof(SPMSG_GETPLAYER));
|
|
}
|
|
break;
|
|
|
|
case DPSYS_SYS:
|
|
TSHELL_INFO(TEXT("HandleMessage System Message."));
|
|
switch(((SPMSG_GENERIC *)lpv)->sMsg.dwType)
|
|
{
|
|
default:
|
|
|
|
DBG_INFO((DBGARG, TEXT("Unknown Type %x"), ((SPMSG_GENERIC *)lpv)->sMsg.dwType));
|
|
break;
|
|
|
|
case DPSYS_ENABLEPLAYER:
|
|
{
|
|
SPMSG_ENABLEPLAYER *pMsg;
|
|
|
|
pMsg = (SPMSG_ENABLEPLAYER *) lpv;
|
|
if (pMsg->dpHdr.usCount == sizeof(DPMSG_ENABLEPLAYER))
|
|
{
|
|
if (m_bPlayer0 && m_bEnablePlayerAdd != pMsg->sMsg.bEnable)
|
|
PostGameMessage( (LPVOID) pMsg, sizeof(SPMSG_ENABLEPLAYER));
|
|
|
|
m_bEnablePlayerAdd = pMsg->sMsg.bEnable;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DPSYS_DELETEPLAYERFROMGRP:
|
|
case DPSYS_ADDPLAYERTOGROUP:
|
|
case DPSYS_SETGROUPPLAYER:
|
|
{
|
|
SPMSG_GROUPADD *pMsg;
|
|
LONG iIndexG;
|
|
LONG iIndexP;
|
|
|
|
pMsg = (SPMSG_GROUPADD *) lpv;
|
|
if (pMsg->dpHdr.usCount == sizeof(DPMSG_GROUPADD))
|
|
{
|
|
ParanoiaLock();
|
|
iIndexG = GetPlayerIndex(pMsg->sMsg.dpIdGroup);
|
|
iIndexP = GetPlayerIndex(pMsg->sMsg.dpIdPlayer);
|
|
if ( iIndexG == -1
|
|
|| m_aPlayer[iIndexG].bPlayer == TRUE
|
|
|| iIndexP == -1
|
|
|| m_aPlayer[iIndexP].bPlayer == FALSE)
|
|
{
|
|
TSHELL_INFO(TEXT("Invalid GroupAdd message."));
|
|
}
|
|
else
|
|
{
|
|
if ( pMsg->sMsg.dwType == DPSYS_ADDPLAYERTOGROUP
|
|
|| pMsg->sMsg.dwType == DPSYS_SETGROUPPLAYER)
|
|
{
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
if (m_aPlayer[iIndexG].aGroup[ii] == 0)
|
|
{
|
|
m_aPlayer[iIndexG].aGroup[ii] = m_aPlayer[iIndexP].pid;
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
if (m_aPlayer[iIndexG].aGroup[ii] == m_aPlayer[iIndexP].pid)
|
|
{
|
|
m_aPlayer[iIndexG].aGroup[ii] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
if (pMsg->sMsg.dwType != DPSYS_SETGROUPPLAYER)
|
|
{
|
|
LocalMsg(iIndexG, (LPVOID) &pMsg->sMsg, sizeof(DPMSG_GROUPADD));
|
|
|
|
if (m_bPlayer0)
|
|
{
|
|
PostGameMessage( (LPVOID) pMsg, sizeof(SPMSG_GROUPADD));
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Invalid size on system message"));
|
|
}
|
|
|
|
|
|
}
|
|
break;
|
|
|
|
|
|
|
|
case DPSYS_SENDDESC:
|
|
{
|
|
SPMSG_SENDDESC *pMsg;
|
|
|
|
pMsg = (SPMSG_SENDDESC *) lpv;
|
|
if (pMsg->dpHdr.usCount == SIZE_SENDDESC)
|
|
{
|
|
memcpy( (LPVOID) &m_dpDesc, (LPVOID) &pMsg->sMsg.dpDesc, sizeof(m_dpDesc));
|
|
// DBG_INFO((DBGARG, TEXT("New Description. Current Players %d"),
|
|
// m_dpDesc.dwCurrentPlayers));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DPSYS_PING:
|
|
{
|
|
SPMSG_PING *pMsg;
|
|
|
|
pMsg = (SPMSG_PING *) lpv;
|
|
if (pMsg->dpHdr.usCount == SIZE_PING)
|
|
{
|
|
if (pMsg->dwTicks == m_dwPingSent)
|
|
{
|
|
m_dpcaps.dwLatency = (GetTickCount() - m_dwPingSent) /2;
|
|
m_dwPingSent = 0;
|
|
// TSHELL_INFO(TEXT("Latency Accepted from our Ping."));
|
|
}
|
|
else
|
|
{
|
|
SPMSG_PING spmsg_ping;
|
|
SPMSG_PING *pMsg2 = &spmsg_ping;
|
|
UINT uiSize = sizeof(SPMSG_PING);
|
|
|
|
memcpy( (LPVOID) pMsg2, (LPVOID) pMsg, sizeof(SPMSG_PING));
|
|
SendTo(m_ClientSocket, pSAddr, SockAddrLen, (char *)pMsg2, &uiSize);
|
|
// TSHELL_INFO(TEXT("Return Ping."));
|
|
|
|
}
|
|
TSHELL_INFO(TEXT("Ping Recieved."));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DPSYS_SETPLAYER:
|
|
{
|
|
SPMSG_SETPLAYER *pSetPlayer;
|
|
|
|
pSetPlayer = (SPMSG_SETPLAYER *) lpv;
|
|
|
|
TSHELL_INFO(TEXT("Received SETPLAYER message"));
|
|
if (pSetPlayer->dpHdr.usCount == SIZE_SETPLAYER)
|
|
{
|
|
ParanoiaLock();
|
|
iIndex = GetPlayerIndex(pSetPlayer->sMsg.dpId);
|
|
if (iIndex != -1)
|
|
{
|
|
if (m_aPlayer[iIndex].bPlayer == (BOOL) pSetPlayer->sMsg.dwPlayerType)
|
|
{
|
|
lstrcpyn( m_aPlayer[iIndex].chNickName, pSetPlayer->sMsg.szShortName, DPSHORTNAMELEN);
|
|
lstrcpyn( m_aPlayer[iIndex].chFullName, pSetPlayer->sMsg.szLongName , DPLONGNAMELEN);
|
|
m_dpDesc.dwCurrentPlayers = pSetPlayer->sMsg.dwCurrentPlayers;
|
|
}
|
|
TSHELL_INFO(TEXT("Name change through SETPLAYER"));
|
|
|
|
|
|
}
|
|
else if ( !m_bPlayer0
|
|
&& ((iIndex = FindInvalidIndex()) != -1))
|
|
{
|
|
if (!pSetPlayer->sMsg.dwPlayerType)
|
|
{
|
|
m_aPlayer[iIndex].aGroup = (DPID *) lmalloc(sizeof(DPID) * MAX_PLAYERS);
|
|
if (m_aPlayer[iIndex].aGroup != NULL)
|
|
memset(m_aPlayer[iIndex].aGroup, 0x00, sizeof(DPID) * MAX_PLAYERS);
|
|
else
|
|
pSetPlayer->sMsg.dwPlayerType = TRUE; // Critical failure.
|
|
}
|
|
|
|
lstrcpy( m_aPlayer[iIndex].chNickName, pSetPlayer->sMsg.szShortName);
|
|
lstrcpy( m_aPlayer[iIndex].chFullName, pSetPlayer->sMsg.szLongName);
|
|
m_aPlayer[iIndex].bValid = TRUE;
|
|
m_aPlayer[iIndex].bPlayer = pSetPlayer->sMsg.dwPlayerType;
|
|
m_aPlayer[iIndex].bLocal = FALSE;
|
|
memcpy(&m_aPlayer[iIndex].sockaddr, pSAddr, sizeof(SOCKADDR));
|
|
|
|
m_aPlayer[iIndex].pid = pSetPlayer->sMsg.dpId;
|
|
m_dpDesc.dwCurrentPlayers = pSetPlayer->sMsg.dwCurrentPlayers;
|
|
|
|
TSHELL_INFO(TEXT("Remote player updated with SETPLAYER."));
|
|
}
|
|
|
|
if (iIndex != -1)
|
|
{
|
|
if (pSetPlayer->sockaddr.sa_family == 0)
|
|
memcpy(&m_aPlayer[iIndex].sockaddr, &m_NSSockAddr, sizeof(SOCKADDR));
|
|
else
|
|
memcpy(&m_aPlayer[iIndex].sockaddr, &pSetPlayer->sockaddr, sizeof(SOCKADDR));
|
|
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DPSYS_ADDPLAYER:
|
|
{
|
|
pAddPlayer = (SPMSG_ADDPLAYER *) lpv;
|
|
|
|
if (pAddPlayer->dpHdr.usCount == SIZE_ADDPLAYER)
|
|
{
|
|
if (m_bEnablePlayerAdd == FALSE && pAddPlayer->sMsg.dwPlayerType == TRUE)
|
|
break;
|
|
|
|
if (m_bPlayer0)
|
|
{
|
|
|
|
if (pAddPlayer->dpHdr.usSeq == m_usSeqSys)
|
|
{
|
|
TSHELL_INFO(TEXT("We have seen this before."));
|
|
//
|
|
// BUGBUG, search our list and try to find a player
|
|
// we have already created and give them that.
|
|
//
|
|
break;
|
|
}
|
|
|
|
ParanoiaLock();
|
|
|
|
TSHELL_INFO(TEXT("Begin AddPlayer Processing Player 0."));
|
|
if ( m_dpDesc.dwMaxPlayers >= m_dpDesc.dwCurrentPlayers
|
|
&& pAddPlayer->sMsg.dpId == 0
|
|
&& ((iIndex = FindInvalidIndex()) != -1))
|
|
{
|
|
|
|
SPMSG_ADDPLAYER spmsg_addplayer;
|
|
SPMSG_ADDPLAYER *pReplyMsg = &spmsg_addplayer;
|
|
|
|
if (!pAddPlayer->sMsg.dwPlayerType)
|
|
{
|
|
m_aPlayer[iIndex].aGroup = (DPID *) lmalloc(sizeof(DPID) * MAX_PLAYERS);
|
|
if (m_aPlayer[iIndex].aGroup != NULL)
|
|
memset(m_aPlayer[iIndex].aGroup, 0x00, sizeof(DPID) * MAX_PLAYERS);
|
|
else
|
|
pAddPlayer->sMsg.dwPlayerType = TRUE; // Critical failure.
|
|
}
|
|
|
|
pAddPlayer->sMsg.dwCurrentPlayers = ++m_dpDesc.dwCurrentPlayers;
|
|
m_aPlayer[iIndex].pid = (DPID) m_dwNextPlayer++;
|
|
lstrcpy( m_aPlayer[iIndex].chNickName, pAddPlayer->sMsg.szShortName);
|
|
lstrcpy( m_aPlayer[iIndex].chFullName, pAddPlayer->sMsg.szLongName);
|
|
m_aPlayer[iIndex].bValid = TRUE;
|
|
m_aPlayer[iIndex].bPlayer = pAddPlayer->sMsg.dwPlayerType;
|
|
m_aPlayer[iIndex].bLocal = FALSE;
|
|
memcpy(&m_aPlayer[iIndex].sockaddr, pSAddr, sizeof(SOCKADDR));
|
|
memcpy(&pAddPlayer->sockaddr, pSAddr, sizeof(SOCKADDR));
|
|
|
|
|
|
pAddPlayer->sMsg.dpId = m_aPlayer[iIndex].pid;
|
|
|
|
TSHELL_INFO(TEXT("Replying to AddPlayer message."));
|
|
m_usSeqSys = pAddPlayer->dpHdr.usSeq;
|
|
pAddPlayer->dpHdr.usSeq = NextSequence();
|
|
memcpy((LPVOID) pReplyMsg, (LPVOID) pAddPlayer,
|
|
sizeof(SPMSG_ADDPLAYER));
|
|
|
|
PostGameMessage( (LPVOID) pReplyMsg, sizeof(SPMSG_ADDPLAYER));
|
|
|
|
LocalMsg(iIndex, &pAddPlayer->sMsg, sizeof(DPMSG_ADDPLAYER));
|
|
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Ignoring message, it will timeout."));
|
|
}
|
|
ParanoiaUnlock();
|
|
|
|
}
|
|
//
|
|
// Ignore it it we already know about this player.
|
|
//
|
|
else if (GetPlayerIndex(pAddPlayer->sMsg.dpId) == -1)
|
|
{
|
|
TSHELL_INFO(TEXT("Begin AddPlayer Processing Remote."));
|
|
|
|
ParanoiaLock();
|
|
|
|
#ifdef DEBUG
|
|
if (m_dpDesc.dwCurrentPlayers != pAddPlayer->sMsg.dwCurrentPlayers)
|
|
{
|
|
DBG_INFO((DBGARG, TEXT("Adjusting local count of players from %d to %d"),
|
|
m_dpDesc.dwCurrentPlayers,
|
|
pAddPlayer->sMsg.dwCurrentPlayers));
|
|
}
|
|
#endif
|
|
|
|
|
|
m_dpDesc.dwCurrentPlayers = pAddPlayer->sMsg.dwCurrentPlayers;
|
|
|
|
iIndex = FindInvalidIndex();
|
|
|
|
if ((iIndex = FindInvalidIndex()) != -1)
|
|
{
|
|
if (!pAddPlayer->sMsg.dwPlayerType)
|
|
{
|
|
m_aPlayer[iIndex].aGroup = (DPID *) lmalloc(sizeof(DPID) * MAX_PLAYERS);
|
|
if (m_aPlayer[iIndex].aGroup != NULL)
|
|
memset(m_aPlayer[iIndex].aGroup, 0x00, sizeof(DPID) * MAX_PLAYERS);
|
|
else
|
|
pAddPlayer->sMsg.dwPlayerType = TRUE; // Critical failure.
|
|
}
|
|
|
|
lstrcpy( m_aPlayer[iIndex].chNickName, pAddPlayer->sMsg.szShortName);
|
|
lstrcpy( m_aPlayer[iIndex].chFullName, pAddPlayer->sMsg.szLongName);
|
|
m_aPlayer[iIndex].bValid = TRUE;
|
|
m_aPlayer[iIndex].bPlayer = pAddPlayer->sMsg.dwPlayerType;
|
|
|
|
if (pAddPlayer->sockaddr.sa_family == 0)
|
|
memcpy(&m_aPlayer[iIndex].sockaddr, &m_NSSockAddr, sizeof(SOCKADDR));
|
|
else
|
|
memcpy(&m_aPlayer[iIndex].sockaddr, &pAddPlayer->sockaddr, sizeof(SOCKADDR));
|
|
|
|
m_aPlayer[iIndex].pid = pAddPlayer->sMsg.dpId;
|
|
|
|
if (m_hNewPlayerEvent && pAddPlayer->dwUnique == m_dwUnique)
|
|
{
|
|
m_aPlayer[iIndex].bLocal = TRUE;
|
|
m_iPlayerIndex = iIndex;
|
|
SetEvent(m_hNewPlayerEvent);
|
|
}
|
|
else
|
|
{
|
|
m_aPlayer[iIndex].bLocal = FALSE;
|
|
}
|
|
LocalMsg(iIndex, &pAddPlayer->sMsg, sizeof(DPMSG_ADDPLAYER));
|
|
}
|
|
ParanoiaUnlock();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Invalid size on system message ADDPLAYER"));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DPSYS_DELETEGROUP:
|
|
case DPSYS_DELETEPLAYER:
|
|
{
|
|
SPMSG_GETPLAYER *pMsg;
|
|
SPMSG_GETPLAYER spmsg_getplayer;
|
|
SPMSG_GETPLAYER *pMsg2 = &spmsg_getplayer;
|
|
|
|
pMsg = (SPMSG_GETPLAYER *) lpv;
|
|
|
|
TSHELL_INFO(TEXT("Got Delete"));
|
|
if (pMsg->dpHdr.usCount == SIZE_GETPLAYER)
|
|
{
|
|
ParanoiaLock();
|
|
if ((iIndex = GetPlayerIndex(pMsg->sMsg.dpId)) != -1)
|
|
{
|
|
if (m_bPlayer0)
|
|
{
|
|
TSHELL_INFO(TEXT("Player 0 Pings Delete."));
|
|
memcpy( (LPVOID) pMsg2, (LPVOID) pMsg, sizeof(SPMSG_GETPLAYER));
|
|
PostGameMessage( (LPVOID) pMsg2, sizeof(SPMSG_GETPLAYER));
|
|
}
|
|
|
|
m_dpDesc.dwCurrentPlayers--;
|
|
if (m_aPlayer[iIndex].bLocal)
|
|
{
|
|
CloseHandle(m_aPlayer[iIndex].hEvent);
|
|
FlushQueue(m_aPlayer[iIndex].pid);
|
|
}
|
|
m_aPlayer[iIndex].bValid = FALSE;
|
|
if (m_aPlayer[iIndex].aGroup)
|
|
lfree(m_aPlayer[iIndex].aGroup);
|
|
LocalMsg(iIndex, (LPVOID) &pMsg->sMsg, sizeof(DPMSG_GETPLAYER));
|
|
|
|
if (pMsg->sMsg.dwType == DPSYS_DELETEPLAYER)
|
|
{
|
|
DWORD ii, jj;
|
|
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if ( m_aPlayer[ii].bValid == TRUE
|
|
&& m_aPlayer[ii].bPlayer == FALSE
|
|
&& m_aPlayer[ii].aGroup)
|
|
{
|
|
for (jj = 0; jj < MAX_PLAYERS; jj++)
|
|
{
|
|
if (m_aPlayer[ii].aGroup[jj] == pMsg->sMsg.dpId)
|
|
{
|
|
m_aPlayer[ii].aGroup[jj] = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Invalid size on system message"));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DPSYS_GETPLAYER:
|
|
{
|
|
DPID pid = ((SPMSG_GETPLAYER *) lpv)->sMsg.dpId;
|
|
BOOL bFound = FALSE;
|
|
|
|
if (m_bPlayer0)
|
|
{
|
|
|
|
ParanoiaLock();
|
|
if ((iIndex = GetPlayerIndex((DPID) pid)) != -1)
|
|
{
|
|
SPMSG_ADDPLAYER spmsg_addplayer;
|
|
SPMSG_ADDPLAYER *pMsg = &spmsg_addplayer;
|
|
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = SIZE_ADDPLAYER;
|
|
pMsg->sMsg.dwType = DPSYS_SETPLAYER;
|
|
pMsg->sMsg.dwPlayerType = m_aPlayer[iIndex].bPlayer;
|
|
pMsg->sMsg.dpId = pid;
|
|
pMsg->sMsg.dwCurrentPlayers = m_dpDesc.dwCurrentPlayers;
|
|
lstrcpy( pMsg->sMsg.szShortName, m_aPlayer[iIndex].chNickName);
|
|
lstrcpy( pMsg->sMsg.szLongName, m_aPlayer[iIndex].chFullName);
|
|
|
|
dwSize = sizeof(SPMSG_SETPLAYER);
|
|
SendTo(m_ClientSocket, pSAddr, SockAddrLen, (char *)pMsg, (LPUINT) &dwSize);
|
|
}
|
|
ParanoiaUnlock();
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case DPSYS_ENUMPLAYERRESP:
|
|
{
|
|
|
|
SPMSG_ADDPLAYER *pMsg;
|
|
|
|
pMsg = (SPMSG_ADDPLAYER *) lpv;
|
|
|
|
TSHELL_INFO(TEXT("Got a remote Player."));
|
|
PlayerDataLock();
|
|
|
|
if (m_fpEnumPlayers)
|
|
{
|
|
memcpy( (LPVOID) &m_spmsgAddPlayer, pMsg, sizeof(SPMSG_ADDPLAYER));
|
|
|
|
SetEvent(m_hPlayerBlkEventMain);
|
|
|
|
TSHELL_INFO(TEXT("Player should be processing in main thread shortly."));
|
|
PlayerDataUnlock();
|
|
|
|
WaitForSingleObject(m_hPlayerBlkEventRead, 5000);
|
|
ResetEvent(m_hPlayerBlkEventRead);
|
|
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Ignore remote player because callback null."));
|
|
PlayerDataUnlock();
|
|
}
|
|
|
|
}
|
|
break;
|
|
|
|
case DPSYS_ENUMALLPLAYERS:
|
|
{
|
|
if (m_bPlayer0)
|
|
{
|
|
|
|
SPMSG_ADDPLAYER spmsg_addplayer;
|
|
SPMSG_ADDPLAYER *pMsg = &spmsg_addplayer;
|
|
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = SIZE_ADDPLAYER;
|
|
pMsg->sMsg.dwType = DPSYS_ENUMPLAYERRESP;
|
|
pMsg->sMsg.dwPlayerType = TRUE;
|
|
pMsg->sMsg.dwCurrentPlayers = m_dpDesc.dwCurrentPlayers;
|
|
|
|
ParanoiaLock();
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if (m_aPlayer[ii].bValid && m_aPlayer[ii].bPlayer)
|
|
{
|
|
pMsg->sMsg.dpId = m_aPlayer[ii].pid;
|
|
lstrcpy( pMsg->sMsg.szShortName, m_aPlayer[ii].chNickName);
|
|
lstrcpy( pMsg->sMsg.szLongName, m_aPlayer[ii].chFullName);
|
|
|
|
dwSize = sizeof(SPMSG_SETPLAYER);
|
|
SendTo(m_ClientSocket, pSAddr, SockAddrLen, (char *)pMsg, (LPUINT) &dwSize);
|
|
}
|
|
}
|
|
ParanoiaUnlock();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
VOID CImpIDP_SP::SendPing()
|
|
{
|
|
|
|
if (!m_bConnected)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if ( m_dwPingSent
|
|
&& (GetTickCount() < (m_dwPingSent + 2000)))
|
|
{
|
|
return;
|
|
}
|
|
else
|
|
m_dwPingSent = 0;
|
|
|
|
SPMSG_PING spmsg_ping;
|
|
SPMSG_PING *pMsg = &spmsg_ping;
|
|
|
|
pMsg->dpHdr.usCookie = DPSYS_SYS;
|
|
pMsg->dpHdr.to = 0;
|
|
pMsg->dpHdr.from = 0;
|
|
pMsg->dpHdr.usCount = SIZE_PING;
|
|
pMsg->dpHdr.usGame = (USHORT) m_usGameCookie;
|
|
pMsg->dwType = DPSYS_PING;
|
|
pMsg->dwTicks = m_dwPingSent = GetTickCount();
|
|
PostNSMessage( (LPVOID) pMsg, sizeof(SPMSG_PING));
|
|
|
|
}
|
|
VOID CImpIDP_SP::ConnectPlayers(SOCKADDR *pSAddr, INT SockAddrLen)
|
|
{
|
|
|
|
DWORD ii;
|
|
DWORD jj;
|
|
SPMSG_ADDPLAYER Msg;
|
|
DPMSG_ADDPLAYER dpAdd;
|
|
DWORD dwSize = sizeof(SPMSG_ADDPLAYER);
|
|
|
|
SPMSG_GROUPADD MsgG;
|
|
DPMSG_GROUPADD dpGAdd;
|
|
DWORD dwGSize = sizeof(SPMSG_GROUPADD);
|
|
|
|
dpAdd.dwType = DPSYS_SETPLAYER;
|
|
dpAdd.dpId = 0;
|
|
|
|
dpGAdd.dwType = DPSYS_SETGROUPPLAYER;
|
|
|
|
|
|
ParanoiaLock();
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if (m_aPlayer[ii].bValid )
|
|
{
|
|
dpAdd.dpId = m_aPlayer[ii].pid;
|
|
dpAdd.dwPlayerType = m_aPlayer[ii].bPlayer;
|
|
lstrcpy( dpAdd.szShortName, m_aPlayer[ii].chNickName);
|
|
lstrcpy( dpAdd.szLongName , m_aPlayer[ii].chFullName);
|
|
dpAdd.dwCurrentPlayers = m_dpDesc.dwCurrentPlayers;
|
|
|
|
Msg.dpHdr.usCookie = DPSYS_SYS;
|
|
Msg.dpHdr.to = (USHORT) m_aPlayer[ii].pid;
|
|
Msg.dpHdr.from = 0;
|
|
Msg.dpHdr.usCount = SIZE_SETPLAYER;
|
|
Msg.dpHdr.usGame = m_usGameCookie;
|
|
Msg.dpHdr.usSeq = NextSequence();
|
|
memcpy( (LPVOID) &Msg.sMsg, &dpAdd, sizeof(DPMSG_ADDPLAYER));
|
|
memcpy( (LPVOID) &Msg.sockaddr, &m_aPlayer[ii].sockaddr, sizeof(SOCKADDR));
|
|
SendTo(m_ClientSocket, pSAddr, SockAddrLen, (char *)&Msg, (LPUINT) &dwSize);
|
|
}
|
|
}
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if ( m_aPlayer[ii].bValid
|
|
&& m_aPlayer[ii].bPlayer == FALSE
|
|
&& m_aPlayer[ii].aGroup)
|
|
{
|
|
for (jj = 0; jj < MAX_PLAYERS; jj++)
|
|
{
|
|
if (m_aPlayer[ii].aGroup[jj] != 0)
|
|
{
|
|
MsgG.dpHdr.usCookie = DPSYS_SYS;
|
|
MsgG.dpHdr.to = 0;
|
|
MsgG.dpHdr.from = 0;
|
|
MsgG.dpHdr.usCount = SIZE_GROUPADD;
|
|
MsgG.dpHdr.usGame = m_usGameCookie;
|
|
MsgG.dpHdr.usSeq = NextSequence();
|
|
dpGAdd.dpIdGroup = m_aPlayer[ii].pid;
|
|
dpGAdd.dpIdPlayer = m_aPlayer[ii].aGroup[jj];
|
|
memcpy( (LPVOID) &MsgG.sMsg, &dpGAdd, sizeof(DPMSG_GROUPADD));
|
|
SendTo(m_ClientSocket, pSAddr, SockAddrLen, (char *)&MsgG, (LPUINT) &dwGSize);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ParanoiaUnlock();
|
|
}
|
|
|
|
|
|
VOID CImpIDP_SP::DeleteRemotePlayers()
|
|
{
|
|
|
|
DWORD ii;
|
|
DPMSG_DELETEPLAYER dpDel;
|
|
|
|
dpDel.dwType = DPSYS_DELETEPLAYER;
|
|
|
|
ParanoiaLock();
|
|
for (ii = 0; ii < MAX_PLAYERS; ii++)
|
|
{
|
|
if (m_aPlayer[ii].bValid && m_aPlayer[ii].bLocal == FALSE)
|
|
{
|
|
m_aPlayer[ii].bValid = FALSE;
|
|
if (m_aPlayer[ii].aGroup)
|
|
lfree(m_aPlayer[ii].aGroup);
|
|
|
|
m_dpDesc.dwCurrentPlayers--;
|
|
dpDel.dpId = m_aPlayer[ii].pid;
|
|
LocalMsg(-1, (LPVOID) &dpDel, sizeof(DPMSG_DELETEPLAYER));
|
|
}
|
|
}
|
|
ParanoiaUnlock();
|
|
|
|
}
|
|
|
|
BOOL CImpIDP_SP::CompareSessions(DWORD dwType, LPDPSESSIONDESC lpSDesc)
|
|
{
|
|
|
|
if ( dwType == DPSYS_OPEN
|
|
&& IsEqualGUID((REFGUID) m_dpDesc.guidSession, (REFGUID) lpSDesc->guidSession)
|
|
&& m_bEnablePlayerAdd == TRUE
|
|
&& m_dpDesc.dwCurrentPlayers < m_dpDesc.dwMaxPlayers
|
|
&& ( m_dpDesc.szPassword[0] == 0x00
|
|
|| lstrcmp(m_dpDesc.szPassword, lpSDesc->szPassword) == 0))
|
|
return(TRUE);
|
|
|
|
if ( dwType == DPSYS_ENUM
|
|
&& m_cMachines < MAX_PLAYERS
|
|
&& ( IsEqualGUID((REFGUID) m_dpDesc.guidSession, (REFGUID) lpSDesc->guidSession)
|
|
|| IsEqualGUID((REFGUID) NULL_GUID, (REFGUID) lpSDesc->guidSession))
|
|
&& ( lpSDesc->dwFlags & DPENUMSESSIONS_ALL
|
|
|| ( m_dpDesc.dwCurrentPlayers < m_dpDesc.dwMaxPlayers
|
|
&& m_bEnablePlayerAdd == TRUE
|
|
&& ( m_dpDesc.szPassword[0] == 0x00
|
|
|| lstrcmp(m_dpDesc.szPassword, lpSDesc->szPassword) == 0))))
|
|
return(TRUE);
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOL CImpIDP_SP::GetSessionData(DWORD dwSession)
|
|
{
|
|
DWORD ii;
|
|
NS_SESSION_SAVE *pns;
|
|
|
|
for (ii = 0; ii < m_dwSessionPrev; ii++)
|
|
{
|
|
pns = (NS_SESSION_SAVE *) m_ppSessionArray[ii];
|
|
if (pns->dpDesc.dwSession == dwSession)
|
|
{
|
|
memcpy(&m_NSSockAddr, &pns->sockaddr, sizeof(SOCKADDR));
|
|
m_usGamePort = pns->usGamePort;
|
|
m_dwUnique = pns->dwUnique;
|
|
return(TRUE);
|
|
}
|
|
}
|
|
return(FALSE);
|
|
}
|
|
VOID CImpIDP_SP::SaveSessionData(NS_SESSION_SAVE *pnsSave)
|
|
{
|
|
//
|
|
//
|
|
//
|
|
if (m_dwSessionAlloc == m_dwSessionPrev)
|
|
{
|
|
char **ppTmp;
|
|
|
|
m_dwSessionAlloc += 16;
|
|
ppTmp = (char **) lmalloc(sizeof(char *) * m_dwSessionAlloc);
|
|
if (ppTmp)
|
|
{
|
|
if (m_ppSessionArray)
|
|
{
|
|
memcpy( ppTmp, m_ppSessionArray, m_dwSessionPrev * sizeof(char *));
|
|
lfree(m_ppSessionArray);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
m_dwSessionAlloc -= 16;
|
|
return;
|
|
}
|
|
m_ppSessionArray = ppTmp;
|
|
|
|
}
|
|
m_ppSessionArray[m_dwSessionPrev] = (char *) lmalloc(sizeof(NS_SESSION_SAVE));
|
|
if (m_ppSessionArray[m_dwSessionPrev])
|
|
{
|
|
*((NS_SESSION_SAVE *)m_ppSessionArray[m_dwSessionPrev++]) = *pnsSave;
|
|
return;
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
VOID CImpIDP_SP::HandleConnect(LPVOID lpv, DWORD dwSize, SOCKADDR *pSAddr, INT SockAddrLen)
|
|
{
|
|
|
|
DWORD ii;
|
|
|
|
// TSHELL_INFO(TEXT("Handle Connect"));
|
|
|
|
SPMSG_ENUM *pMsg = (SPMSG_ENUM *) lpv;
|
|
|
|
if (dwSize != sizeof(SPMSG_ENUM))
|
|
{
|
|
TSHELL_INFO(TEXT("Connect message wrong size."));
|
|
return;
|
|
}
|
|
|
|
if (m_bPlayer0)
|
|
{
|
|
|
|
switch (pMsg->dwType)
|
|
{
|
|
case DPSYS_ENUM_REPLY:
|
|
TSHELL_INFO(TEXT("Player 0 got an enum reply, this is bogus."));
|
|
return;
|
|
|
|
default:
|
|
TSHELL_INFO(TEXT("Player 0 got an unknown type connection msg, this is bogus."));
|
|
return;
|
|
|
|
case DPSYS_ENUM:
|
|
{
|
|
TSHELL_INFO(TEXT("HandleConnect:Player 0 ENUM."));
|
|
if ( pMsg->usVerMajor == DPVERSION_MAJOR
|
|
&& pMsg->usVerMinor == DPVERSION_MINOR
|
|
&& CompareSessions(pMsg->dwType, &pMsg->dpSessionDesc))
|
|
{
|
|
pMsg->dwType = DPSYS_ENUM_REPLY;
|
|
pMsg->dpSessionDesc = m_dpDesc;
|
|
memset(pMsg->dpSessionDesc.szPassword, 0x00, DPSHORTNAMELEN);
|
|
pMsg->usPort = m_usGamePort;
|
|
pMsg->dwUnique = ++m_dwUnique;
|
|
pMsg->dpHdr.usSeq = NextSequence();
|
|
if (SendTo(m_ClientSocket, pSAddr, SockAddrLen, (char *)pMsg, (LPUINT) &dwSize) != 0)
|
|
{
|
|
TSHELL_INFO(TEXT("ENUM SendTo failed."));
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Enum SendTo succeeded."));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
TSHELL_INFO(TEXT("Compare Sessions Failed."));
|
|
}
|
|
}
|
|
break;
|
|
|
|
case DPSYS_OPEN:
|
|
TSHELL_INFO(TEXT("HandleConnect:Player 0 OPEN."));
|
|
pMsg->usPort = m_usGamePort;
|
|
if (pMsg->usPort != m_usGamePort)
|
|
{
|
|
TSHELL_INFO(TEXT("Attempt to open from wrong port."));
|
|
return;
|
|
}
|
|
|
|
if (CompareSessions(pMsg->dwType, &pMsg->dpSessionDesc))
|
|
{
|
|
pMsg->dwType = DPSYS_CONNECT;
|
|
pMsg->dpSessionDesc = m_dpDesc;
|
|
SendTo(m_ClientSocket, pSAddr, SockAddrLen, (char *)pMsg, (LPUINT) &dwSize);
|
|
|
|
if (m_dpDesc.dwCurrentPlayers != 0)
|
|
{
|
|
TSHELL_INFO(TEXT("Send current players."));
|
|
ConnectPlayers(pSAddr, SockAddrLen);
|
|
}
|
|
|
|
for (ii = 0; ii < m_cMachines; ii++)
|
|
if (memcmp(&m_aMachineAddr[ii], pSAddr, sizeof(SOCKADDR)) == 0)
|
|
return;
|
|
|
|
memcpy( &m_aMachineAddr[m_cMachines++], pSAddr, sizeof(SOCKADDR));
|
|
}
|
|
else
|
|
{
|
|
pMsg->dwType = DPSYS_REJECT;
|
|
pMsg->dpSessionDesc = m_dpDesc;
|
|
pMsg->dpHdr.usSeq = NextSequence();
|
|
SendTo(m_ClientSocket, pSAddr, SockAddrLen, (char *)pMsg, (LPUINT) &dwSize);
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
}
|
|
else
|
|
{
|
|
|
|
switch (pMsg->dwType)
|
|
{
|
|
default:
|
|
TSHELL_INFO(TEXT("Player x got an unknown type connection msg, this is bogus."));
|
|
return;
|
|
|
|
case DPSYS_ENUM_REPLY:
|
|
TSHELL_INFO(TEXT("HandleConnect:Player N Reply."));
|
|
|
|
EnumDataLock();
|
|
|
|
if (m_fpEnumSessions)
|
|
{
|
|
NS_SESSION_SAVE ns;
|
|
|
|
m_dwSession++;
|
|
m_SessionAddrLen = SockAddrLen;
|
|
m_usGamePort = pMsg->usPort;
|
|
|
|
memcpy( &m_NSSockAddr, pSAddr, m_SessionAddrLen);
|
|
|
|
pMsg->dpSessionDesc.dwSession = m_dwSession;
|
|
|
|
ns.dpDesc = pMsg->dpSessionDesc;
|
|
memcpy( &ns.sockaddr, pSAddr, m_SessionAddrLen);
|
|
ns.usGamePort = pMsg->usPort;
|
|
ns.dwUnique = pMsg->dwUnique;
|
|
|
|
SaveSessionData(&ns);
|
|
|
|
DBG_INFO((DBGARG, TEXT("Session %d Name %s"),
|
|
pMsg->dpSessionDesc.dwSession,
|
|
pMsg->dpSessionDesc.szSessionName));
|
|
|
|
memcpy( (LPVOID) &m_spmsgEnum, pMsg, sizeof(SPMSG_ENUM));
|
|
|
|
DBG_INFO((DBGARG, TEXT("Tick %d"), GetTickCount()));
|
|
SetEvent(m_hEnumBlkEventMain);
|
|
|
|
EnumDataUnlock();
|
|
DBG_INFO((DBGARG, TEXT("Tick %d"), GetTickCount()));
|
|
|
|
|
|
WaitForSingleObject(m_hEnumBlkEventRead, 5000);
|
|
ResetEvent(m_hEnumBlkEventRead);
|
|
DBG_INFO((DBGARG, TEXT("Tick %d"), GetTickCount()));
|
|
}
|
|
else
|
|
EnumDataUnlock();
|
|
|
|
break;
|
|
|
|
case DPSYS_CONNECT:
|
|
TSHELL_INFO(TEXT("HandleConnect:Player N Connect."));
|
|
m_bConnected = TRUE;
|
|
m_usGamePort = pMsg->usPort;
|
|
m_SessionAddrLen = SockAddrLen;
|
|
memcpy( &m_NSSockAddr, pSAddr, m_SessionAddrLen);
|
|
memcpy( &m_dpDesc, &pMsg->dpSessionDesc, sizeof(m_dpDesc));
|
|
|
|
DBG_INFO((DBGARG, TEXT("Current Players from connect %d"),
|
|
pMsg->dpSessionDesc.dwCurrentPlayers));
|
|
|
|
GetSockAddress(&m_GameSockAddr, NULL, m_usGamePort, NULL, TRUE);
|
|
SetEvent(m_hBlockingEvent);
|
|
return;
|
|
|
|
case DPSYS_REJECT:
|
|
TSHELL_INFO(TEXT("HandleConnect:Player N Reject."));
|
|
TSHELL_INFO(TEXT("We have been rejected for Open."));
|
|
SetEvent(m_hBlockingEvent);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
// TSHELL_INFO(TEXT("Leave Connect"));
|
|
return;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|