source: trunk/src/DPlayX/name_server.cpp@ 5120

Last change on this file since 5120 was 4446, checked in by hugh, 25 years ago

Updated to latest WINE

File size: 11.1 KB
Line 
1// $Id: name_server.cpp,v 1.3 2000-10-06 19:49:06 hugh Exp $
2/* DPLAYX.DLL name server implementation
3 *
4 * Copyright 2000 - Peter Hunnisett
5 *
6 * <presently under construction - contact hunnise@nortelnetworks.com>
7 *
8 */
9
10/* NOTE: Methods with the NS_ prefix are name server methods */
11
12#include <string.h>
13
14#include <odin.h>
15#define ICOM_CINTERFACE 1
16#define CINTERFACE
17
18#include "winbase.h"
19#include "winuser.h"
20#include "debugtools.h"
21#include "heap.h"
22#include "heapstring.h"
23#include "mmsystem.h"
24
25#include "dplayx_global.h"
26#include "name_server.h"
27#include "dplaysp.h"
28#include "dplayx_messages.h"
29#include "dplayx_queue.h"
30
31/* FIXME: Need to create a crit section, store and use it */
32
33DEFAULT_DEBUG_CHANNEL(dplay);
34
35#undef debugstr_guid
36#define debugstr_guid(a) a
37
38/* NS specific structures */
39struct NSCacheData
40{
41 DPQ_ENTRY(NSCacheData) next;
42
43 DWORD dwTime; /* Time at which data was last known valid */
44 LPDPSESSIONDESC2 data;
45
46 LPVOID lpNSAddrHdr;
47
48};
49typedef struct NSCacheData NSCacheData, *lpNSCacheData;
50
51struct NSCache
52{
53 lpNSCacheData present; /* keep track of what is to be looked at when walking */
54
55 DPQ_HEAD(NSCacheData) first;
56};
57typedef struct NSCache NSCache, *lpNSCache;
58
59/* Function prototypes */
60DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData );
61
62/* Name Server functions
63 * ---------------------
64 */
65void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd )
66{
67#if 0
68 /* FIXME: Remove this method? */
69 DPLAYX_SetLocalSession( lpsd );
70#endif
71}
72
73DPQ_DECL_COMPARECB( cbUglyPig, GUID )
74{
75 return IsEqualGUID( elem1, elem2 );
76}
77
78/* Store the given NS remote address for future reference */
79void NS_SetRemoteComputerAsNameServer( LPVOID lpNSAddrHdr,
80 DWORD dwHdrSize,
81 LPDPMSG_ENUMSESSIONSREPLY lpMsg,
82 LPVOID lpNSInfo )
83{
84 lpNSCache lpCache = (lpNSCache)lpNSInfo;
85 lpNSCacheData lpCacheNode;
86
87 TRACE( "%p, %p, %p\n", lpNSAddrHdr, lpMsg, lpNSInfo );
88
89 /* FIXME: Should check to see if the reply is for an existing session. If
90 * so we remove the old and add the new so oldest is at front.
91 */
92
93 /* See if we can find this session. If we can, remove it as it's a dup */
94 DPQ_REMOVE_ENTRY_CB( lpCache->first, next, data->guidInstance, cbUglyPig,
95 lpMsg->sd.guidInstance, lpCacheNode );
96
97 if( lpCacheNode != NULL )
98 {
99 TRACE( "Duplicate session entry for %s removed - updated version kept\n",
100 debugstr_guid( &lpCacheNode->data->guidInstance ) );
101 cbDeleteNSNodeFromHeap( lpCacheNode );
102 }
103
104 /* Add this to the list */
105 lpCacheNode = (lpNSCacheData)HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
106 sizeof( *lpCacheNode ) );
107
108 if( lpCacheNode == NULL )
109 {
110 ERR( "no memory for NS node\n" );
111 return;
112 }
113
114 lpCacheNode->lpNSAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
115 dwHdrSize );
116 CopyMemory( lpCacheNode->lpNSAddrHdr, lpNSAddrHdr, dwHdrSize );
117
118
119 lpCacheNode->data = (LPDPSESSIONDESC2)HeapAlloc( GetProcessHeap(),
120 HEAP_ZERO_MEMORY,
121 sizeof( *lpCacheNode->data ) );
122
123 if( lpCacheNode->data == NULL )
124 {
125 ERR( "no memory for SESSIONDESC2\n" );
126 return;
127 }
128
129 CopyMemory( lpCacheNode->data, &lpMsg->sd, sizeof( *lpCacheNode->data ) );
130 lpCacheNode->data->sess.lpszSessionNameA = HEAP_strdupWtoA( GetProcessHeap(),
131 HEAP_ZERO_MEMORY,
132 (LPWSTR)(lpMsg+1) );
133
134 lpCacheNode->dwTime = GetTickCount();
135
136 DPQ_INSERT(lpCache->first, lpCacheNode, next );
137
138 lpCache->present = lpCacheNode;
139
140 /* Use this message as an oportunity to weed out any old sessions so
141 * that we don't enum them again
142 */
143 NS_PruneSessionCache( lpNSInfo );
144}
145
146LPVOID NS_GetNSAddr( LPVOID lpNSInfo )
147{
148 lpNSCache lpCache = (lpNSCache)lpNSInfo;
149
150 FIXME( ":quick stub\n" );
151
152 /* Ok. Cheat and don't search for the correct stuff just take the first.
153 * FIXME: In the future how are we to know what is _THE_ enum we used?
154 * This is going to have to go into dplay somehow. Perhaps it
155 * comes back with app server id for the join command! Oh...that
156 * must be it. That would make this method obsolete once that's
157 * in place.
158 */
159
160 return lpCache->first.lpQHFirst->lpNSAddrHdr;
161}
162
163/* This function is responsible for sending a request for all other known
164 nameservers to send us what sessions they have registered locally
165 */
166HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
167 DWORD dwFlags,
168 LPSPINITDATA lpSpData )
169
170{
171 DPSP_ENUMSESSIONSDATA data;
172 LPDPMSG_ENUMSESSIONSREQUEST lpMsg;
173
174 TRACE( "enumerating for guid %s\n", debugstr_guid( lpcGuid ) );
175
176 /* Get the SP to deal with sending the EnumSessions request */
177 FIXME( ": not all data fields are correct\n" );
178
179 data.dwMessageSize = lpSpData->dwSPHeaderSize + sizeof( *lpMsg ); /*FIXME!*/
180 data.lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
181 data.dwMessageSize );
182 data.lpISP = lpSpData->lpISP;
183 data.bReturnStatus = (dwFlags & DPENUMSESSIONS_RETURNSTATUS) ? TRUE : FALSE;
184
185
186 lpMsg = (LPDPMSG_ENUMSESSIONSREQUEST)(((BYTE*)data.lpMessage)+lpSpData->dwSPHeaderSize);
187
188 /* Setup EnumSession reqest message */
189 lpMsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
190 lpMsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREQUEST;
191 lpMsg->envelope.wVersion = DPMSGVER_DP6;
192
193 lpMsg->dwPasswordSize = 0; /* FIXME: If enumerating passwords..? */
194 lpMsg->dwFlags = dwFlags;
195
196 CopyMemory( &lpMsg->guidApplication, lpcGuid, sizeof( *lpcGuid ) );
197
198 return (lpSpData->lpCB->EnumSessions)( &data );
199}
200
201DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData )
202{
203 /* NOTE: This proc doesn't deal with the walking pointer */
204
205 /* FIXME: Memory leak on data (contained ptrs) */
206 HeapFree( GetProcessHeap(), 0, elem->data );
207 HeapFree( GetProcessHeap(), 0, elem->lpNSAddrHdr );
208 HeapFree( GetProcessHeap(), 0, elem );
209}
210
211
212
213/* Render all data in a session cache invalid */
214void NS_InvalidateSessionCache( LPVOID lpNSInfo )
215{
216 lpNSCache lpCache = (lpNSCache)lpNSInfo;
217
218 if( lpCache == NULL )
219 {
220 ERR( ": invalidate non existant cache\n" );
221 return;
222 }
223
224 DPQ_DELETEQ( lpCache->first, next, lpNSCacheData, cbDeleteNSNodeFromHeap );
225
226 /* NULL out the walking pointer */
227 lpCache->present = NULL;
228}
229
230/* Create and initialize a session cache */
231BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo )
232{
233 lpNSCache lpCache = (lpNSCache)HeapAlloc( GetProcessHeap(),
234 HEAP_ZERO_MEMORY,
235 sizeof( *lpCache ) );
236
237 *lplpNSInfo = lpCache;
238
239 if( lpCache == NULL )
240 {
241 return FALSE;
242 }
243
244 DPQ_INIT(lpCache->first);
245 lpCache->present = NULL;
246
247 return TRUE;
248}
249
250/* Delete a session cache */
251void NS_DeleteSessionCache( LPVOID lpNSInfo )
252{
253 NS_InvalidateSessionCache( (lpNSCache)lpNSInfo );
254}
255
256/* Reinitialize the present pointer for this cache */
257void NS_ResetSessionEnumeration( LPVOID lpNSInfo )
258{
259
260 ((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first.lpQHFirst;
261}
262
263LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo )
264{
265 LPDPSESSIONDESC2 lpSessionDesc;
266 lpNSCache lpCache = (lpNSCache)lpNSInfo;
267
268 /* FIXME: The pointers could disappear when walking if a prune happens */
269
270 /* Test for end of the list */
271 if( lpCache->present == NULL )
272 {
273 return NULL;
274 }
275
276 lpSessionDesc = lpCache->present->data;
277
278 /* Advance tracking pointer */
279 lpCache->present = lpCache->present->next.lpQNext;
280
281 return lpSessionDesc;
282}
283
284/* This method should check to see if there are any sessions which are
285 * older than the criteria. If so, just delete that information.
286 */
287void NS_PruneSessionCache( LPVOID lpNSInfo )
288{
289 lpNSCache lpCache = (lpNSCache)lpNSInfo;
290
291 const DWORD dwPresentTime = timeGetTime();
292 const DWORD dwPrunePeriod = 60000; /* is 60 secs enough? */
293 const DWORD dwPruneTime = dwPresentTime - dwPrunePeriod;
294
295 /* This silly little algorithm is based on the fact we keep entries in
296 * the queue in a time based order. It also assumes that it is not possible
297 * to wrap around over yourself (which is not unreasonable).
298 * The if statements verify if the first entry in the queue is less
299 * than dwPrunePeriod old depending on the "clock" roll over.
300 */
301 for( ;; )
302 {
303 lpNSCacheData lpFirstData;
304
305 if( DPQ_IS_EMPTY(lpCache->first) )
306 {
307 /* Nothing to prune */
308 break;
309 }
310
311 if( dwPruneTime > dwPresentTime ) /* 0 <= dwPresentTime <= dwPrunePeriod */
312 {
313 if( ( DPQ_FIRST(lpCache->first)->dwTime <= dwPresentTime ) ||
314 ( DPQ_FIRST(lpCache->first)->dwTime > dwPruneTime )
315 )
316 {
317 /* Less than dwPrunePeriod old - keep */
318 break;
319 }
320 }
321 else /* dwPrunePeriod <= dwPresentTime <= max dword */
322 {
323 if( ( DPQ_FIRST(lpCache->first)->dwTime <= dwPresentTime ) &&
324 ( DPQ_FIRST(lpCache->first)->dwTime > dwPruneTime )
325 )
326 {
327 /* Less than dwPrunePeriod old - keep */
328 break;
329 }
330 }
331
332 lpFirstData = DPQ_FIRST(lpCache->first);
333 DPQ_REMOVE( lpCache->first, DPQ_FIRST(lpCache->first), next );
334 cbDeleteNSNodeFromHeap( lpFirstData );
335 }
336
337}
338
339
340
341/* Message stuff */
342void NS_ReplyToEnumSessionsRequest( LPVOID lpMsg,
343 LPDPSP_REPLYDATA lpReplyData,
344 IDirectPlay2Impl* lpDP )
345{
346 LPDPMSG_ENUMSESSIONSREPLY rmsg;
347 DWORD dwVariableSize;
348 DWORD dwVariableLen;
349 LPWSTR string;
350 /* LPDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpMsg; */
351 BOOL bAnsi = TRUE; /* FIXME: This needs to be in the DPLAY interface */
352
353 FIXME( ": few fixed + need to check request for response\n" );
354
355 dwVariableLen = bAnsi ? lstrlenA( lpDP->dp2->lpSessionDesc->sess.lpszSessionNameA ) + 1
356 : lstrlenW( lpDP->dp2->lpSessionDesc->sess.lpszSessionName ) + 1;
357
358 dwVariableSize = dwVariableLen * sizeof( WCHAR );
359
360 lpReplyData->dwMessageSize = lpDP->dp2->spData.dwSPHeaderSize +
361 sizeof( *rmsg ) + dwVariableSize;
362 lpReplyData->lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
363 lpReplyData->dwMessageSize );
364
365 rmsg = (LPDPMSG_ENUMSESSIONSREPLY)( (BYTE*)lpReplyData->lpMessage +
366 lpDP->dp2->spData.dwSPHeaderSize);
367
368 rmsg->envelope.dwMagic = DPMSGMAGIC_DPLAYMSG;
369 rmsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREPLY;
370 rmsg->envelope.wVersion = DPMSGVER_DP6;
371
372 CopyMemory( &rmsg->sd, lpDP->dp2->lpSessionDesc,
373 sizeof( lpDP->dp2->lpSessionDesc->dwSize ) );
374 rmsg->dwUnknown = 0x0000005c;
375 if( bAnsi )
376 {
377 string = HEAP_strdupAtoW( GetProcessHeap(), 0,
378 lpDP->dp2->lpSessionDesc->sess.lpszSessionNameA );
379 /* FIXME: Memory leak */
380 }
381 else
382 {
383 string = lpDP->dp2->lpSessionDesc->sess.lpszSessionName;
384 }
385
386 lstrcpyW( (LPWSTR)(rmsg+1), string );
387
388}
389
Note: See TracBrowser for help on using the repository browser.