Commit e2853822 authored by Peter Hunnisett's avatar Peter Hunnisett Committed by Alexandre Julliard

Started local name server framework.

parent b40a9b7f
......@@ -71,6 +71,8 @@ typedef struct tagDirectPlay2Data
HANDLE hEnumSessionThread;
EnumSessionAsyncCallbackData enumSessionAsyncCallbackData;
LPVOID lpNameServerData; /* DPlay interface doesn't know type */
} DirectPlay2Data;
typedef struct tagDirectPlay3Data
......@@ -163,6 +165,11 @@ BOOL DP_CreateDirectPlay2( LPVOID lpDP )
This->dp2->enumSessionAsyncCallbackData.lpContext = NULL;
This->dp2->enumSessionAsyncCallbackData.dwTimeout = INFINITE;
if( !NS_InitializeSessionCache( &This->dp2->lpNameServerData ) )
{
return FALSE;
}
return TRUE;
}
......@@ -175,6 +182,8 @@ BOOL DP_DestroyDirectPlay2( LPVOID lpDP )
TerminateThread( This->dp2->hEnumSessionThread, 0 );
CloseHandle( This->dp2->hEnumSessionThread );
}
NS_DeleteSessionCache( This->dp2->lpNameServerData );
/* Delete the contents */
HeapFree( GetProcessHeap(), 0, This->dp2 );
......@@ -751,21 +760,30 @@ static HRESULT WINAPI DirectPlay2WImpl_EnumPlayers
return DP_OK;
}
/* This function is responsible for sending a request for all other known
nameservers to send us what sessions they have registered locally
*/
void DP_SendSessionRequestBroadcast()
{
FIXME( ": stub\n" );
}
/* This function should call the registered callback function that the user
passed into EnumSessions
passed into EnumSessions for each entry available.
*/
static void DP_InvokeEnumSessionCallbacksA( LPDPENUMSESSIONSCALLBACK2 lpEnumSessionsCallback2,
LPVOID lpNSInfo,
DWORD dwTimeout,
LPVOID lpContext )
{
FIXME( ": stub\n" );
LPDPSESSIONDESC2 lpSessionDesc;
FIXME( ": not checking for conditions\n" );
NS_ResetSessionEnumeration( lpNSInfo );
/* Enumerate all sessions */
while( (lpSessionDesc = NS_WalkSessions( lpNSInfo ) ) != NULL )
{
TRACE( "EnumSessionsCallback2 invoked\n" );
if( !lpEnumSessionsCallback2( lpSessionDesc, &dwTimeout, 0, lpContext ) )
{
return;
}
}
}
static DWORD CALLBACK DP_EnumSessionsSpwanThreadA( LPVOID lpContext )
......@@ -773,21 +791,34 @@ static DWORD CALLBACK DP_EnumSessionsSpwanThreadA( LPVOID lpContext )
ICOM_THIS(IDirectPlay2Impl,lpContext);
DWORD dwTimeout = This->dp2->enumSessionAsyncCallbackData.dwTimeout;
TRACE( "->(%p)->(0x%08lx)\n", This, dwTimeout );
TRACE( "(%p)->(0x%08lx)\n", This, dwTimeout );
/* FIXME: Don't think this is exactly right. It'll do for now */
for( ;; )
{
/* 2: Send the broadcast for session enumeration */
DP_SendSessionRequestBroadcast( NULL, 0 ); /* Should pass lpsd */
NS_SendSessionRequestBroadcast( This->dp2->lpNameServerData );
SleepEx( dwTimeout, FALSE );
DP_InvokeEnumSessionCallbacksA( This->dp2->enumSessionAsyncCallbackData.cb,
This->dp2->lpNameServerData,
dwTimeout,
This->dp2->enumSessionAsyncCallbackData.lpContext );
/* All sessions have been enumerated. Invoke the callback function
once more indicating a timeout has occured. This is the way
that the application can indicate that it wishes to continue with the
enumeration */
if( !(This->dp2->enumSessionAsyncCallbackData.cb)( NULL, &dwTimeout, DPESC_TIMEDOUT, lpContext ) )
{
/* The application doesn't want us to continue - end this thread */
return 0;
}
}
return 0;
return 1;
}
static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
......@@ -800,6 +831,8 @@ static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
if( dwTimeout == 0 )
{
/* Should actually be getting the dwTimeout value through
IDirectPlay_GetCaps( This, ...) */
FIXME( ": should provide a dependent dwTimeout\n" );
dwTimeout = 5 * 1000; /* 5 seconds */
}
......@@ -833,10 +866,14 @@ static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
{
DWORD dwThreadId;
/* Enumerate everything presently in the local session cache */
DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2, This->dp2->lpNameServerData, dwTimeout, lpContext );
/* See if we've already created a thread to service this interface */
if( This->dp2->hEnumSessionThread == INVALID_HANDLE_VALUE )
{
/* FIXME: Should be adding a reference here - another thread now knows
how to call this interface */
This->dp2->enumSessionAsyncCallbackData.cb = lpEnumSessionsCallback2;
This->dp2->enumSessionAsyncCallbackData.lpContext = lpContext;
This->dp2->enumSessionAsyncCallbackData.dwTimeout = dwTimeout;
......@@ -851,17 +888,15 @@ static HRESULT WINAPI DirectPlay2AImpl_EnumSessions
&dwThreadId );
}
DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2, lpContext );
}
else
{
/* Send the broadcast for session enumeration */
/* FIXME: How to handle the replies? Queue? */
DP_SendSessionRequestBroadcast( lpsd, dwFlags );
NS_SendSessionRequestBroadcast( This->dp2->lpNameServerData );
SleepEx( dwTimeout, FALSE );
DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2, lpContext );
DP_InvokeEnumSessionCallbacksA( lpEnumSessionsCallback2, This->dp2->lpNameServerData, dwTimeout, lpContext );
}
return DP_OK;
......@@ -1061,7 +1096,7 @@ static HRESULT WINAPI DirectPlay2AImpl_Open
/* Rightoo - this computer is the host and the local computer needs to be
the name server so that others can join this session */
DPLAYX_NS_SetLocalComputerAsNameServer( lpsd );
NS_SetLocalComputerAsNameServer( lpsd );
}
......@@ -1593,9 +1628,31 @@ static HRESULT WINAPI DirectPlay3AImpl_SecureOpen
FIXME("(%p)->(%p,0x%08lx,%p,%p): stub\n", This, lpsd, dwFlags, lpSecurity, lpCredentials );
if( This->dp2->bConnectionOpen )
{
TRACE( ": rejecting already open connection.\n" );
return DPERR_ALREADYINITIALIZED;
}
/* When we open we need to stop any EnumSession activity */
IDirectPlayX_EnumSessions( iface, NULL, 0, NULL, NULL, DPENUMSESSIONS_STOPASYNC );
if( dwFlags & DPOPEN_CREATE )
{
dwFlags &= ~DPOPEN_CREATE;
/* Rightoo - this computer is the host and the local computer needs to be
the name server so that others can join this session */
NS_SetLocalComputerAsNameServer( lpsd );
}
if( dwFlags )
{
ERR( ": ignored dwFlags 0x%08lx\n", dwFlags );
}
return DP_OK;
}
static HRESULT WINAPI DirectPlay3WImpl_SecureOpen
......
/* dplayx.dll global data implementation.
*
* Copyright 1999 - Peter Hunnisett
* Copyright 1999,2000 - Peter Hunnisett
*
* <presently under construction - contact hunnise@nortelnetworks.com>
*
......@@ -36,27 +36,34 @@ static HANDLE hDplayxSema;
/* HACK for simple global data right now */
enum { numSupportedLobbies = 32 };
enum { numSupportedLobbies = 32, numSupportedSessions = 32 };
typedef struct tagDirectPlayLobbyData
{
/* Just a DPLCONNECTION struct */
DWORD dwConnFlags;
DPSESSIONDESC2 sessionDesc;
DPNAME playerName;
GUID guidSP;
LPVOID lpAddress;
DWORD dwAddressSize;
/* Information for dplobby interfaces */
DWORD dwAppID;
HANDLE hReceiveEvent;
DWORD dwAppLaunchedFromID;
} DirectPlayLobbyData, *lpDirectPlayLobbyData;
static DirectPlayLobbyData lobbyData[ numSupportedLobbies ];
/* Hack for now */
static DPSESSIONDESC2 sessionData[ numSupportedSessions ];
/* Function prototypes */
BOOL DPLAYX_IsAppIdLobbied( DWORD dwAppId, lpDirectPlayLobbyData* dplData );
void DPLAYX_InitializeLobbyDataEntry( lpDirectPlayLobbyData lpData );
BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
LPCDPSESSIONDESC2 lpSessionSrc );
......@@ -87,6 +94,12 @@ void DPLAYX_ConstructData(void)
DPLAYX_InitializeLobbyDataEntry( &lobbyData[ i ] );
}
/* Set all sessions to be "empty" */
for( i=0; i < numSupportedSessions; i++ )
{
sessionData[i].dwSize = 0;
}
}
/***************************************************************************
......@@ -578,6 +591,89 @@ HRESULT DPLAYX_SetConnectionSettingsW
return DP_OK;
}
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateSessionDesc2A( LPCDPSESSIONDESC2 lpSessionSrc )
{
LPDPSESSIONDESC2 lpSessionDest = (LPDPSESSIONDESC2) HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof( *lpSessionSrc ) );
DPLAYX_CopyIntoSessionDesc2A( lpSessionDest, lpSessionSrc );
return lpSessionDest;
}
/* Copy an ANSI session desc structure to the given buffer */
BOOL DPLAYX_CopyIntoSessionDesc2A( LPDPSESSIONDESC2 lpSessionDest,
LPCDPSESSIONDESC2 lpSessionSrc )
{
memcpy( lpSessionDest, lpSessionSrc, sizeof( *lpSessionSrc ) );
if( lpSessionSrc->sess.lpszSessionNameA )
{
lpSessionDest->sess.lpszSessionNameA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpSessionSrc->sess.lpszSessionNameA );
}
if( lpSessionSrc->pass.lpszPasswordA )
{
lpSessionDest->pass.lpszPasswordA =
HEAP_strdupA( GetProcessHeap(), HEAP_ZERO_MEMORY, lpSessionSrc->pass.lpszPasswordA );
}
return TRUE;
}
/* Start the index at 0. index will be updated to equal that which should
be passed back into this function for the next element */
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index )
{
for( ; (*index) < numSupportedSessions; (*index)++ )
{
if( sessionData[(*index)].dwSize != 0 )
{
return DPLAYX_CopyAndAllocateSessionDesc2A( &sessionData[(*index)++] );
}
}
/* No more sessions */
return NULL;
}
/* Start the index at 0. index will be updated to equal that which should
be passed back into this function for the next element */
BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd )
{
for( ; (*index) < numSupportedSessions; (*index)++ )
{
if( sessionData[(*index)].dwSize != 0 )
{
return DPLAYX_CopyIntoSessionDesc2A( lpsd, &sessionData[(*index)++] );
}
}
/* No more sessions */
return FALSE;
}
void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd )
{
UINT i;
FIXME( ": stub\n" );
/* FIXME: Is this an error if it exists already? */
/* Crude/wrong implementation for now. Just always add to first empty spot */
for( i=0; i < numSupportedSessions; i++ )
{
/* Is this one empty? */
if( sessionData[i].dwSize == 0 )
{
DPLAYX_CopyIntoSessionDesc2A( &sessionData[i], lpsd );
break;
}
}
}
/* NOTE: This is potentially not thread safe. You are not guaranteed to end up
with the correct string printed in the case where the HRESULT is not
known. You'll just get the last hr passed in printed. This can change
......
......@@ -16,6 +16,10 @@ HRESULT DPLAYX_SetConnectionSettingsW ( DWORD dwFlags, DWORD dwAppID, LPDPLCONNE
BOOL DPLAYX_CreateLobbyApplication( DWORD dwAppID, HANDLE hReceiveEvent );
BOOL DPLAYX_DestroyLobbyApplication( DWORD dwAppID );
LPDPSESSIONDESC2 DPLAYX_CopyAndAllocateLocalSession( UINT* index );
BOOL DPLAYX_CopyLocalSession( UINT* index, LPDPSESSIONDESC2 lpsd );
void DPLAYX_SetLocalSession( LPCDPSESSIONDESC2 lpsd );
/* Convert a DP or DPL HRESULT code into a string for human consumption */
LPCSTR DPLAYX_HresultToString( HRESULT hr );
......
......@@ -8,15 +8,152 @@
/* NOTE: Methods with the NS_ prefix are name server methods */
#include "winbase.h"
#include "debugtools.h"
#include "dplayx_global.h"
#include "name_server.h"
/* FIXME: Need to aquire the interface semaphore before didlling data */
DEFAULT_DEBUG_CHANNEL(dplay);
/* NS specific structures */
typedef struct tagNSCacheData
{
struct tagNSCacheData* next;
LPDPSESSIONDESC2 data;
} NSCacheData, *lpNSCacheData;
void DPLAYX_NS_SetLocalComputerAsNameServer( LPDPSESSIONDESC2 lpsd )
typedef struct tagNSCache
{
FIXME( ": (%p) stub\n", lpsd );
lpNSCacheData present; /* keep track of what is to be looked at */
lpNSCacheData first;
} NSCache, *lpNSCache;
/* Local Prototypes */
static void NS_InvalidateSessionCache( lpNSCache lpCache );
/* Name Server functions
* ---------------------
*/
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd )
{
DPLAYX_SetLocalSession( lpsd );
}
/* This function is responsible for sending a request for all other known
nameservers to send us what sessions they have registered locally
*/
void NS_SendSessionRequestBroadcast( LPVOID lpNSInfo )
{
UINT index = 0;
lpNSCache lpCache = (lpNSCache)lpNSInfo;
LPDPSESSIONDESC2 lpTmp = NULL;
/* Invalidate the session cache for the interface */
NS_InvalidateSessionCache( lpCache );
/* Add the local known sessions to the cache */
if( ( lpTmp = DPLAYX_CopyAndAllocateLocalSession( &index ) ) != NULL )
{
lpCache->first = (lpNSCacheData)HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof( *(lpCache->first) ) );
lpCache->first->data = lpTmp;
lpCache->first->next = NULL;
lpCache->present = lpCache->first;
while( ( lpTmp = DPLAYX_CopyAndAllocateLocalSession( &index ) ) != NULL )
{
lpCache->present->next = (lpNSCacheData)HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof( *(lpCache->present) ) );
lpCache->present = lpCache->present->next;
lpCache->present->data = lpTmp;
lpCache->present->next = NULL;
}
lpCache->present = lpCache->first;
}
/* Send out requests for matching sessions to all other known computers */
FIXME( ": no remote requests sent\n" );
/* FIXME - how to handle responses to messages anyways? */
}
/* Render all data in a session cache invalid */
static void NS_InvalidateSessionCache( lpNSCache lpCache )
{
if( lpCache == NULL )
{
ERR( ": invalidate non existant cache\n" );
return;
}
/* Remove everything from the cache */
while( lpCache->first )
{
lpCache->present = lpCache->first;
lpCache->first = lpCache->first->next;
HeapFree( GetProcessHeap(), 0, lpCache->present );
}
/* NULL out the cache pointers */
lpCache->present = NULL;
lpCache->first = NULL;
}
/* Create and initialize a session cache */
BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo )
{
lpNSCache lpCache = (lpNSCache)HeapAlloc( GetProcessHeap(),
HEAP_ZERO_MEMORY,
sizeof( *lpCache ) );
*lplpNSInfo = lpCache;
if( lpCache == NULL )
{
return FALSE;
}
lpCache->first = lpCache->present = NULL;
return TRUE;
}
/* Delete a session cache */
void NS_DeleteSessionCache( LPVOID lpNSInfo )
{
NS_InvalidateSessionCache( (lpNSCache)lpNSInfo );
}
/* Reinitialize the present pointer for this cache */
void NS_ResetSessionEnumeration( LPVOID lpNSInfo )
{
((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first;
}
LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo )
{
LPDPSESSIONDESC2 lpSessionDesc;
lpNSCache lpCache = (lpNSCache)lpNSInfo;
/* Test for end of the list */
if( lpCache->present == NULL )
{
return NULL;
}
lpSessionDesc = lpCache->present->data;
/* Advance tracking pointer */
lpCache->present = lpCache->present->next;
return lpSessionDesc;
}
......@@ -4,6 +4,13 @@
#include "dplay.h"
void DPLAYX_NS_SetLocalComputerAsNameServer( LPDPSESSIONDESC2 lpsd );
void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd );
void NS_SendSessionRequestBroadcast( LPVOID lpNSInfo );
BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo );
void NS_DeleteSessionCache( LPVOID lpNSInfo );
void NS_ResetSessionEnumeration( LPVOID lpNSInfo );
LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo );
#endif /* __WINE_DPLAYX_NAMESERVER */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment