Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

856 lines
28 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: Endpoint.h
  6. * Content: Winsock endpoint
  7. *
  8. *
  9. * History:
  10. * Date By Reason
  11. * ==== == ======
  12. * 01/20/1999 jtk Created
  13. * 05/11/1999 jtk Split out to make a base class
  14. * 01/10/2000 rmt Updated to build with Millenium build process
  15. * 03/22/2000 jtk Updated with changes to interface names
  16. * 03/12/2001 mjn Added ENDPOINT_STATE_WAITING_TO_COMPLETE, m_dwThreadCount
  17. * 10/10/2001 vanceo Added multicast code
  18. ***************************************************************************/
  19. #ifndef __ENDPOINT_H__
  20. #define __ENDPOINT_H__
  21. //**********************************************************************
  22. // Constant definitions
  23. //**********************************************************************
  24. #define TEMP_HOSTNAME_LENGTH 100
  25. //
  26. // enumeration of types of endpoints
  27. //
  28. typedef enum _ENDPOINT_TYPE
  29. {
  30. ENDPOINT_TYPE_UNKNOWN = 0, // unknown
  31. ENDPOINT_TYPE_CONNECT, // endpoint is for connect
  32. ENDPOINT_TYPE_LISTEN, // endpoint is for enum
  33. ENDPOINT_TYPE_ENUM, // endpoint is for listen
  34. ENDPOINT_TYPE_CONNECT_ON_LISTEN, // endpoint is for new connect coming from a listen
  35. #ifndef DPNBUILD_NOMULTICAST
  36. ENDPOINT_TYPE_MULTICAST_SEND, // endpoint is for sending multicasts
  37. ENDPOINT_TYPE_MULTICAST_LISTEN, // endpoint is for receiving multicasts
  38. ENDPOINT_TYPE_MULTICAST_RECEIVE, // endpoint is for receiving multicasts from a specific sender
  39. #endif // ! DPNBUILD_NOMULTICAST
  40. } ENDPOINT_TYPE;
  41. //
  42. // enumeration of the states an endpoint can be in
  43. //
  44. typedef enum
  45. {
  46. ENDPOINT_STATE_UNINITIALIZED = 0, // uninitialized state
  47. ENDPOINT_STATE_ATTEMPTING_ENUM, // attempting to enum
  48. ENDPOINT_STATE_ENUM, // endpoint is supposed to enum connections
  49. ENDPOINT_STATE_ATTEMPTING_CONNECT, // attempting to connect
  50. ENDPOINT_STATE_CONNECT_CONNECTED, // endpoint is supposed to connect and is connected
  51. ENDPOINT_STATE_ATTEMPTING_LISTEN, // attempting to listen
  52. ENDPOINT_STATE_LISTEN, // endpoint is supposed to listen for connections
  53. ENDPOINT_STATE_DISCONNECTING, // endpoint is disconnecting
  54. ENDPOINT_STATE_WAITING_TO_COMPLETE, // endpoint is waiting to complete
  55. ENDPOINT_STATE_MAX
  56. } ENDPOINT_STATE;
  57. //
  58. // enumeration of the states an endpoint uses to determine whether to accept an enum or not
  59. //
  60. typedef enum _ENUMSALLOWEDSTATE
  61. {
  62. ENUMSNOTREADY, // enums shouldn't be accepted yet
  63. ENUMSALLOWED, // enums can be accepted
  64. ENUMSDISALLOWED // enums must not be accepted
  65. } ENUMSALLOWEDSTATE;
  66. //**********************************************************************
  67. // Macro definitions
  68. //**********************************************************************
  69. //**********************************************************************
  70. // Structure definitions
  71. //**********************************************************************
  72. //
  73. // forward references
  74. //
  75. class CSocketPort;
  76. class CSocketAddress;
  77. //
  78. // structure to bind extra information to an enum query to be used on enum reponse
  79. //
  80. typedef struct _ENDPOINT_ENUM_QUERY_CONTEXT
  81. {
  82. SPIE_QUERY EnumQueryData;
  83. HANDLE hEndpoint;
  84. DWORD dwEnumKey;
  85. CSocketAddress *pReturnAddress;
  86. } ENDPOINT_ENUM_QUERY_CONTEXT;
  87. //
  88. // structure to hold command parameters for endpoints
  89. //
  90. typedef struct _ENDPOINT_COMMAND_PARAMETERS
  91. {
  92. union // Local copy of the pending command data.
  93. { // This data contains the pointers to the
  94. SPCONNECTDATA ConnectData; // active command, and the user context.
  95. SPLISTENDATA ListenData; //
  96. SPENUMQUERYDATA EnumQueryData; //
  97. } PendingCommandData; //
  98. GATEWAY_BIND_TYPE GatewayBindType; // type of NAT binding that should be made for the endpoint
  99. DWORD dwEnumSendIndex; // index of time stamp on enumeration to be sent
  100. DWORD dwEnumSendTimes[ ENUM_RTT_ARRAY_SIZE ]; // times of last enumeration sends
  101. static void PoolInitFunction( void* pvItem, void* pvContext)
  102. {
  103. memset(pvItem, 0, sizeof(_ENDPOINT_COMMAND_PARAMETERS));
  104. }
  105. } ENDPOINT_COMMAND_PARAMETERS;
  106. //**********************************************************************
  107. // Variable definitions
  108. //**********************************************************************
  109. //**********************************************************************
  110. // Function prototypes
  111. //**********************************************************************
  112. //**********************************************************************
  113. // Class definition
  114. //**********************************************************************
  115. //
  116. // class to act as a key for the enum lists in socket ports
  117. //
  118. class CEndpointEnumKey
  119. {
  120. public:
  121. CEndpointEnumKey() { };
  122. ~CEndpointEnumKey() { };
  123. const WORD GetKey( void ) const { return ( m_wKey & ~( ENUM_RTT_MASK ) ); }
  124. void SetKey( const WORD wNewKey ) { m_wKey = wNewKey; };
  125. #undef DPF_MODNAME
  126. #define DPF_MODNAME "CEndpointEnumKey::CompareFunction"
  127. static BOOL CompareFunction( PVOID pvKey1, PVOID pvKey2 )
  128. {
  129. const CEndpointEnumKey* pEPEnumKey1 = (CEndpointEnumKey*)pvKey1;
  130. const CEndpointEnumKey* pEPEnumKey2 = (CEndpointEnumKey*)pvKey2;
  131. return (pEPEnumKey1->GetKey() == pEPEnumKey2->GetKey());
  132. }
  133. #undef DPF_MODNAME
  134. #define DPF_MODNAME "CEndpointEnumKey::HashFunction"
  135. static DWORD HashFunction( PVOID pvKey, BYTE bBitDepth )
  136. {
  137. DWORD dwReturn;
  138. UINT_PTR Temp;
  139. const CEndpointEnumKey* pEPEnumKey = (CEndpointEnumKey*)pvKey;
  140. DNASSERT(pvKey != NULL);
  141. //
  142. // initialize
  143. //
  144. dwReturn = 0;
  145. //
  146. // hash enum key
  147. //
  148. Temp = pEPEnumKey->GetKey();
  149. do
  150. {
  151. dwReturn ^= Temp & ( ( 1 << bBitDepth ) - 1 );
  152. Temp >>= bBitDepth;
  153. } while ( Temp != 0 );
  154. return dwReturn;
  155. }
  156. private:
  157. WORD m_wKey;
  158. };
  159. #ifndef DPNBUILD_ONLYONETHREAD
  160. #pragma pack(push, 4)
  161. typedef struct _SEQUENCEDREFCOUNT
  162. {
  163. WORD wRefCount;
  164. WORD wSequence;
  165. } SEQUENCEDREFCOUNT;
  166. #pragma pack(pop)
  167. #endif // ! DPNBUILD_ONLYONETHREAD
  168. //
  169. // class for an endpoint
  170. //
  171. class CEndpoint
  172. {
  173. public:
  174. #undef DPF_MODNAME
  175. #define DPF_MODNAME "CEndpoint::Lock"
  176. void Lock( void )
  177. {
  178. DNEnterCriticalSection( &m_Lock );
  179. }
  180. #undef DPF_MODNAME
  181. #define DPF_MODNAME "CEndpoint::Unlock"
  182. void Unlock( void )
  183. {
  184. DNLeaveCriticalSection( &m_Lock );
  185. }
  186. #undef DPF_MODNAME
  187. #define DPF_MODNAME "CEndpoint::AddCommandRef"
  188. BOOL AddCommandRef( void )
  189. {
  190. #ifdef DPNBUILD_ONLYONETHREAD
  191. LONG lResult;
  192. DNASSERT(m_lCommandRefCount >= 0);
  193. //
  194. // Check if the command ref count is 0 at this moment. If it is, then
  195. // the endpoint must be unbinding and this new reference should fail.
  196. //
  197. if (m_lCommandRefCount == 0)
  198. {
  199. DPFX(DPFPREP, 3, "Endpoint 0x%p command refcount is 0, not allowing new command ref.", this);
  200. return FALSE;
  201. }
  202. lResult = DNInterlockedIncrement( const_cast<LONG*>(&m_lCommandRefCount) );
  203. DPFX(DPFPREP, 9, "Endpoint 0x%p command refcount = %i", this, lResult);
  204. #else // ! DPNBUILD_ONLYONETHREAD
  205. SEQUENCEDREFCOUNT OldCommandRefCount;
  206. SEQUENCEDREFCOUNT NewCommandRefCount;
  207. LONG lResult;
  208. //
  209. // Check if the command ref count is 0 at this moment. If it is, then
  210. // the endpoint must be unbinding and this new reference should fail.
  211. // We go through a few hoops to make sure that the ref count doesn't
  212. // go to 0 while we're trying to add a reference.
  213. //
  214. do
  215. {
  216. DBG_CASSERT(sizeof(m_CommandRefCount) == sizeof(LONG));
  217. *((LONG*) (&OldCommandRefCount)) = *((volatile LONG *) (&m_CommandRefCount));
  218. if (OldCommandRefCount.wRefCount == 0)
  219. {
  220. DPFX(DPFPREP, 3, "Endpoint 0x%p command refcount is 0, not allowing new command ref.", this);
  221. return FALSE;
  222. }
  223. DNASSERT(OldCommandRefCount.wRefCount < 0xFFFF);
  224. NewCommandRefCount.wRefCount = OldCommandRefCount.wRefCount + 1;
  225. NewCommandRefCount.wSequence = OldCommandRefCount.wSequence + 1;
  226. lResult = DNInterlockedCompareExchange((LONG*) (&m_CommandRefCount),
  227. (*(LONG*) (&NewCommandRefCount)),
  228. (*(LONG*) (&OldCommandRefCount)));
  229. }
  230. while (lResult != (*(LONG*) (&OldCommandRefCount)));
  231. DPFX(DPFPREP, 9, "Endpoint 0x%p command refcount = %i", this, NewCommandRefCount.wRefCount);
  232. #endif // ! DPNBUILD_ONLYONETHREAD
  233. AddRef();
  234. return TRUE;
  235. }
  236. #undef DPF_MODNAME
  237. #define DPF_MODNAME "CEndpoint::DecCommandRef"
  238. void DecCommandRef( void )
  239. {
  240. #ifdef DPNBUILD_ONLYONETHREAD
  241. LONG lResult;
  242. DNASSERT(m_lCommandRefCount > 0);
  243. lResult = DNInterlockedDecrement( const_cast<LONG*>(&m_lCommandRefCount) );
  244. if ( lResult == 0 )
  245. {
  246. DPFX(DPFPREP, 9, "Endpoint 0x%p command refcount = 0, cleaning up command.", this);
  247. CleanUpCommand();
  248. }
  249. else
  250. {
  251. DPFX(DPFPREP, 9, "Endpoint 0x%p command refcount = %i", this, lResult);
  252. }
  253. #else // ! DPNBUILD_ONLYONETHREAD
  254. SEQUENCEDREFCOUNT OldCommandRefCount;
  255. SEQUENCEDREFCOUNT NewCommandRefCount;
  256. LONG lResult;
  257. do
  258. {
  259. DBG_CASSERT(sizeof(m_CommandRefCount) == sizeof(LONG));
  260. *((LONG*) (&OldCommandRefCount)) = *((volatile LONG *) (&m_CommandRefCount));
  261. DNASSERT(OldCommandRefCount.wRefCount > 0);
  262. NewCommandRefCount.wRefCount = OldCommandRefCount.wRefCount - 1;
  263. NewCommandRefCount.wSequence = OldCommandRefCount.wSequence + 1;
  264. lResult = DNInterlockedCompareExchange((LONG*) (&m_CommandRefCount),
  265. (*(LONG*) (&NewCommandRefCount)),
  266. (*(LONG*) (&OldCommandRefCount)));
  267. }
  268. while (lResult != (*(LONG*) (&OldCommandRefCount)));
  269. if ( NewCommandRefCount.wRefCount == 0 )
  270. {
  271. DPFX(DPFPREP, 9, "Endpoint 0x%p command refcount = 0, cleaning up command.", this);
  272. CleanUpCommand();
  273. }
  274. else
  275. {
  276. DPFX(DPFPREP, 9, "Endpoint 0x%p command refcount = %i", this, NewCommandRefCount.wRefCount);
  277. }
  278. #endif // ! DPNBUILD_ONLYONETHREAD
  279. DecRef();
  280. }
  281. #undef DPF_MODNAME
  282. #define DPF_MODNAME "CEndpoint::AddRef"
  283. void AddRef( void )
  284. {
  285. LONG lResult;
  286. DNASSERT( m_lRefCount != 0 );
  287. lResult = DNInterlockedIncrement( const_cast<LONG*>(&m_lRefCount) );
  288. DPFX(DPFPREP, 9, "Endpoint 0x%p refcount = %i", this, lResult);
  289. }
  290. #undef DPF_MODNAME
  291. #define DPF_MODNAME "CEndpoint::DecRef"
  292. void DecRef( void )
  293. {
  294. LONG lResult;
  295. DNASSERT( m_lRefCount != 0 );
  296. lResult = DNInterlockedDecrement( const_cast<LONG*>(&m_lRefCount) );
  297. if ( lResult == 0 )
  298. {
  299. DPFX(DPFPREP, 9, "Endpoint 0x%p refcount = 0, releasing.", this, lResult);
  300. g_EndpointPool.Release( this );
  301. }
  302. else
  303. {
  304. DPFX(DPFPREP, 9, "Endpoint 0x%p refcount = %i", this, lResult);
  305. }
  306. }
  307. #ifndef DPNBUILD_NOSPUI
  308. #undef DPF_MODNAME
  309. #define DPF_MODNAME "CEndpoint::SetTempHostName"
  310. void SetTempHostName( const TCHAR *const pHostName, const UINT_PTR uHostNameLength )
  311. {
  312. DNASSERT( pHostName[ uHostNameLength ] == TEXT('\0') );
  313. DNASSERT( ( uHostNameLength + 1 ) <= LENGTHOF( m_TempHostName ) );
  314. memcpy( m_TempHostName, pHostName, ( uHostNameLength + 1) * sizeof(TCHAR) );
  315. }
  316. #endif // ! DPNBUILD_NOSPUI
  317. HRESULT Open( const ENDPOINT_TYPE EndpointType,
  318. IDirectPlay8Address *const pDP8Address,
  319. PVOID pvSessionData,
  320. DWORD dwSessionDataSize,
  321. const CSocketAddress *const pSocketAddress );
  322. void Close( const HRESULT hActiveCommandResult );
  323. void ReinitializeWithBroadcast( void )
  324. {
  325. m_pRemoteMachineAddress->InitializeWithBroadcastAddress();
  326. }
  327. void *GetUserEndpointContext( void ) const
  328. {
  329. return m_pUserEndpointContext;
  330. }
  331. #undef DPF_MODNAME
  332. #define DPF_MODNAME "CEndpoint::SetUserEndpointContext"
  333. void SetUserEndpointContext( void *const pUserEndpointContext )
  334. {
  335. DNASSERT( ( m_pUserEndpointContext == NULL ) ||
  336. ( pUserEndpointContext == NULL ) );
  337. m_pUserEndpointContext = pUserEndpointContext;
  338. }
  339. const ENDPOINT_TYPE GetType( void ) const
  340. {
  341. return m_EndpointType;
  342. }
  343. const ENDPOINT_STATE GetState( void ) const
  344. {
  345. return m_State;
  346. }
  347. #undef DPF_MODNAME
  348. #define DPF_MODNAME "CEndpoint::SetState"
  349. void SetState( const ENDPOINT_STATE EndpointState )
  350. {
  351. DNASSERT( (EndpointState == ENDPOINT_STATE_DISCONNECTING ) || (EndpointState == ENDPOINT_STATE_WAITING_TO_COMPLETE));
  352. AssertCriticalSectionIsTakenByThisThread( &m_Lock, TRUE );
  353. m_State = EndpointState;
  354. }
  355. const GATEWAY_BIND_TYPE GetGatewayBindType( void ) const
  356. {
  357. return m_GatewayBindType;
  358. }
  359. #undef DPF_MODNAME
  360. #define DPF_MODNAME "CEndpoint::SetGatewayBindType"
  361. void SetGatewayBindType( const GATEWAY_BIND_TYPE GatewayBindType )
  362. {
  363. DNASSERT( (m_GatewayBindType != GATEWAY_BIND_TYPE_UNKNOWN) || (GatewayBindType != GATEWAY_BIND_TYPE_UNKNOWN));
  364. m_GatewayBindType = GatewayBindType;
  365. }
  366. #undef DPF_MODNAME
  367. #define DPF_MODNAME "CEndpoint::GetWritableRemoteAddressPointer"
  368. CSocketAddress *GetWritableRemoteAddressPointer( void ) const
  369. {
  370. DNASSERT( m_pRemoteMachineAddress != NULL );
  371. return m_pRemoteMachineAddress;
  372. }
  373. #undef DPF_MODNAME
  374. #define DPF_MODNAME "CEndpoint::GetRemoteAddressPointer"
  375. const CSocketAddress *GetRemoteAddressPointer( void ) const
  376. {
  377. DNASSERT( m_pRemoteMachineAddress != NULL );
  378. return m_pRemoteMachineAddress;
  379. }
  380. void ChangeLoopbackAlias( const CSocketAddress *const pSocketAddress ) const;
  381. const CEndpointEnumKey *GetEnumKey( void ) const
  382. {
  383. return &m_EnumKey;
  384. }
  385. void SetEnumKey( const WORD wKey )
  386. {
  387. m_EnumKey.SetKey( wKey );
  388. }
  389. void SetEnumsAllowedOnListen( const BOOL fAllowed, const BOOL fOverwritePrevious );
  390. const BOOL IsEnumAllowedOnListen( void ) const
  391. {
  392. return (m_EnumsAllowedState == ENUMSALLOWED) ? TRUE : FALSE;
  393. }
  394. #undef DPF_MODNAME
  395. #define DPF_MODNAME "CEndpoint::GetLocalAdapterDP8Address"
  396. IDirectPlay8Address *GetLocalAdapterDP8Address( const SP_ADDRESS_TYPE AddressType )
  397. {
  398. DNASSERT( GetSocketPort() != NULL );
  399. #ifdef DPNBUILD_XNETSECURITY
  400. return GetSocketPort()->GetDP8BoundNetworkAddress( AddressType,
  401. ((IsUsingXNetSecurity()) ? &m_ullKeyID : NULL),
  402. GetGatewayBindType() );
  403. #else // ! DPNBUILD_XNETSECURITY
  404. return GetSocketPort()->GetDP8BoundNetworkAddress( AddressType, GetGatewayBindType() );
  405. #endif // ! DPNBUILD_XNETSECURITY
  406. }
  407. #undef DPF_MODNAME
  408. #define DPF_MODNAME "CEndpoint::GetRemoteHostDP8Address"
  409. IDirectPlay8Address *GetRemoteHostDP8Address( void )
  410. {
  411. DNASSERT( m_pRemoteMachineAddress != NULL );
  412. #ifdef DPNBUILD_XNETSECURITY
  413. return m_pRemoteMachineAddress->DP8AddressFromSocketAddress( ((IsUsingXNetSecurity()) ? &m_ullKeyID : NULL),
  414. NULL,
  415. SP_ADDRESS_TYPE_HOST );
  416. #else // ! DPNBUILD_XNETSECURITY
  417. return m_pRemoteMachineAddress->DP8AddressFromSocketAddress( SP_ADDRESS_TYPE_HOST );
  418. #endif // ! DPNBUILD_XNETSECURITY
  419. }
  420. CSocketPort *GetSocketPort( void ) const
  421. {
  422. return m_pSocketPort;
  423. }
  424. #undef DPF_MODNAME
  425. #define DPF_MODNAME "CEndpoint::SetSocketPort"
  426. void SetSocketPort( CSocketPort *const pSocketPort )
  427. {
  428. DNASSERT( ( m_pSocketPort == NULL ) || ( pSocketPort == NULL ) );
  429. m_pSocketPort = pSocketPort;
  430. }
  431. #undef DPF_MODNAME
  432. #define DPF_MODNAME "CEndpoint::SetCommandParametersGatewayBindType"
  433. void SetCommandParametersGatewayBindType( GATEWAY_BIND_TYPE GatewayBindType )
  434. {
  435. DNASSERT( GetCommandParameters() != NULL );
  436. GetCommandParameters()->GatewayBindType = GatewayBindType;
  437. }
  438. #if ((! defined(DPNBUILD_NOWINSOCK2)) || (! defined(DPNBUILD_NOREGISTRY)))
  439. void MungeProxiedAddress( const CSocketPort * const pSocketPort,
  440. IDirectPlay8Address *const pHostAddress,
  441. const BOOL fEnum );
  442. #endif // ! DPNBUILD_NOWINSOCK2 or ! DPNBUILD_NOREGISTRY
  443. HRESULT CopyConnectData( const SPCONNECTDATA *const pConnectData );
  444. static void WINAPI ConnectJobCallback( void * const pvContext, void * const pvTimerData, const UINT uiTimerUnique );
  445. HRESULT CompleteConnect( void );
  446. #undef DPF_MODNAME
  447. #define DPF_MODNAME "CEndpoint::CleanupConnect"
  448. void CleanupConnect( void )
  449. {
  450. DNASSERT( GetCommandParameters() != NULL );
  451. DNASSERT( GetCommandParameters()->PendingCommandData.ConnectData.pAddressHost != NULL );
  452. IDirectPlay8Address_Release( GetCommandParameters()->PendingCommandData.ConnectData.pAddressHost );
  453. DNASSERT( GetCommandParameters()->PendingCommandData.ConnectData.pAddressDeviceInfo != NULL );
  454. IDirectPlay8Address_Release( GetCommandParameters()->PendingCommandData.ConnectData.pAddressDeviceInfo );
  455. }
  456. BOOL ConnectHasBeenSignalled( void ) const { return m_fConnectSignalled; }
  457. void SignalDisconnect( void );
  458. HRESULT Disconnect( void );
  459. void StopEnumCommand( const HRESULT hCommandResult );
  460. HRESULT CopyListenData( const SPLISTENDATA *const pListenData, IDirectPlay8Address *const pDeviceAddress );
  461. static void WINAPI ListenJobCallback( void * const pvContext, void * const pvTimerData, const UINT uiTimerUnique );
  462. HRESULT CompleteListen( void );
  463. HRESULT CopyEnumQueryData( const SPENUMQUERYDATA *const pEnumQueryData );
  464. static void WINAPI EnumQueryJobCallback( void * const pvContext, void * const pvTimerData, const UINT uiTimerUnique );
  465. HRESULT CompleteEnumQuery( void );
  466. #ifndef DPNBUILD_ONLYONETHREAD
  467. static void ConnectBlockingJobWrapper( void * const pvContext );
  468. void ConnectBlockingJob( void );
  469. static void ListenBlockingJobWrapper( void * const pvContext );
  470. void ListenBlockingJob( void );
  471. static void EnumQueryBlockingJobWrapper( void * const pvContext );
  472. void EnumQueryBlockingJob( void );
  473. #endif // ! DPNBUILD_ONLYONETHREAD
  474. #undef DPF_MODNAME
  475. #define DPF_MODNAME "CEndpoint::CleanupEnumQuery"
  476. void CleanupEnumQuery( void )
  477. {
  478. DNASSERT( GetCommandParameters() != NULL );
  479. DNASSERT( GetCommandParameters()->PendingCommandData.EnumQueryData.pAddressHost != NULL );
  480. IDirectPlay8Address_Release( GetCommandParameters()->PendingCommandData.EnumQueryData.pAddressHost );
  481. DNASSERT( GetCommandParameters()->PendingCommandData.EnumQueryData.pAddressDeviceInfo != NULL );
  482. IDirectPlay8Address_Release( GetCommandParameters()->PendingCommandData.EnumQueryData.pAddressDeviceInfo );
  483. }
  484. void ProcessEnumData( SPRECEIVEDBUFFER *const pBuffer, const DWORD dwEnumKey, const CSocketAddress *const pReturnSocketAddress );
  485. void ProcessEnumResponseData( SPRECEIVEDBUFFER *const pBuffer,
  486. const CSocketAddress *const pReturnSocketAddress,
  487. #ifdef DPNBUILD_XNETSECURITY
  488. const XNADDR *const pxnaddrReturn,
  489. #endif // DPNBUILD_XNETSECURITY
  490. const UINT_PTR uRTTIndex );
  491. void ProcessUserData( CReadIOData *const pReadData );
  492. void ProcessUserDataOnListen( CReadIOData *const pReadData, const CSocketAddress *const pSocketAddress );
  493. #ifndef DPNBUILD_NOMULTICAST
  494. void ProcessMcastDataFromUnknownSender( CReadIOData *const pReadData, const CSocketAddress *const pSocketAddress );
  495. #endif // ! DPNBUILD_NOMULTICAST
  496. #ifndef DPNBUILD_ONLYONEADAPTER
  497. void RemoveFromMultiplexList(void)
  498. {
  499. // requires SPData's socket data lock
  500. m_blMultiplex.RemoveFromList();
  501. }
  502. #endif // ! DPNBUILD_ONLYONEADAPTER
  503. void AddToSocketPortList( CBilink * pBilink)
  504. {
  505. // requires SPData's socket data lock
  506. m_blSocketPortList.InsertBefore( pBilink );
  507. }
  508. void RemoveFromSocketPortList(void)
  509. {
  510. // requires SPData's socket data lock
  511. m_blSocketPortList.RemoveFromList();
  512. }
  513. #undef DPF_MODNAME
  514. #define DPF_MODNAME "CEndpoint::EndpointFromSocketPortListBilink"
  515. static CEndpoint *EndpointFromSocketPortListBilink( CBilink *const pBilink )
  516. {
  517. DNASSERT( pBilink != NULL );
  518. return reinterpret_cast<CEndpoint*>( &reinterpret_cast<BYTE*>( pBilink )[ -OFFSETOF( CEndpoint, m_blSocketPortList ) ] );
  519. }
  520. //
  521. // Thread count references
  522. //
  523. DWORD AddRefThreadCount( void )
  524. {
  525. return( ++m_dwThreadCount );
  526. }
  527. DWORD DecRefThreadCount( void )
  528. {
  529. return( --m_dwThreadCount );
  530. }
  531. ENDPOINT_COMMAND_PARAMETERS *GetCommandParameters( void ) const
  532. {
  533. return m_pCommandParameters;
  534. }
  535. #undef DPF_MODNAME
  536. #define DPF_MODNAME "CEndpoint::IncNumReceives"
  537. void IncNumReceives( void )
  538. {
  539. //
  540. // Assume the lock is held.
  541. //
  542. m_dwNumReceives++;
  543. //
  544. // Make sure it hasn't wrapped back to 0.
  545. //
  546. if ( m_dwNumReceives == 0 )
  547. {
  548. DPFX(DPFPREP, 1, "Endpoint 0x%p number of receives wrapped, will be off by one from now on.",
  549. this);
  550. m_dwNumReceives++;
  551. }
  552. }
  553. DWORD GetNumReceives( void ) const
  554. {
  555. return m_dwNumReceives;
  556. }
  557. #ifndef DPNBUILD_NOSPUI
  558. //
  559. // UI functions
  560. //
  561. HRESULT ShowSettingsDialog( CThreadPool *const pThreadPool );
  562. void SettingsDialogComplete( const HRESULT hr );
  563. static void StopSettingsDialog( const HWND hDlg );
  564. HWND GetActiveDialogHandle( void ) const
  565. {
  566. return m_hActiveSettingsDialog;
  567. }
  568. #undef DPF_MODNAME
  569. #define DPF_MODNAME "CEndpoint::SetActiveDialogHandle"
  570. void SetActiveDialogHandle( const HWND hDialog )
  571. {
  572. DNASSERT( ( GetActiveDialogHandle() == NULL ) ||
  573. ( hDialog == NULL ) );
  574. m_hActiveSettingsDialog = hDialog;
  575. }
  576. #endif // ! DPNBUILD_NOSPUI
  577. #ifdef DPNBUILD_ASYNCSPSENDS
  578. static void WINAPI CompleteAsyncSend( void * const pvContext, void * const pvTimerData, const UINT uiTimerUnique );
  579. #endif // DPNBUILD_ASYNCSPSENDS
  580. #ifndef DPNBUILD_NOMULTICAST
  581. HRESULT EnableMulticastReceive( CSocketPort * const pSocketPort );
  582. HRESULT DisableMulticastReceive( void );
  583. #ifdef WINNT
  584. static void MADCAPTimerComplete( const HRESULT hResult, void * const pContext );
  585. static void MADCAPTimerFunction( void * const pContext );
  586. #endif // WINNT
  587. void GetScopeGuid( GUID * const pGuid ) { memcpy( pGuid, &m_guidMulticastScope, sizeof( m_guidMulticastScope ) ); };
  588. #endif // ! DPNBUILD_NOMULTICAST
  589. #ifdef DPNBUILD_XNETSECURITY
  590. BOOL IsUsingXNetSecurity( void ) { return m_fXNetSecurity; };
  591. #endif // DPNBUILD_XNETSECURITY
  592. #ifndef DPNBUILD_NONATHELP
  593. #undef DPF_MODNAME
  594. #define DPF_MODNAME "CEndpoint::SetUserTraversalMode"
  595. void SetUserTraversalMode( DWORD dwMode )
  596. {
  597. DNASSERT((dwMode == DPNA_TRAVERSALMODE_NONE) || (dwMode == DPNA_TRAVERSALMODE_PORTREQUIRED) || (dwMode == DPNA_TRAVERSALMODE_PORTRECOMMENDED));
  598. m_dwUserTraversalMode = dwMode;
  599. }
  600. DWORD GetUserTraversalMode( void ) const { return m_dwUserTraversalMode; }
  601. #endif // ! DPNBUILD_NONATHELP
  602. #ifdef DBG
  603. inline BOOL IsValid( void ) const
  604. {
  605. if (( m_Sig[0] != 'I' ) ||
  606. ( m_Sig[1] != 'P' ) ||
  607. ( m_Sig[2] != 'E' ) ||
  608. ( m_Sig[3] != 'P' ))
  609. {
  610. return FALSE;
  611. }
  612. return TRUE;
  613. }
  614. #endif // DBG
  615. //
  616. // pool functions
  617. //
  618. static BOOL PoolAllocFunction( void* pvItem, void* pvContext );
  619. static void PoolInitFunction( void* pvItem, void* pvContext );
  620. static void PoolReleaseFunction( void* pvItem );
  621. static void PoolDeallocFunction( void* pvItem );
  622. protected:
  623. BYTE m_Sig[4]; // debugging signature ('IPEP')
  624. #ifndef DPNBUILD_NOSPUI
  625. TCHAR m_TempHostName[ TEMP_HOSTNAME_LENGTH ];
  626. #endif // ! DPNBUILD_NOSPUI
  627. volatile ENDPOINT_STATE m_State; // endpoint state
  628. volatile BOOL m_fConnectSignalled; // Boolean indicating whether we've indicated a connection on this endpoint
  629. ENDPOINT_TYPE m_EndpointType; // type of endpoint
  630. CSocketAddress *m_pRemoteMachineAddress; // pointer to address of remote machine
  631. CSPData *m_pSPData; // pointer to SPData
  632. CSocketPort *m_pSocketPort; // pointer to associated socket port
  633. GATEWAY_BIND_TYPE m_GatewayBindType; // type of binding made (whether there should be a port mapping on the gateway or not)
  634. CEndpointEnumKey m_EnumKey; // key used for enums
  635. void *m_pUserEndpointContext; // context passed back with endpoint handles
  636. BOOL m_fListenStatusNeedsToBeIndicated;
  637. ENUMSALLOWEDSTATE m_EnumsAllowedState; // whether incoming enums can be processed by this LISTEN endpoint or not
  638. #ifndef DPNBUILD_ONLYONEADAPTER
  639. CBilink m_blMultiplex; // bilink in multiplexed command list, protected by SPData's socket data lock
  640. #endif // ! DPNBUILD_ONLYONEADAPTER
  641. CBilink m_blSocketPortList; // bilink in socketport list (not hash), protected by SPData's socket data lock
  642. DWORD m_dwNumReceives; // how many packets have been received by this CONNECT/CONNECT_ON_LISTEN endpoint, or 0 if none
  643. BOOL CommandPending( void ) const { return ( GetCommandParameters() != NULL ); }
  644. void SetPendingCommandResult( const HRESULT hr ) { m_hrPendingCommandResult = hr; }
  645. HRESULT PendingCommandResult( void ) const { return m_hrPendingCommandResult; }
  646. void CompletePendingCommand( const HRESULT hrCommandResult );
  647. HRESULT SignalConnect( SPIE_CONNECT *const pConnectData );
  648. #undef DPF_MODNAME
  649. #define DPF_MODNAME "CEndpoint::SetCommandParameters"
  650. void SetCommandParameters( ENDPOINT_COMMAND_PARAMETERS *const pCommandParameters )
  651. {
  652. DNASSERT( ( GetCommandParameters() == NULL ) ||
  653. ( pCommandParameters == NULL ) );
  654. m_pCommandParameters = pCommandParameters;
  655. }
  656. #ifndef DPNBUILD_ONLYONEADAPTER
  657. void SetEndpointID( const DWORD dwEndpointID ) { m_dwEndpointID = dwEndpointID; }
  658. DWORD GetEndpointID( void ) const { return m_dwEndpointID; }
  659. #endif // ! DPNBUILD_ONLYONEADAPTER
  660. DEBUG_ONLY( BOOL m_fEndpointOpen );
  661. #ifndef DPNBUILD_ONLYONETHREAD
  662. DNCRITICAL_SECTION m_Lock; // critical section
  663. #endif // !DPNBUILD_ONLYONETHREAD
  664. LONG m_lRefCount;
  665. #ifdef DPNBUILD_ONLYONETHREAD
  666. volatile LONG m_lCommandRefCount; // Command ref count. When this goes to zero, the endpoint is unbound from the CSocketPort
  667. #else // ! DPNBUILD_ONLYONETHREAD
  668. SEQUENCEDREFCOUNT m_CommandRefCount; // Command ref count. When this goes to zero, the endpoint is unbound from the CSocketPort
  669. #endif // ! DPNBUILD_ONLYONETHREAD
  670. DWORD volatile m_dwThreadCount; // Number of (ENUM) threads using endpoint
  671. #ifndef DPNBUILD_ONLYONEADAPTER
  672. DWORD m_dwEndpointID; // unique identifier for this endpoint
  673. #endif // ! DPNBUILD_ONLYONEADAPTER
  674. #ifndef DPNBUILD_NOMULTICAST
  675. GUID m_guidMulticastScope; // multicast scope being used
  676. #ifdef WINNT
  677. BOOL m_fMADCAPTimerJobSubmitted; // whether the MADCAP timer job has been submitted or not
  678. MCAST_LEASE_RESPONSE m_McastLeaseResponse; // information describing the MADCAP lease response
  679. #endif // WINNT
  680. #endif // ! DPNBUILD_NOMULTICAST
  681. #ifndef DPNBUILD_NOSPUI
  682. HWND m_hActiveSettingsDialog; // handle of active settings dialog
  683. #endif // !DPNBUILD_NOSPUI
  684. ENDPOINT_COMMAND_PARAMETERS *m_pCommandParameters; // pointer to command parameters
  685. HRESULT m_hrPendingCommandResult; // result for pending command
  686. CCommandData *m_pActiveCommandData; // pointer to command data that's embedded in the command parameters
  687. // We don't know where in the union the command data really is, and
  688. // finding it programmatically each time would bloat the code.
  689. #ifdef DPNBUILD_XNETSECURITY
  690. BOOL m_fXNetSecurity; // whether this endpoint is using XNet security or not
  691. GUID m_guidKey; // secure transport key GUID
  692. ULONGLONG m_ullKeyID; // secure transport key ID
  693. #endif // DPNBUILD_XNETSECURITY
  694. #ifndef DPNBUILD_NONATHELP
  695. DWORD m_dwUserTraversalMode; // the traversal mode specified by the user for this endpoint
  696. #endif // ! DPNBUILD_NONATHELP
  697. static void EnumCompleteWrapper( const HRESULT hCompletionCode, void *const pContext );
  698. static void EnumTimerCallback( void *const pContext );
  699. void EnumComplete( const HRESULT hCompletionCode );
  700. void CleanUpCommand( void );
  701. //
  702. // make copy constructor and assignment operator private and unimplemented
  703. // to prevent illegal copies from being made
  704. //
  705. CEndpoint( const CEndpoint & );
  706. CEndpoint& operator=( const CEndpoint & );
  707. };
  708. #undef DPF_MODNAME
  709. #endif // __ENDPOINT_H__