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.

423 lines
14 KiB

  1. /*==========================================================================
  2. *
  3. * Copyright (C) 1999-2002 Microsoft Corporation. All Rights Reserved.
  4. *
  5. * File: SocketPort.h
  6. * Content: Winsock socket port that manages data flow on a given adapter,
  7. * address and port.
  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. * 03/22/2000 jtk Updated with changes to interface names
  15. ***************************************************************************/
  16. #ifndef __SOCKET_PORT_H__
  17. #define __SOCKET_PORT_H__
  18. //**********************************************************************
  19. // Constant definitions
  20. //**********************************************************************
  21. //
  22. // states of socket port
  23. //
  24. typedef enum
  25. {
  26. SOCKET_PORT_STATE_UNKNOWN = 0,
  27. SOCKET_PORT_STATE_INITIALIZED,
  28. SOCKET_PORT_STATE_BOUND,
  29. SOCKET_PORT_STATE_UNBOUND,
  30. } SOCKET_PORT_STATE;
  31. //
  32. // enumeration of socket types
  33. //
  34. typedef enum _GATEWAY_BIND_TYPE
  35. {
  36. GATEWAY_BIND_TYPE_UNKNOWN = 0, // uninitialized
  37. GATEWAY_BIND_TYPE_DEFAULT, // map the local port to any random port on the server
  38. GATEWAY_BIND_TYPE_SPECIFIC, // map the local port to the same port on the server
  39. GATEWAY_BIND_TYPE_SPECIFIC_SHARED, // map the local port to the same port on the server and share it (DPNSVR listen socket port)
  40. GATEWAY_BIND_TYPE_NONE // don't map the local port on the server
  41. } GATEWAY_BIND_TYPE;
  42. //**********************************************************************
  43. // Macro definitions
  44. //**********************************************************************
  45. //**********************************************************************
  46. // Structure definitions
  47. //**********************************************************************
  48. //
  49. // forward references
  50. //
  51. class CSocketPort;
  52. //**********************************************************************
  53. // Variable definitions
  54. //**********************************************************************
  55. //**********************************************************************
  56. // Function prototypes
  57. //**********************************************************************
  58. typedef BOOL (CSocketPort::*PSOCKET_SERVICE_FUNCTION)( void );
  59. //**********************************************************************
  60. // Class definition
  61. //**********************************************************************
  62. //
  63. // reference to other classes and structures
  64. //
  65. #ifndef DPNBUILD_ONLYONEADAPTER
  66. class CAdapterEntry;
  67. #endif // ! DPNBUILD_ONLYONEADAPTER
  68. class CEndpoint;
  69. class CEndpointEnumKey;
  70. class CSPData;
  71. //
  72. // main class definition
  73. //
  74. class CSocketPort
  75. {
  76. public:
  77. HRESULT Initialize( CSocketData *const pSocketData,
  78. CThreadPool *const pThreadPool,
  79. CSocketAddress *const pAddress );
  80. HRESULT Deinitialize( void );
  81. #ifdef DPNBUILD_ONLYONEPROCESSOR
  82. HRESULT BindToNetwork( const GATEWAY_BIND_TYPE GatewayBindType );
  83. #else // ! DPNBUILD_ONLYONEPROCESSOR
  84. HRESULT BindToNetwork( const DWORD dwCPU, const GATEWAY_BIND_TYPE GatewayBindType );
  85. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  86. HRESULT UnbindFromNetwork( void );
  87. const CSocketAddress *const GetNetworkAddress( void ) const { return m_pNetworkSocketAddress; }
  88. const SOCKET GetSocket( void ) const { return m_Socket; }
  89. #undef DPF_MODNAME
  90. #define DPF_MODNAME "CSocketPort::AddRef"
  91. void AddRef( void )
  92. {
  93. LONG lResult;
  94. lResult = DNInterlockedIncrement( const_cast<LONG*>(&m_iRefCount) );
  95. //
  96. // NOTE: This generates a lot of spew, especially when running WinSock1 code
  97. // path, so it is at secret level 10!
  98. //
  99. DPFX(DPFPREP, 10, "Socket port 0x%p refcount = %i.", this, lResult );
  100. }
  101. #undef DPF_MODNAME
  102. #define DPF_MODNAME "CSocketPort::DecRef"
  103. void DecRef( void )
  104. {
  105. LONG lResult;
  106. DNASSERT( m_State != SOCKET_PORT_STATE_UNKNOWN );
  107. DNASSERT( m_iRefCount != 0 );
  108. //
  109. // Decrement the reference counts and return this item to the pool if nobody
  110. // is referencing it anymore.
  111. //
  112. lResult = DNInterlockedDecrement( const_cast<LONG*>(&m_iRefCount) );
  113. if ( lResult == 0 )
  114. {
  115. HRESULT hr;
  116. DNASSERT( m_iEndpointRefCount == 0 );
  117. //
  118. // There's no need to lock this socket port because this is the last
  119. // reference to it, nobody else will access it.
  120. //
  121. hr = Deinitialize();
  122. if ( hr != DPN_OK )
  123. {
  124. DPFX(DPFPREP, 0, "Problem deinitializing socket port 0x%p in DecRef!", this );
  125. DisplayDNError( 0, hr );
  126. }
  127. m_State = SOCKET_PORT_STATE_UNKNOWN;
  128. g_SocketPortPool.Release( this );
  129. }
  130. else
  131. {
  132. //
  133. // NOTE: This generates a lot of spew, especially when running WinSock1 code
  134. // path, so it is at secret level 10!
  135. //
  136. DPFX(DPFPREP, 10, "Not deinitializing socket port 0x%p, refcount = %i.", this, lResult );
  137. }
  138. }
  139. BOOL EndpointAddRef( void );
  140. DWORD EndpointDecRef( void );
  141. void Lock( void ) { DNEnterCriticalSection( &m_Lock ); }
  142. void Unlock( void ) { DNLeaveCriticalSection( &m_Lock ); }
  143. HRESULT BindEndpoint( CEndpoint *const pEndpoint, GATEWAY_BIND_TYPE GatewayBindType );
  144. void UnbindEndpoint( CEndpoint *const pEndpoint );
  145. #undef DPF_MODNAME
  146. #define DPF_MODNAME "CSocketPort::GetNewEnumKey"
  147. const WORD GetNewEnumKey( void )
  148. {
  149. WORD wReturn;
  150. DBG_CASSERT( ENUM_RTT_MASK == 0x0F );
  151. Lock();
  152. m_iEnumKey++;
  153. wReturn = (WORD) (m_iEnumKey << 4);
  154. Unlock();
  155. return wReturn;
  156. }
  157. DWORD GetSocketPortID( void ) const { return m_dwSocketPortID; }
  158. #ifndef DPNBUILD_NOWINSOCK2
  159. BOOL IsUsingProxyWinSockLSP( void ) const { return m_fUsingProxyWinSockLSP; }
  160. #endif // !DPNBUILD_NOWINSOCK2
  161. CSocketAddress *GetBoundNetworkAddress( const SP_ADDRESS_TYPE AddressType ) const;
  162. IDirectPlay8Address *GetDP8BoundNetworkAddress( const SP_ADDRESS_TYPE AddressType,
  163. #ifdef DPNBUILD_XNETSECURITY
  164. ULONGLONG * const pullKeyID,
  165. #endif // DPNBUILD_XNETSECURITY
  166. const GATEWAY_BIND_TYPE GatewayBindType ) const;
  167. #ifndef DPNBUILD_ONLYONEADAPTER
  168. CAdapterEntry *GetAdapterEntry( void ) const { return m_pAdapterEntry; }
  169. #undef DPF_MODNAME
  170. #define DPF_MODNAME "CSocketPort::SetAdapterEntry"
  171. void SetAdapterEntry( CAdapterEntry *const pAdapterEntry )
  172. {
  173. DNASSERT( ( m_pAdapterEntry == NULL ) || ( pAdapterEntry == NULL ) );
  174. m_pAdapterEntry = pAdapterEntry;
  175. }
  176. #endif // ! DPNBUILD_ONLYONEADAPTER
  177. static void WINAPI Winsock2ReceiveComplete( void * const pvContext, void * const pvTimerData, const UINT uiTimerUnique );
  178. //
  179. // Public service functions for Winsock1 since we can't get asynchronous
  180. // notification.
  181. //
  182. #ifndef DPNBUILD_ONLYWINSOCK2
  183. BOOL Winsock1ReadService( void );
  184. BOOL Winsock1ErrorService( void );
  185. #endif // ! DPNBUILD_ONLYWINSOCK2
  186. void ReadLockEndpointData( void ) { m_EndpointDataRWLock.EnterReadLock(); }
  187. void WriteLockEndpointData( void ) { m_EndpointDataRWLock.EnterWriteLock(); }
  188. void UnlockEndpointData( void ) { m_EndpointDataRWLock.LeaveLock(); }
  189. //
  190. // functions for active list
  191. //
  192. #undef DPF_MODNAME
  193. #define DPF_MODNAME "CSocketPort::AddToActiveList"
  194. void AddToActiveList( CBilink *const pBilink )
  195. {
  196. DNASSERT( pBilink != NULL );
  197. m_ActiveListLinkage.InsertBefore( pBilink );
  198. }
  199. void RemoveFromActiveList( void ) { m_ActiveListLinkage.RemoveFromList(); }
  200. #undef DPF_MODNAME
  201. #define DPF_MODNAME "CSocketPort::SocketPortFromBilink"
  202. static CSocketPort *SocketPortFromBilink( CBilink *const pBilink )
  203. {
  204. DNASSERT( pBilink != NULL );
  205. DBG_CASSERT( sizeof( BYTE* ) == sizeof( pBilink ) );
  206. DBG_CASSERT( sizeof( CSocketPort* ) == sizeof( BYTE* ) );
  207. return reinterpret_cast<CSocketPort*>( &reinterpret_cast<BYTE*>( pBilink )[ -OFFSETOF( CSocketPort, m_ActiveListLinkage ) ] );
  208. }
  209. #ifndef WINCE
  210. void SetWinsockBufferSize( const INT iBufferSize ) const;
  211. #endif // ! WINCE
  212. #ifndef DPNBUILD_NONATHELP
  213. #undef DPF_MODNAME
  214. #define DPF_MODNAME "CSocketPort::GetNATHelpPort"
  215. DPNHHANDLE GetNATHelpPort( const DWORD dwPortIndex )
  216. {
  217. DNASSERT( dwPortIndex < MAX_NUM_DIRECTPLAYNATHELPERS );
  218. return m_ahNATHelpPorts[dwPortIndex];
  219. }
  220. #endif // DPNBUILD_NONATHELP
  221. #undef DPF_MODNAME
  222. #define DPF_MODNAME "CSocketPort::GetListenEndpoint"
  223. CEndpoint * GetListenEndpoint( void )
  224. {
  225. return m_pListenEndpoint;
  226. }
  227. #ifndef DPNBUILD_NOMULTICAST
  228. #undef DPF_MODNAME
  229. #define DPF_MODNAME "CSocketPort::FindConnectEndpoint"
  230. BOOL FindConnectEndpoint( CSocketAddress * const pSocketAddress, CEndpoint ** ppEndpoint )
  231. {
  232. return m_ConnectEndpointHash.Find( (PVOID) pSocketAddress, (PVOID*) ppEndpoint );
  233. }
  234. #undef DPF_MODNAME
  235. #define DPF_MODNAME "CSocketPort::GetMulticastTTL"
  236. BYTE GetMulticastTTL( void ) const
  237. {
  238. return m_bMulticastTTL;
  239. }
  240. #endif // ! DPNBUILD_NOMULTICAST
  241. #ifndef DPNBUILD_ONLYONEPROCESSOR
  242. #undef DPF_MODNAME
  243. #define DPF_MODNAME "CSocketPort::GetCPU"
  244. DWORD GetCPU( void ) const
  245. {
  246. return m_dwCPU;
  247. }
  248. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  249. #ifndef DPNBUILD_NONATHELP
  250. #undef DPF_MODNAME
  251. #define DPF_MODNAME "CEndpoint::SetUserTraversalMode"
  252. void SetUserTraversalMode( DWORD dwMode )
  253. {
  254. DNASSERT((dwMode == DPNA_TRAVERSALMODE_NONE) || (dwMode == DPNA_TRAVERSALMODE_PORTREQUIRED) || (dwMode == DPNA_TRAVERSALMODE_PORTRECOMMENDED));
  255. m_dwUserTraversalMode = dwMode;
  256. }
  257. DWORD GetUserTraversalMode( void ) const { return m_dwUserTraversalMode; }
  258. #endif // ! DPNBUILD_NONATHELP
  259. //
  260. // Pool functions
  261. //
  262. static BOOL PoolAllocFunction( void* pvItem, void* pvContext );
  263. static void PoolInitFunction( void* pvItem, void* pvContext );
  264. #ifdef DBG
  265. static void PoolDeinitFunction( void* pvItem );
  266. #endif // DBG
  267. static void PoolDeallocFunction( void* pvItem );
  268. #ifdef DPNBUILD_ASYNCSPSENDS
  269. void SendData( BUFFERDESC *pBuffers, UINT_PTR uiBufferCount, const CSocketAddress *pDestinationSocketAddress, OVERLAPPED * pOverlapped );
  270. #else // ! DPNBUILD_ASYNCSPSENDS
  271. void SendData( BUFFERDESC *pBuffers, UINT_PTR uiBufferCount, const CSocketAddress *pDestinationSocketAddress );
  272. #endif // ! DPNBUILD_ASYNCSPSENDS
  273. protected:
  274. private:
  275. BYTE m_Sig[4]; // debugging signature ('SOKP')
  276. CSocketData *m_pSocketData; // pointer to owning socket data object
  277. CThreadPool *m_pThreadPool; // pointer to thread pool
  278. #ifndef DPNBUILD_ONLYONETHREAD
  279. DNCRITICAL_SECTION m_Lock; // thread lock
  280. #endif // !DPNBUILD_ONLYONETHREAD
  281. volatile LONG m_iRefCount; // count of all outstanding references (endpoint and I/O)
  282. volatile LONG m_iEndpointRefCount; // count of outstanding endpoint references
  283. volatile SOCKET_PORT_STATE m_State; // state of socket port
  284. volatile SOCKET m_Socket; // communications socket
  285. CSocketAddress *m_pNetworkSocketAddress; // network address this socket is bound to
  286. #if ((! defined(DPNBUILD_ONLYONETHREAD)) || (defined(DBG)))
  287. volatile LONG m_iThreadsInReceive; // Number of threads currently in the process of calling WSARecvFrom
  288. #endif // ! DPNBUILD_ONLYONETHREAD or DBG
  289. #ifndef DPNBUILD_ONLYONEADAPTER
  290. CAdapterEntry *m_pAdapterEntry; // pointer to adapter entry to use
  291. #endif // ! DPNBUILD_ONLYONEADAPTER
  292. #ifndef DPNBUILD_NONATHELP
  293. DPNHHANDLE m_ahNATHelpPorts[MAX_NUM_DIRECTPLAYNATHELPERS]; // array NAT Help registered port handles associated with this socket
  294. #endif // DPNBUILD_NONATHELP
  295. CBilink m_ActiveListLinkage; // linkage to list of active socket ports
  296. CReadWriteLock m_EndpointDataRWLock; // read/write lock for endpoint data
  297. CHashTable m_ConnectEndpointHash; // hash table of connect endpoints
  298. CBilink m_blConnectEndpointList; // list of connect endpoints
  299. CHashTable m_EnumEndpointHash; // hash table of enum endpoints
  300. CEndpoint *m_pListenEndpoint; // associated listen/multicast listen endpoint (there can only be one!)
  301. #ifndef DPNBUILD_NOMULTICAST
  302. BYTE m_bMulticastTTL; // the multicast TTL setting for this socket port, or 0 if not set yet
  303. #endif // ! DPNBUILD_NOMULTICAST
  304. volatile LONG m_iEnumKey; // current 'key' to be assigned to an enum
  305. DWORD m_dwSocketPortID; // unique identifier for this socketport
  306. #ifndef DPNBUILD_NOWINSOCK2
  307. BOOL m_fUsingProxyWinSockLSP; // whether the socket is bound to a proxy client WinSock layered service provider
  308. #endif // !DPNBUILD_NOWINSOCK2
  309. #ifndef DPNBUILD_ONLYONEPROCESSOR
  310. DWORD m_dwCPU; // CPU to which this socket is bound
  311. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  312. #ifndef DPNBUILD_NONATHELP
  313. DWORD m_dwUserTraversalMode; // the traversal mode specified by the user for this socketport
  314. #endif // ! DPNBUILD_NONATHELP
  315. #ifdef DBG
  316. BOOL m_fInitialized;
  317. #endif // DBG
  318. HRESULT BindToNextAvailablePort( const CSocketAddress *const pNetworkSocketAddress,
  319. const WORD wBasePort ) const;
  320. #ifndef DPNBUILD_NONATHELP
  321. #ifndef DPNBUILD_NOLOCALNAT
  322. HRESULT CheckForOverridingMapping( const CSocketAddress *const pBoundSocketAddress);
  323. #endif // ! DPNBUILD_NOLOCALNAT
  324. HRESULT BindToInternetGateway( const CSocketAddress *const pBoundSocketAddress,
  325. const GATEWAY_BIND_TYPE GatewayBindType );
  326. #endif // ! DPNBUILD_NONATHELP
  327. HRESULT StartReceiving( void );
  328. #ifndef DPNBUILD_ONLYWINSOCK2
  329. #endif // ! DPNBUILD_ONLYWINSOCK2
  330. #ifndef DPNBUILD_NOWINSOCK2
  331. #ifdef DPNBUILD_ONLYONEPROCESSOR
  332. HRESULT Winsock2Receive( void );
  333. #else // ! DPNBUILD_ONLYONEPROCESSOR
  334. HRESULT Winsock2Receive( const DWORD dwCPU );
  335. #endif // ! DPNBUILD_ONLYONEPROCESSOR
  336. #endif // ! DPNBUILD_NOWINSOCK2
  337. void ProcessReceivedData( CReadIOData *const pReadData );
  338. //
  339. // make copy constructor and assignment operator private and unimplemented
  340. // to prevent illegal copies from being made
  341. //
  342. CSocketPort( const CSocketPort & );
  343. CSocketPort& operator=( const CSocketPort & );
  344. };
  345. #undef DPF_MODNAME
  346. #endif // __SOCKET_PORT_H__