ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

name_server.c
Go to the documentation of this file.
00001 /* DPLAYX.DLL name server implementation
00002  *
00003  * Copyright 2000-2001 - Peter Hunnisett
00004  *
00005  * This library is free software; you can redistribute it and/or
00006  * modify it under the terms of the GNU Lesser General Public
00007  * License as published by the Free Software Foundation; either
00008  * version 2.1 of the License, or (at your option) any later version.
00009  *
00010  * This library is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public
00016  * License along with this library; if not, write to the Free Software
00017  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00018  */
00019 
00020 /* NOTE: Methods with the NS_ prefix are name server methods */
00021 
00022 #include <stdarg.h>
00023 #include <string.h>
00024 
00025 #define NONAMELESSUNION
00026 #define NONAMELESSSTRUCT
00027 #include "windef.h"
00028 #include "winbase.h"
00029 #include "winnls.h"
00030 #include "wine/unicode.h"
00031 #include "wine/debug.h"
00032 #include "mmsystem.h"
00033 
00034 #include "dplayx_global.h"
00035 #include "name_server.h"
00036 #include "dplaysp.h"
00037 #include "dplayx_messages.h"
00038 #include "dplayx_queue.h"
00039 
00040 /* FIXME: Need to create a crit section, store and use it */
00041 
00042 WINE_DEFAULT_DEBUG_CHANNEL(dplay);
00043 
00044 /* NS specific structures */
00045 struct NSCacheData
00046 {
00047   DPQ_ENTRY(NSCacheData) next;
00048 
00049   DWORD dwTime; /* Time at which data was last known valid */
00050   LPDPSESSIONDESC2 data;
00051 
00052   LPVOID lpNSAddrHdr;
00053 
00054 };
00055 typedef struct NSCacheData NSCacheData, *lpNSCacheData;
00056 
00057 struct NSCache
00058 {
00059   lpNSCacheData present; /* keep track of what is to be looked at when walking */
00060 
00061   DPQ_HEAD(NSCacheData) first;
00062 
00063   BOOL bNsIsLocal;
00064   LPVOID lpLocalAddrHdr;  /* FIXME: Not yet used */
00065   LPVOID lpRemoteAddrHdr; /* FIXME: Not yet used */
00066 };
00067 typedef struct NSCache NSCache, *lpNSCache;
00068 
00069 /* Function prototypes */
00070 DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData );
00071 
00072 /* Name Server functions
00073  * ---------------------
00074  */
00075 void NS_SetLocalComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo )
00076 {
00077 #if 0
00078   /* FIXME: Remove this method? */
00079   DPLAYX_SetLocalSession( lpsd );
00080 #endif
00081   lpNSCache lpCache = (lpNSCache)lpNSInfo;
00082 
00083   lpCache->bNsIsLocal = TRUE;
00084 }
00085 
00086 void NS_SetRemoteComputerAsNameServer( LPCDPSESSIONDESC2 lpsd, LPVOID lpNSInfo )
00087 {
00088   lpNSCache lpCache = (lpNSCache)lpNSInfo;
00089 
00090   lpCache->bNsIsLocal = FALSE;
00091 }
00092 
00093 static DPQ_DECL_COMPARECB( cbUglyPig, GUID )
00094 {
00095   return IsEqualGUID( elem1, elem2 );
00096 }
00097 
00098 /* Store the given NS remote address for future reference */
00099 /* FIXME: LPDPMSG_ENUMSESSIONSREPLY should be const */
00100 void NS_AddRemoteComputerAsNameServer( LPCVOID                   lpcNSAddrHdr,
00101                                        DWORD                     dwHdrSize,
00102                                        LPDPMSG_ENUMSESSIONSREPLY lpMsg,
00103                                        LPVOID                    lpNSInfo )
00104 {
00105   DWORD len;
00106   lpNSCache     lpCache = (lpNSCache)lpNSInfo;
00107   lpNSCacheData lpCacheNode;
00108 
00109   TRACE( "%p, %p, %p\n", lpcNSAddrHdr, lpMsg, lpNSInfo );
00110 
00111   /* See if we can find this session. If we can, remove it as it's a dup */
00112   DPQ_REMOVE_ENTRY_CB( lpCache->first, next, data->guidInstance, cbUglyPig,
00113                        lpMsg->sd.guidInstance, lpCacheNode );
00114 
00115   if( lpCacheNode != NULL )
00116   {
00117     TRACE( "Duplicate session entry for %s removed - updated version kept\n",
00118            debugstr_guid( &lpCacheNode->data->guidInstance ) );
00119     cbDeleteNSNodeFromHeap( lpCacheNode );
00120   }
00121 
00122   /* Add this to the list */
00123   lpCacheNode = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpCacheNode ) );
00124 
00125   if( lpCacheNode == NULL )
00126   {
00127     ERR( "no memory for NS node\n" );
00128     return;
00129   }
00130 
00131   lpCacheNode->lpNSAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
00132                                         dwHdrSize );
00133   CopyMemory( lpCacheNode->lpNSAddrHdr, lpcNSAddrHdr, dwHdrSize );
00134 
00135   lpCacheNode->data = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *(lpCacheNode->data) ) );
00136 
00137   if( lpCacheNode->data == NULL )
00138   {
00139     ERR( "no memory for SESSIONDESC2\n" );
00140     return;
00141   }
00142 
00143   CopyMemory( lpCacheNode->data, &lpMsg->sd, sizeof( *lpCacheNode->data ) );
00144   len = WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1, NULL, 0, NULL, NULL );
00145   if ((lpCacheNode->data->lpszSessionNameA = HeapAlloc( GetProcessHeap(), 0, len )))
00146   {
00147       WideCharToMultiByte( CP_ACP, 0, (LPWSTR)(lpMsg+1), -1,
00148                            lpCacheNode->data->lpszSessionNameA, len, NULL, NULL );
00149   }
00150 
00151   lpCacheNode->dwTime = timeGetTime();
00152 
00153   DPQ_INSERT(lpCache->first, lpCacheNode, next );
00154 
00155   lpCache->present = lpCacheNode;
00156 
00157   /* Use this message as an opportunity to weed out any old sessions so
00158    * that we don't enum them again
00159    */
00160   NS_PruneSessionCache( lpNSInfo );
00161 }
00162 
00163 LPVOID NS_GetNSAddr( LPVOID lpNSInfo )
00164 {
00165   lpNSCache lpCache = (lpNSCache)lpNSInfo;
00166 
00167   FIXME( ":quick stub\n" );
00168 
00169   /* Ok. Cheat and don't search for the correct stuff just take the first.
00170    * FIXME: In the future how are we to know what is _THE_ enum we used?
00171    *        This is going to have to go into dplay somehow. Perhaps it
00172    *        comes back with app server id for the join command! Oh...that
00173    *        must be it. That would make this method obsolete once that's
00174    *        in place.
00175    */
00176 #if 1
00177   return lpCache->first.lpQHFirst->lpNSAddrHdr;
00178 #else
00179   /* FIXME: Should convert over to this */
00180   return lpCache->bNsIsLocal ? lpCache->lpLocalAddrHdr
00181                              : lpCache->lpRemoteAddrHdr;
00182 #endif
00183 }
00184 
00185 /* Get the magic number associated with the Name Server */
00186 DWORD NS_GetNsMagic( LPVOID lpNSInfo )
00187 {
00188   LPDWORD lpHdrInfo = (LPDWORD)NS_GetNSAddr( lpNSInfo );
00189 
00190   return lpHdrInfo[1];
00191 }
00192 
00193 /* Get the magic number associated with the non NS end */
00194 DWORD NS_GetOtherMagic( LPVOID lpNSInfo )
00195 {
00196   lpNSCache lpCache = (lpNSCache)lpNSInfo;
00197 
00198   return ((LPDWORD)lpCache->lpLocalAddrHdr)[1];
00199 }
00200 
00201 void NS_SetLocalAddr( LPVOID lpNSInfo, LPCVOID lpHdr, DWORD dwHdrSize )
00202 {
00203   lpNSCache lpCache = (lpNSCache)lpNSInfo;
00204 
00205   lpCache->lpLocalAddrHdr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwHdrSize );
00206 
00207   CopyMemory( lpCache->lpLocalAddrHdr, lpHdr, dwHdrSize );
00208 }
00209 
00210 /* This function is responsible for sending a request for all other known
00211    nameservers to send us what sessions they have registered locally
00212  */
00213 HRESULT NS_SendSessionRequestBroadcast( LPCGUID lpcGuid,
00214                                         DWORD dwFlags,
00215                                         LPSPINITDATA lpSpData )
00216 
00217 {
00218   DPSP_ENUMSESSIONSDATA data;
00219   LPDPMSG_ENUMSESSIONSREQUEST lpMsg;
00220 
00221   TRACE( "enumerating for guid %s\n", debugstr_guid( lpcGuid ) );
00222 
00223   /* Get the SP to deal with sending the EnumSessions request */
00224   FIXME( ": not all data fields are correct\n" );
00225 
00226   data.dwMessageSize = lpSpData->dwSPHeaderSize + sizeof( *lpMsg ); /*FIXME!*/
00227   data.lpMessage = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
00228                               data.dwMessageSize );
00229   data.lpISP = lpSpData->lpISP;
00230   data.bReturnStatus = (dwFlags & DPENUMSESSIONS_RETURNSTATUS) ? TRUE : FALSE;
00231 
00232 
00233   lpMsg = (LPDPMSG_ENUMSESSIONSREQUEST)(((BYTE*)data.lpMessage)+lpSpData->dwSPHeaderSize);
00234 
00235   /* Setup EnumSession request message */
00236   lpMsg->envelope.dwMagic    = DPMSGMAGIC_DPLAYMSG;
00237   lpMsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREQUEST;
00238   lpMsg->envelope.wVersion   = DPMSGVER_DP6;
00239 
00240   lpMsg->dwPasswordSize = 0; /* FIXME: If enumerating passwords..? */
00241   lpMsg->dwFlags        = dwFlags;
00242 
00243   CopyMemory( &lpMsg->guidApplication, lpcGuid, sizeof( *lpcGuid ) );
00244 
00245   return (lpSpData->lpCB->EnumSessions)( &data );
00246 }
00247 
00248 /* Delete a name server node which has been allocated on the heap */
00249 DPQ_DECL_DELETECB( cbDeleteNSNodeFromHeap, lpNSCacheData )
00250 {
00251   /* NOTE: This proc doesn't deal with the walking pointer */
00252 
00253   /* FIXME: Memory leak on data (contained ptrs) */
00254   HeapFree( GetProcessHeap(), 0, elem->data );
00255   HeapFree( GetProcessHeap(), 0, elem->lpNSAddrHdr );
00256   HeapFree( GetProcessHeap(), 0, elem );
00257 }
00258 
00259 /* Render all data in a session cache invalid */
00260 void NS_InvalidateSessionCache( LPVOID lpNSInfo )
00261 {
00262   lpNSCache lpCache = (lpNSCache)lpNSInfo;
00263 
00264   if( lpCache == NULL )
00265   {
00266     ERR( ": invalidate nonexistent cache\n" );
00267     return;
00268   }
00269 
00270   DPQ_DELETEQ( lpCache->first, next, lpNSCacheData, cbDeleteNSNodeFromHeap );
00271 
00272   /* NULL out the walking pointer */
00273   lpCache->present = NULL;
00274 
00275   lpCache->bNsIsLocal = FALSE;
00276 
00277 }
00278 
00279 /* Create and initialize a session cache */
00280 BOOL NS_InitializeSessionCache( LPVOID* lplpNSInfo )
00281 {
00282   lpNSCache lpCache = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof( *lpCache ) );
00283 
00284   *lplpNSInfo = lpCache;
00285 
00286   if( lpCache == NULL )
00287   {
00288     return FALSE;
00289   }
00290 
00291   DPQ_INIT(lpCache->first);
00292   lpCache->present = NULL;
00293 
00294   lpCache->bNsIsLocal = FALSE;
00295 
00296   return TRUE;
00297 }
00298 
00299 /* Delete a session cache */
00300 void NS_DeleteSessionCache( LPVOID lpNSInfo )
00301 {
00302   NS_InvalidateSessionCache( (lpNSCache)lpNSInfo );
00303 }
00304 
00305 /* Reinitialize the present pointer for this cache */
00306 void NS_ResetSessionEnumeration( LPVOID lpNSInfo )
00307 {
00308   ((lpNSCache)lpNSInfo)->present = ((lpNSCache)lpNSInfo)->first.lpQHFirst;
00309 }
00310 
00311 LPDPSESSIONDESC2 NS_WalkSessions( LPVOID lpNSInfo )
00312 {
00313   LPDPSESSIONDESC2 lpSessionDesc;
00314   lpNSCache lpCache = (lpNSCache)lpNSInfo;
00315 
00316   /* FIXME: The pointers could disappear when walking if a prune happens */
00317 
00318   /* Test for end of the list */
00319   if( lpCache->present == NULL )
00320   {
00321     return NULL;
00322   }
00323 
00324   lpSessionDesc = lpCache->present->data;
00325 
00326   /* Advance tracking pointer */
00327   lpCache->present = lpCache->present->next.lpQNext;
00328 
00329   return lpSessionDesc;
00330 }
00331 
00332 /* This method should check to see if there are any sessions which are
00333  * older than the criteria. If so, just delete that information.
00334  */
00335 /* FIXME: This needs to be called by some periodic timer */
00336 void NS_PruneSessionCache( LPVOID lpNSInfo )
00337 {
00338   lpNSCache     lpCache = lpNSInfo;
00339 
00340   const DWORD dwPresentTime = timeGetTime();
00341   const DWORD dwPrunePeriod = DPMSG_WAIT_60_SECS; /* is 60 secs enough? */
00342 
00343   /* This silly little algorithm is based on the fact we keep entries in
00344    * the queue in a time based order. It also assumes that it is not possible
00345    * to wrap around over yourself (which is not unreasonable).
00346    * The if statements verify if the first entry in the queue is less
00347    * than dwPrunePeriod old depending on the "clock" roll over.
00348    */
00349   for( ;; )
00350   {
00351     lpNSCacheData lpFirstData;
00352 
00353     if( DPQ_IS_EMPTY(lpCache->first) )
00354     {
00355       /* Nothing to prune */
00356       break;
00357     }
00358 
00359     /* Deal with time in a wrap around safe manner - unsigned arithmetic.
00360      * Check the difference in time */
00361     if( (dwPresentTime - (DPQ_FIRST(lpCache->first)->dwTime)) < dwPrunePeriod )
00362     {
00363       /* First entry has not expired yet; don't prune */
00364       break;
00365     }
00366 
00367     lpFirstData = DPQ_FIRST(lpCache->first);
00368     DPQ_REMOVE( lpCache->first, DPQ_FIRST(lpCache->first), next );
00369     cbDeleteNSNodeFromHeap( lpFirstData );
00370   }
00371 
00372 }
00373 
00374 /* NAME SERVER Message stuff */
00375 void NS_ReplyToEnumSessionsRequest( LPCVOID lpcMsg,
00376                                     LPVOID* lplpReplyData,
00377                                     LPDWORD lpdwReplySize,
00378                                     IDirectPlay2Impl* lpDP )
00379 {
00380   LPDPMSG_ENUMSESSIONSREPLY rmsg;
00381   DWORD dwVariableSize;
00382   DWORD dwVariableLen;
00383   /* LPCDPMSG_ENUMSESSIONSREQUEST msg = (LPDPMSG_ENUMSESSIONSREQUEST)lpcMsg; */
00384   BOOL bAnsi = TRUE; /* FIXME: This needs to be in the DPLAY interface */
00385 
00386   FIXME( ": few fixed + need to check request for response\n" );
00387 
00388   if (bAnsi)
00389   {
00390       dwVariableLen = MultiByteToWideChar( CP_ACP, 0,
00391                                            lpDP->dp2->lpSessionDesc->lpszSessionNameA,
00392                                            -1, NULL, 0 );
00393   }
00394   else
00395   {
00396       dwVariableLen = strlenW( lpDP->dp2->lpSessionDesc->lpszSessionName ) + 1;
00397   }
00398 
00399   dwVariableSize = dwVariableLen * sizeof( WCHAR );
00400 
00401   *lpdwReplySize = lpDP->dp2->spData.dwSPHeaderSize +
00402                      sizeof( *rmsg ) + dwVariableSize;
00403   *lplpReplyData = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY,
00404                               *lpdwReplySize );
00405 
00406   rmsg = (LPDPMSG_ENUMSESSIONSREPLY)( (BYTE*)*lplpReplyData +
00407                                              lpDP->dp2->spData.dwSPHeaderSize);
00408 
00409   rmsg->envelope.dwMagic    = DPMSGMAGIC_DPLAYMSG;
00410   rmsg->envelope.wCommandId = DPMSGCMD_ENUMSESSIONSREPLY;
00411   rmsg->envelope.wVersion   = DPMSGVER_DP6;
00412 
00413   CopyMemory( &rmsg->sd, lpDP->dp2->lpSessionDesc,
00414               sizeof( lpDP->dp2->lpSessionDesc->dwSize ) );
00415   rmsg->dwUnknown = 0x0000005c;
00416   if( bAnsi )
00417   {
00418       MultiByteToWideChar( CP_ACP, 0, lpDP->dp2->lpSessionDesc->lpszSessionNameA, -1,
00419                            (LPWSTR)(rmsg+1), dwVariableLen );
00420   }
00421   else
00422   {
00423       strcpyW( (LPWSTR)(rmsg+1), lpDP->dp2->lpSessionDesc->lpszSessionName );
00424   }
00425 }

Generated on Sun May 27 2012 04:21:38 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.