|
|
// =================================================================
//
// 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; }
|