From e2853822c50ade43a8b219b136713f4553a09b3f Mon Sep 17 00:00:00 2001 From: Peter Hunnisett Date: Fri, 26 May 2000 22:26:30 +0000 Subject: [PATCH] Started local name server framework. --- dlls/dplayx/dplay.c | 95 +++++++++++++++++++++++------ dlls/dplayx/dplayx_global.c | 104 ++++++++++++++++++++++++++++++-- dlls/dplayx/dplayx_global.h | 4 ++ dlls/dplayx/name_server.c | 143 +++++++++++++++++++++++++++++++++++++++++++- dlls/dplayx/name_server.h | 9 ++- 5 files changed, 328 insertions(+), 27 deletions(-) diff --git a/dlls/dplayx/dplay.c b/dlls/dplayx/dplay.c index aa790a972ed..a3d7c33b37b 100644 --- a/dlls/dplayx/dplay.c +++ b/dlls/dplayx/dplay.c @@ -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 diff --git a/dlls/dplayx/dplayx_global.c b/dlls/dplayx/dplayx_global.c index e959e25b5f0..bee0c82fb9e 100644 --- a/dlls/dplayx/dplayx_global.c +++ b/dlls/dplayx/dplayx_global.c @@ -1,6 +1,6 @@ /* dplayx.dll global data implementation. * - * Copyright 1999 - Peter Hunnisett + * Copyright 1999,2000 - Peter Hunnisett * * * @@ -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 diff --git a/dlls/dplayx/dplayx_global.h b/dlls/dplayx/dplayx_global.h index 6f49e42002e..3310b932141 100644 --- a/dlls/dplayx/dplayx_global.h +++ b/dlls/dplayx/dplayx_global.h @@ -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 ); diff --git a/dlls/dplayx/name_server.c b/dlls/dplayx/name_server.c index 57188aab5db..d81ad5721db 100644 --- a/dlls/dplayx/name_server.c +++ b/dlls/dplayx/name_server.c @@ -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; +} diff --git a/dlls/dplayx/name_server.h b/dlls/dplayx/name_server.h index b0404d6f9d3..33c27ac053b 100644 --- a/dlls/dplayx/name_server.h +++ b/dlls/dplayx/name_server.h @@ -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 */ -- 2.11.4.GIT