Source code of Windows XP (NT5)
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.

616 lines
15 KiB

  1. /**********************************************************************/
  2. /** Microsoft Windows NT **/
  3. /** Copyright(c) Microsoft Corp., 1994 **/
  4. /**********************************************************************/
  5. /*
  6. conn.hxx
  7. This module contains the connection class
  8. FILE HISTORY:
  9. Johnl 15-Aug-1994 Created
  10. */
  11. #ifndef _CONN_HXX_
  12. #define _CONN_HXX_
  13. # include "w3inst.hxx"
  14. # include "rdns.hxx"
  15. # include <reftrace.h>
  16. //
  17. // Determines if client connection reference count tracking is enabled
  18. //
  19. #if DBG && !defined(_WIN64)
  20. #define CC_REF_TRACKING 1
  21. #else
  22. #define CC_REF_TRACKING 0
  23. #endif
  24. //
  25. // The default timeout to wait for the completion of an Atq IO request (in sec)
  26. //
  27. #define W3_IO_TIMEOUT (5*60)
  28. //
  29. // The initial size of the buffer to receive the client request
  30. //
  31. #define W3_DEFAULT_BUFFSIZE 4096
  32. //
  33. // The end of a line is considered to be the linefeed character
  34. //
  35. #define W3_EOL 0x0A
  36. //
  37. // Valid signature of a CLIENT_CONN_STATE
  38. //
  39. #define CLIENT_CONN_SIGNATURE ((DWORD) ' SCC')
  40. //
  41. // Invalid signature of a CLIENT_CONN_STATE
  42. //
  43. #define CLIENT_CONN_SIGNATURE_FREE ((DWORD) 'xssc')
  44. //
  45. // The various states a CLIENT_CONN object can be in
  46. //
  47. enum CLIENT_CONN_STATE
  48. {
  49. //
  50. // We've just accepted the TCP connection from the client but we have
  51. // no other information.
  52. //
  53. CCS_STARTUP = 0,
  54. //
  55. // We are in the process of receiving the client's HTTP request buffer
  56. //
  57. CCS_GETTING_CLIENT_REQ,
  58. //
  59. // We are reading data from the client socket meant for a gateway
  60. //
  61. CCS_GATHERING_GATEWAY_DATA,
  62. //
  63. // We're executing the clients HTTP request
  64. //
  65. CCS_PROCESSING_CLIENT_REQ,
  66. //
  67. // The server or client has initiated a disconnect. We have to
  68. // wait till all outstanding IO requests are completed before
  69. // cleaning up
  70. //
  71. CCS_DISCONNECTING,
  72. //
  73. // All pending requests have been completed. Finish cleaning
  74. // up.
  75. //
  76. CCS_SHUTDOWN
  77. };
  78. //
  79. // parameter block used to initialize connections
  80. //
  81. typedef struct _CLIENT_CONN_PARAMS
  82. {
  83. SOCKET sClient;
  84. PSOCKADDR pAddrLocal;
  85. PSOCKADDR pAddrRemote;
  86. PATQ_CONTEXT pAtqContext;
  87. PVOID pEndpointObject;
  88. PIIS_ENDPOINT pEndpoint;
  89. PVOID pvInitialBuff;
  90. DWORD cbInitialBuff;
  91. } CLIENT_CONN_PARAMS, *PCLIENT_CONN_PARAMS;
  92. class CLIENT_CONN
  93. {
  94. public:
  95. BOOL IsValid( VOID )
  96. { return _fIsValid; }
  97. //
  98. // This is the work entry point that is driven by the completion of the
  99. // async IO.
  100. //
  101. BOOL DoWork( DWORD BytesWritten,
  102. DWORD CompletionStatus,
  103. BOOL fIOCompletion);
  104. #if CC_REF_TRACKING
  105. //
  106. // ATQ notification trace
  107. //
  108. // Notification of ATQ completion, for debugging purpose only.
  109. //
  110. VOID NotifyAtqProcessContext( DWORD BytesWritten,
  111. DWORD CompletionStatus,
  112. DWORD dwSig );
  113. #endif
  114. //
  115. // Optionally sends a status response then initiates the disconnect
  116. //
  117. // HTResponse - HTTP status code
  118. // ErrorResponse - System error or resource ID of response
  119. //
  120. // If this function fails, then the connection will be aborted
  121. //
  122. dllexp
  123. VOID Disconnect( HTTP_REQ_BASE * pRequest = NULL,
  124. DWORD HTResponse = 0,
  125. DWORD ErrorResponse = NO_ERROR,
  126. BOOL fDoShutdown = TRUE,
  127. LPBOOL pfFinished =NULL );
  128. dllexp
  129. BOOL OnSessionStartup( BOOL *pfDoAgain,
  130. PVOID pvInitial = NULL,
  131. DWORD cbInitial = 0,
  132. BOOL fFirst = FALSE);
  133. //
  134. // Walks the connection list and calls disconnect on each connection
  135. //
  136. static VOID DisconnectAllUsers( PIIS_SERVER_INSTANCE Instance = NULL );
  137. //
  138. // Increments and decrements the reference count
  139. //
  140. UINT Reference( VOID );
  141. UINT Dereference( VOID );
  142. UINT QueryRefCount( VOID ) const
  143. { return _cRef; }
  144. PIIS_ENDPOINT QueryW3Endpoint( VOID ) const
  145. { return m_pW3Endpoint; }
  146. PW3_SERVER_INSTANCE QueryW3Instance( VOID ) const
  147. { return m_pInstance; }
  148. BOOL IsW3Instance( VOID ) const
  149. { return m_pInstance != NULL; }
  150. VOID SetW3Instance( IN PW3_SERVER_INSTANCE pInstance )
  151. { DBG_ASSERT(m_pInstance == NULL); m_pInstance = pInstance; }
  152. W3_SERVER_STATISTICS * QueryW3StatsObj( VOID ) const
  153. { return m_pW3Stats; }
  154. VOID SetW3StatsObj( IN LPW3_SERVER_STATISTICS pW3Stats )
  155. { m_pW3Stats = pW3Stats; }
  156. DWORD QueryLocalIPAddress( VOID ) const
  157. { return m_localIpAddress; }
  158. DWORD QueryRemoteIPAddress( VOID ) const
  159. { return m_remoteIpAddress; }
  160. BOOL RequestAbortiveClose( VOID );
  161. BOOL CloseConnection( VOID );
  162. //
  163. // Simple wrappers to the corresponding Atq functions
  164. //
  165. BOOL ReadFile( LPVOID lpBuffer,
  166. DWORD nBytesToRead );
  167. BOOL WriteFile( LPVOID lpBuffer,
  168. DWORD nBytesToRead );
  169. BOOL SyncWsaSend( WSABUF * rgWsaBuffers,
  170. DWORD cWsaBuffers,
  171. LPDWORD pcbWritten );
  172. BOOL TransmitFile( HANDLE hFile,
  173. DWORD Offset,
  174. DWORD BytesToWrite,
  175. DWORD dwFlags,
  176. PVOID pHead = NULL,
  177. DWORD HeadLength = 0,
  178. PVOID pTail = NULL,
  179. DWORD TailLength = 0 );
  180. BOOL TransmitFileAndRecv( HANDLE hFile,
  181. DWORD Offset,
  182. DWORD BytesToWrite,
  183. DWORD dwFlags,
  184. PVOID pHead = NULL,
  185. DWORD HeadLength = 0,
  186. PVOID pTail = NULL,
  187. DWORD TailLength = 0,
  188. LPVOID lpBuffer = NULL,
  189. DWORD BytesToRead = 0);
  190. BOOL WriteFileAndRecv( LPVOID lpSendBuffer,
  191. DWORD BytesToWrite,
  192. LPVOID lpRecvBuffer = NULL,
  193. DWORD BytesToRead = 0);
  194. BOOL PostCompletionStatus( DWORD BytesTransferred );
  195. //
  196. // This list entry is put on the client connection list
  197. //
  198. LIST_ENTRY ListEntry;
  199. SOCKET QuerySocket( VOID ) const
  200. { return _sClient; }
  201. PATQ_CONTEXT QueryAtqContext( VOID ) const
  202. { return _AtqContext; }
  203. USHORT QueryPort( VOID ) const
  204. { return _sPort; }
  205. USHORT QueryRemotePort( VOID ) const
  206. { return _sRemotePort; }
  207. BOOL IsSecurePort( VOID ) const
  208. { return _fSecurePort; }
  209. //
  210. // Make sure the next state is set before an async IO call is made
  211. //
  212. enum CLIENT_CONN_STATE QueryState( VOID ) const
  213. { return _ccState; }
  214. VOID SetState( CLIENT_CONN_STATE ccState )
  215. { _ccState = ccState; }
  216. BOOL CheckSignature( VOID ) const
  217. { return _Signature == CLIENT_CONN_SIGNATURE; }
  218. TCHAR * QueryRemoteAddr( VOID ) const
  219. { return (TCHAR *) _achRemoteAddr; }
  220. TCHAR * QueryLocalAddr( VOID ) const
  221. { return (TCHAR *) _achLocalAddr; }
  222. VOID SetAtqReuseContextFlag( BOOL fReuseContext )
  223. { _fReuseContext = fReuseContext; }
  224. static DWORD QueryFreeListSize( VOID )
  225. { return _cFree; }
  226. static DWORD Initialize( VOID );
  227. static VOID Terminate( VOID );
  228. static CLIENT_CONN * Alloc( PCLIENT_CONN_PARAMS );
  229. dllexp static VOID Free( CLIENT_CONN * pConn );
  230. static VOID TrimFreeList( VOID );
  231. BOOL QueryDnsName(
  232. LPBOOL pfSync,
  233. ADDRCHECKFUNCEX pFunc,
  234. ADDRCHECKARG pArg,
  235. LPSTR * ppName
  236. )
  237. {
  238. return _acCheck.QueryDnsName( pfSync, pFunc, pArg, ppName );
  239. }
  240. AC_RESULT CheckIpAccess( LPBOOL pfNeedDns )
  241. { return _acCheck.CheckIpAccess( pfNeedDns ); }
  242. AC_RESULT CheckDnsAccess()
  243. { return _acCheck.CheckDnsAccess(); }
  244. BOOL BindAccessCheckList( LPBYTE p, DWORD dw )
  245. { return _acCheck.BindCheckList( p, dw ); }
  246. VOID UnbindAccessCheckList()
  247. { _acCheck.UnbindCheckList(); }
  248. LPSTR QueryResolvedDnsName()
  249. { return _acCheck.QueryResolvedDnsName(); }
  250. BOOL IsDnsResolved()
  251. { return _acCheck.IsDnsResolved(); }
  252. HTTP_REQ_BASE * QueryHttpReq( VOID) const
  253. { return (_phttpReq); }
  254. protected:
  255. //
  256. // Constructor and destructor
  257. //
  258. CLIENT_CONN( PCLIENT_CONN_PARAMS );
  259. VOID Initialize( PCLIENT_CONN_PARAMS );
  260. ~CLIENT_CONN( VOID );
  261. VOID Reset( VOID );
  262. BOOL IsCleaningUp( VOID ) const
  263. { return QueryState() == CCS_DISCONNECTING ||
  264. QueryState() == CCS_SHUTDOWN;
  265. }
  266. private:
  267. //
  268. // Contains the CLIENT_CONN signature
  269. //
  270. ULONG _Signature;
  271. //
  272. // Construction success indicator
  273. //
  274. BOOL _fIsValid;
  275. //
  276. // Contains the client socket connection openned by the connection thread
  277. //
  278. SOCKET _sClient;
  279. enum CLIENT_CONN_STATE _ccState;
  280. //
  281. // Reference count. Can't go away until the count reaches 0
  282. //
  283. LONG _cRef;
  284. //
  285. // Contains an ASCII representation of the client's remote address
  286. // and the adapter local address
  287. //
  288. CHAR _achRemoteAddr[20];
  289. CHAR _achLocalAddr[20];
  290. //
  291. // Port this connection is on
  292. //
  293. USHORT _sPort;
  294. //
  295. // Remote port
  296. //
  297. USHORT _sRemotePort;
  298. //
  299. // This request came in through the secure port
  300. //
  301. BOOL _fSecurePort;
  302. //
  303. // Parses the data and determines the appropriate action
  304. //
  305. HTTP_REQ_BASE * _phttpReq;
  306. //
  307. // server instance. Both are referenced.
  308. //
  309. PW3_SERVER_INSTANCE m_pInstance;
  310. PIIS_ENDPOINT m_pW3Endpoint;
  311. //
  312. // server instance - statistics object.
  313. //
  314. LPW3_SERVER_STATISTICS m_pW3Stats;
  315. //
  316. // local ip address
  317. //
  318. DWORD m_localIpAddress;
  319. //
  320. // remote sockaddr
  321. //
  322. DWORD m_remoteIpAddress;
  323. //
  324. // context returned on a non-acceptex completion
  325. //
  326. PVOID m_atqEndpointObject;
  327. //
  328. // Initial receive buffer if we're doing AcceptEx processing
  329. //
  330. PVOID _pvInitial;
  331. DWORD _cbInitial;
  332. PATQ_CONTEXT _AtqContext;
  333. //
  334. // If FALSE, the Atq Context should not be reused because the calling
  335. // thread will be exiting soon
  336. //
  337. BOOL _fReuseContext:1;
  338. BOOL _fAbortiveClose:1;
  339. //
  340. // Response string for disconnect notifications.
  341. //
  342. // NOTE: If the server handles non-serial requests, then two request completing at
  343. // the same time could use this string
  344. //
  345. STR _strResponse;
  346. //
  347. // These are for the lookaside buffer list
  348. //
  349. static CRITICAL_SECTION _csBuffList;
  350. static LIST_ENTRY _BuffListHead;
  351. static BOOL _fGlobalInit;
  352. static DWORD _cFree;
  353. static DWORD _FreeListScavengerCookie;
  354. LIST_ENTRY _BuffListEntry;
  355. //
  356. // Address check object for IP / DNS
  357. //
  358. ADDRESS_CHECK _acCheck;
  359. #if CC_REF_TRACKING
  360. public:
  361. //
  362. // For object local refcount tracing
  363. //
  364. PTRACE_LOG _pDbgCCRefTraceLog;
  365. private:
  366. #endif
  367. };
  368. //
  369. // Functions for connection reference counts
  370. //
  371. inline VOID ReferenceConn( CLIENT_CONN * pConn )
  372. {
  373. pConn->Reference();
  374. }
  375. inline VOID DereferenceConn( CLIENT_CONN * pConn )
  376. {
  377. if ( !pConn->Dereference() ) {
  378. CLIENT_CONN::Free( pConn );
  379. }
  380. }
  381. /*******************************************************************
  382. Support for CLIENT_CONN debug ref trace logging
  383. SYNOPSIS: Macro for writing to debug ref trace log.
  384. HISTORY:
  385. DaveK 10-Sep-1997 Created
  386. ********************************************************************/
  387. //
  388. // NOTE we avoid compile failure by hokey double typecast, below
  389. // (since htrState is an enum, we must first cast it to int).
  390. //
  391. #define SHARED_LOG_REF_COUNT( \
  392. cRefs \
  393. , pClientConn \
  394. , pHttpRequest \
  395. , pWamRequest \
  396. , htrState \
  397. ) \
  398. \
  399. if( g_pDbgCCRefTraceLog != NULL ) { \
  400. \
  401. ULONG_PTR i = (ULONG_PTR)htrState; \
  402. PVOID pv = (PVOID) i; \
  403. \
  404. WriteRefTraceLogEx( \
  405. g_pDbgCCRefTraceLog \
  406. , cRefs \
  407. , pClientConn \
  408. , pHttpRequest \
  409. , pWamRequest \
  410. , pv \
  411. ); \
  412. } \
  413. //
  414. // This macro logs the CLIENT_CONN specific ref trace log
  415. //
  416. #define LOCAL_LOG_REF_COUNT( \
  417. cRefs \
  418. , pClientConn \
  419. , pHttpRequest \
  420. , pWamRequest \
  421. , htrState \
  422. ) \
  423. \
  424. if( _pDbgCCRefTraceLog != NULL ) { \
  425. \
  426. ULONG_PTR i = (ULONG_PTR)htrState; \
  427. PVOID pv = (PVOID) i; \
  428. \
  429. WriteRefTraceLogEx( \
  430. _pDbgCCRefTraceLog \
  431. , cRefs \
  432. , pClientConn \
  433. , pHttpRequest \
  434. , pWamRequest \
  435. , pv \
  436. ); \
  437. } \
  438. #if CC_REF_TRACKING
  439. inline
  440. VOID
  441. LogRefCountCCLocal(
  442. IN LONG cRefs
  443. , IN PVOID pClientConn
  444. , IN PVOID pHttpRequest
  445. , IN PVOID pWamRequest
  446. , IN int htrState
  447. )
  448. {
  449. if( pClientConn && ((CLIENT_CONN *)pClientConn)->_pDbgCCRefTraceLog )
  450. {
  451. WriteRefTraceLogEx(
  452. ((CLIENT_CONN *) pClientConn)->_pDbgCCRefTraceLog
  453. , cRefs
  454. , pClientConn
  455. , pHttpRequest
  456. , pWamRequest
  457. , (PVOID) htrState
  458. );
  459. }
  460. }
  461. #endif
  462. #if DBG
  463. VOID DBG_CHECK_UnbalancedThreadToken(
  464. IN const char * pszFilePath,
  465. IN int nLineNum
  466. );
  467. #endif //DBG
  468. #endif // !_CONN_HXX_