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.

916 lines
16 KiB

  1. #ifndef _MAINCONTEXT_HXX_
  2. #define _MAINCONTEXT_HXX_
  3. class W3_CONNECTION;
  4. class RAW_CONNECTION;
  5. class W3_MAIN_CONTEXT;
  6. //
  7. // Different states
  8. //
  9. enum CONTEXT_STATE
  10. {
  11. CONTEXT_STATE_START,
  12. CONTEXT_STATE_URLINFO,
  13. CONTEXT_STATE_AUTHENTICATION,
  14. CONTEXT_STATE_AUTHORIZATION,
  15. CONTEXT_STATE_HANDLE_REQUEST,
  16. CONTEXT_STATE_RESPONSE,
  17. CONTEXT_STATE_LOG,
  18. CONTEXT_STATE_DONE,
  19. //
  20. // This should be the last value
  21. //
  22. STATE_COUNT
  23. };
  24. //
  25. // W3_CONNECTION_STATE - Abstract class representing state associated with
  26. // connection (W3_CONNECTION)
  27. //
  28. class W3_CONNECTION_STATE
  29. {
  30. public:
  31. virtual BOOL
  32. Cleanup(
  33. VOID
  34. ) = 0;
  35. };
  36. //
  37. // W3_CONTEXT_STATE - Abstract class representing context information for a
  38. // given state, stored for a given W3_MAIN_CONTEXT
  39. // At the end of the state machine, objects implementing
  40. // this class will be cleaned up (using Cleanup()).
  41. //
  42. class W3_MAIN_CONTEXT_STATE
  43. {
  44. public:
  45. virtual
  46. ~W3_MAIN_CONTEXT_STATE()
  47. {
  48. }
  49. virtual BOOL
  50. Cleanup(
  51. W3_MAIN_CONTEXT * pContext
  52. ) = 0;
  53. VOID *
  54. operator new(
  55. size_t uiSize,
  56. VOID * pPlacement
  57. );
  58. VOID
  59. operator delete(
  60. VOID * pContext
  61. );
  62. };
  63. //
  64. // W3_MAIN_CONTEXT
  65. //
  66. // This class represents the mainline (non-child) context representing the
  67. // the execution of a single HTTP request. This class contains and manages
  68. // the HTTP state machine
  69. //
  70. class W3_MAIN_CONTEXT : public W3_CONTEXT
  71. {
  72. private:
  73. //
  74. // Reference count used to manage fact that this context can be attached
  75. // to a RAW_CONNECTION
  76. //
  77. LONG _cRefs;
  78. //
  79. // Request information
  80. //
  81. W3_REQUEST _request;
  82. //
  83. // Response object (not necessarily used in sending a response)
  84. //
  85. W3_RESPONSE _response;
  86. //
  87. // The associated connection for this given request
  88. //
  89. W3_CONNECTION * _pConnection;
  90. BOOL _fAssociationChecked;
  91. //
  92. // The associated Site for this request
  93. //
  94. W3_SITE * _pSite;
  95. //
  96. // Metadata for request
  97. //
  98. URL_CONTEXT * _pUrlContext;
  99. //
  100. // User for the context. For now, the user cannot be reset for a child
  101. // context and is therefore stored only in the main context. That could
  102. // change later if we allow child requests to take on different
  103. // user identity
  104. //
  105. W3_USER_CONTEXT * _pUserContext;
  106. //
  107. // Did an authentication provider already handle sending
  108. // access denied headers?
  109. //
  110. BOOL _fProviderHandled;
  111. //
  112. // Certificate context representing client certificate if negotiated
  113. //
  114. CERTIFICATE_CONTEXT * _pCertificateContext;
  115. //
  116. // ULATQ context used to communicate with UL
  117. //
  118. ULATQ_CONTEXT _ulatqContext;
  119. //
  120. // Filter state
  121. //
  122. W3_FILTER_CONTEXT * _pFilterContext;
  123. //
  124. // State machine
  125. //
  126. DWORD _currentState;
  127. DWORD _nextState;
  128. //
  129. // State context objects
  130. //
  131. W3_MAIN_CONTEXT_STATE * _rgStateContexts[ STATE_COUNT ];
  132. //
  133. // Should we disconnect at the end of this request?
  134. //
  135. BOOL _fDisconnect;
  136. //
  137. // Are we done with compression for this request?
  138. //
  139. BOOL _fDoneWithCompression;
  140. //
  141. // The COMPRESSION_CONTEXT for the current request
  142. //
  143. COMPRESSION_CONTEXT *_pCompressionContext;
  144. //
  145. // Logging data to be passed on to UL
  146. //
  147. LOG_CONTEXT _LogContext;
  148. //
  149. // Buffer for allocating stuff with lifetime of the request
  150. //
  151. CHUNK_BUFFER _HeaderBuffer;
  152. //
  153. // Do we need to send a final done?
  154. //
  155. BOOL _fNeedFinalDone;
  156. //
  157. // The current context to receive IO completions
  158. //
  159. W3_CONTEXT * _pCurrentContext;
  160. //
  161. // Is this response cacheble in UL?
  162. //
  163. BOOL _fIsUlCacheable;
  164. //
  165. // Access check (put here only since a child request cannot/should not
  166. // change the remote address)
  167. //
  168. ADDRESS_CHECK _IpAddressCheck;
  169. //
  170. // Keep track of available entity body to be read thru UL.
  171. //
  172. DWORD _cbRemainingEntityFromUL;
  173. //
  174. // For HEAD requests, UL will not send a content-length so we'll have
  175. // to do for HEAD requests. The reason we keep this state
  176. // is because filters/child-requests can reset the verb -> a resetting
  177. // which still doesn't change the fact that UL will not be setting
  178. // Content-Length
  179. //
  180. BOOL _fGenerateContentLength;
  181. //
  182. // Raw connection. Needed since we need to tell the raw connection when
  183. // it should no longer reference us
  184. //
  185. RAW_CONNECTION * _pRawConnection;
  186. //
  187. // Handle for TIMER callback when a W3_MAIN_CONTEXT has existed for too long
  188. //
  189. HANDLE _hTimer;
  190. //
  191. // timeout in milliseconds before DebugBreak() is called
  192. // read from registry at static Initialization
  193. //
  194. static DWORD sm_dwTimeout;
  195. //
  196. // Callback function that does the DebugBreak for overtime W3_MAIN_CONTEXT
  197. //
  198. static VOID TimerCallback(PVOID pvParam, BOOLEAN fReason);
  199. //
  200. // Inline buffer to allocate context structures from
  201. //
  202. DWORD _cbInlineOffset;
  203. BYTE _rgBuffer[ 0 ];
  204. public:
  205. //
  206. // Lookaside for main contexts
  207. //
  208. static ALLOC_CACHE_HANDLER * sm_pachMainContexts;
  209. //
  210. // The states
  211. //
  212. static W3_STATE * sm_pStates[ STATE_COUNT ];
  213. static SHORT sm_rgInline[ STATE_COUNT ];
  214. static USHORT sm_cbInlineBytes;
  215. //
  216. // Outstanding thread count. How many threads are still doing
  217. // W3CORE.DLL stuff
  218. //
  219. static LONG sm_cOutstandingThreads;
  220. W3_MAIN_CONTEXT(
  221. HTTP_REQUEST * pUlHttpRequest,
  222. ULATQ_CONTEXT pUlAtqContext
  223. );
  224. ~W3_MAIN_CONTEXT();
  225. VOID *
  226. operator new(
  227. size_t size
  228. )
  229. {
  230. DBG_ASSERT( size == sizeof( W3_MAIN_CONTEXT ) );
  231. DBG_ASSERT( sm_pachMainContexts != NULL );
  232. return sm_pachMainContexts->Alloc();
  233. }
  234. VOID
  235. operator delete(
  236. VOID * pMainContext
  237. )
  238. {
  239. DBG_ASSERT( pMainContext != NULL );
  240. DBG_ASSERT( sm_pachMainContexts != NULL );
  241. DBG_REQUIRE( sm_pachMainContexts->Free( pMainContext ) );
  242. }
  243. //
  244. // Overridden W3_CONTEXT methods
  245. //
  246. ULATQ_CONTEXT
  247. QueryUlatqContext(
  248. VOID
  249. )
  250. {
  251. return _ulatqContext;
  252. }
  253. W3_REQUEST *
  254. QueryRequest(
  255. VOID
  256. )
  257. {
  258. return &_request;
  259. }
  260. W3_RESPONSE *
  261. QueryResponse(
  262. VOID
  263. )
  264. {
  265. return &_response;
  266. }
  267. BOOL
  268. QueryResponseSent(
  269. VOID
  270. )
  271. {
  272. return _response.QueryResponseSent();
  273. }
  274. CHUNK_BUFFER *
  275. QueryHeaderBuffer(
  276. VOID
  277. )
  278. {
  279. return &_HeaderBuffer;
  280. }
  281. BOOL
  282. QueryIsUlCacheable(
  283. VOID
  284. )
  285. {
  286. return _fIsUlCacheable;
  287. }
  288. VOID
  289. DisableUlCache(
  290. VOID
  291. )
  292. {
  293. _fIsUlCacheable = FALSE;
  294. }
  295. BOOL
  296. QueryProviderHandled(
  297. VOID
  298. )
  299. {
  300. return _fProviderHandled;
  301. }
  302. BOOL
  303. QueryNeedFinalDone(
  304. VOID
  305. )
  306. {
  307. return _fNeedFinalDone;
  308. }
  309. VOID
  310. SetNeedFinalDone(
  311. VOID
  312. )
  313. {
  314. _fNeedFinalDone = TRUE;
  315. }
  316. BOOL
  317. QueryShouldGenerateContentLength(
  318. VOID
  319. ) const
  320. {
  321. return _fGenerateContentLength;
  322. }
  323. W3_USER_CONTEXT *
  324. QueryUserContext(
  325. VOID
  326. )
  327. {
  328. return _pUserContext;
  329. }
  330. W3_USER_CONTEXT *
  331. QueryConnectionUserContext(
  332. VOID
  333. );
  334. VOID
  335. SetConnectionUserContext(
  336. W3_USER_CONTEXT * pUserContext
  337. );
  338. VOID
  339. SetUserContext(
  340. W3_USER_CONTEXT * pUserContext
  341. )
  342. {
  343. // perf ctr
  344. if (pUserContext->QueryAuthType() == MD_AUTH_ANONYMOUS)
  345. {
  346. _pSite->IncAnonUsers();
  347. }
  348. else
  349. {
  350. _pSite->IncNonAnonUsers();
  351. }
  352. _pUserContext = pUserContext;
  353. }
  354. CERTIFICATE_CONTEXT *
  355. QueryCertificateContext(
  356. VOID
  357. ) const
  358. {
  359. return _pCertificateContext;
  360. }
  361. VOID
  362. DetermineRemainingEntity(
  363. VOID
  364. );
  365. VOID
  366. SetCertificateContext(
  367. CERTIFICATE_CONTEXT * pCertificateContext
  368. )
  369. {
  370. _pCertificateContext = pCertificateContext;
  371. }
  372. W3_FILTER_CONTEXT *
  373. QueryFilterContext(
  374. BOOL fCreateIfNotFound = TRUE
  375. );
  376. URL_CONTEXT *
  377. QueryUrlContext(
  378. VOID
  379. )
  380. {
  381. return _pUrlContext;
  382. }
  383. W3_SITE *
  384. QuerySite(
  385. VOID
  386. )
  387. {
  388. return _pSite;
  389. }
  390. W3_CONTEXT *
  391. QueryCurrentContext(
  392. VOID
  393. )
  394. {
  395. return _pCurrentContext;
  396. }
  397. VOID
  398. PopCurrentContext(
  399. VOID
  400. )
  401. {
  402. _pCurrentContext = _pCurrentContext->QueryParentContext();
  403. if ( _pCurrentContext == NULL )
  404. {
  405. _pCurrentContext = this;
  406. }
  407. }
  408. VOID
  409. PushCurrentContext(
  410. W3_CONTEXT * pW3Context
  411. )
  412. {
  413. _pCurrentContext = pW3Context;
  414. }
  415. W3_CONTEXT *
  416. QueryParentContext(
  417. VOID
  418. )
  419. {
  420. return NULL;
  421. }
  422. W3_MAIN_CONTEXT *
  423. QueryMainContext(
  424. VOID
  425. )
  426. {
  427. return this;
  428. }
  429. BOOL
  430. QueryDisconnect(
  431. VOID
  432. )
  433. {
  434. return _fDisconnect;
  435. }
  436. VOID
  437. SetDisconnect(
  438. BOOL fDisconnect
  439. )
  440. {
  441. _fDisconnect = fDisconnect;
  442. }
  443. VOID
  444. SetDeniedFlags(
  445. DWORD dwDeniedFlags
  446. )
  447. {
  448. if( _pFilterContext )
  449. {
  450. _pFilterContext->SetDeniedFlags( dwDeniedFlags );
  451. }
  452. }
  453. BOOL
  454. NotifyFilters(
  455. DWORD dwNotification,
  456. VOID * pvFilterInfo,
  457. BOOL * pfFinished
  458. );
  459. BOOL
  460. IsNotificationNeeded(
  461. DWORD dwNotification
  462. );
  463. //
  464. // W3_MAIN_CONTEXT specific methods. These methods are not callable
  465. // when we are in the state of invoking a handler
  466. //
  467. VOID
  468. ReferenceMainContext(
  469. VOID
  470. )
  471. {
  472. InterlockedIncrement( &_cRefs );
  473. }
  474. VOID
  475. DereferenceMainContext(
  476. VOID
  477. )
  478. {
  479. if ( !InterlockedDecrement( &_cRefs ) )
  480. {
  481. delete this;
  482. }
  483. }
  484. VOID
  485. SetRawConnection(
  486. RAW_CONNECTION * pRawConnection
  487. );
  488. BOOL
  489. QueryExpiry(
  490. LARGE_INTEGER * pExpiry
  491. );
  492. HRESULT
  493. ExecuteExpiredUrl(
  494. STRU & strExpUrl
  495. );
  496. HRESULT
  497. PasswdExpireNotify(
  498. VOID
  499. );
  500. HRESULT
  501. PasswdChangeExecute(
  502. VOID
  503. );
  504. HRESULT
  505. ReceiveEntityBody(
  506. BOOL fAsync,
  507. VOID * pBuffer,
  508. DWORD cbBuffer,
  509. DWORD * pBytesReceived
  510. );
  511. DWORD
  512. QueryRemainingEntityFromUl(
  513. VOID
  514. ) const
  515. {
  516. return _cbRemainingEntityFromUL;
  517. }
  518. VOID
  519. SetRemainingEntityFromUl(
  520. DWORD cbRemaining
  521. )
  522. {
  523. _cbRemainingEntityFromUL = cbRemaining;
  524. }
  525. HRESULT
  526. GetRemoteDNSName(
  527. STRA * pstrDNSName
  528. );
  529. ADDRESS_CHECK *
  530. QueryAddressCheck(
  531. VOID
  532. )
  533. {
  534. return &_IpAddressCheck;
  535. }
  536. VOID
  537. SetProviderHandled(
  538. BOOL fProviderHandled
  539. )
  540. {
  541. _fProviderHandled = fProviderHandled;
  542. }
  543. HRESULT
  544. OnAccessDenied(
  545. VOID
  546. )
  547. {
  548. return NO_ERROR;
  549. }
  550. VOID
  551. SetUrlContext(
  552. URL_CONTEXT * pUrlContext
  553. )
  554. {
  555. _pUrlContext = pUrlContext;
  556. }
  557. VOID
  558. AssociateSite(
  559. W3_SITE * site
  560. )
  561. {
  562. _pSite = site;
  563. }
  564. VOID *
  565. ContextAlloc(
  566. UINT cbSize
  567. );
  568. BYTE *
  569. QueryInlineBuffer(
  570. VOID
  571. )
  572. {
  573. return _rgBuffer;
  574. }
  575. W3_CONNECTION *
  576. QueryConnection(
  577. BOOL fCreateIfNotFound = TRUE
  578. );
  579. //
  580. // Retrieve context for specified/current state
  581. //
  582. W3_MAIN_CONTEXT_STATE *
  583. QueryContextState(
  584. DWORD contextState = -1
  585. )
  586. {
  587. if ( contextState == -1 )
  588. {
  589. contextState = _currentState;
  590. }
  591. return _rgStateContexts[ contextState ];
  592. }
  593. //
  594. // Set context for current state
  595. //
  596. VOID
  597. SetContextState(
  598. W3_MAIN_CONTEXT_STATE * pStateContext
  599. )
  600. {
  601. _rgStateContexts[ _currentState ] = pStateContext;
  602. }
  603. W3_CONNECTION_STATE *
  604. QueryConnectionState(
  605. VOID
  606. );
  607. VOID
  608. SetConnectionState(
  609. W3_CONNECTION_STATE * pConnectionState
  610. );
  611. VOID SetDoneWithCompression()
  612. {
  613. _fDoneWithCompression = TRUE;
  614. }
  615. BOOL QueryDoneWithCompression()
  616. {
  617. return _fDoneWithCompression;
  618. }
  619. VOID SetCompressionContext(IN COMPRESSION_CONTEXT *pCompressionContext)
  620. {
  621. _pCompressionContext = pCompressionContext;
  622. }
  623. COMPRESSION_CONTEXT *QueryCompressionContext()
  624. {
  625. return _pCompressionContext;
  626. }
  627. HTTP_LOG_FIELDS_DATA *QueryUlLogData()
  628. {
  629. return _LogContext.QueryUlLogData();
  630. }
  631. LOG_CONTEXT *QueryLogContext()
  632. {
  633. return &_LogContext;
  634. }
  635. HRESULT CollectLoggingData(BOOL fCollectForULLogging);
  636. void SetLastIOPending(LAST_IO_PENDING ioPending)
  637. {
  638. _LogContext.m_ioPending = ioPending;
  639. }
  640. LAST_IO_PENDING QueryLastIOPending()
  641. {
  642. return _LogContext.m_ioPending;
  643. }
  644. VOID IncrementBytesRecvd(DWORD dwRecvd)
  645. {
  646. _LogContext.m_dwBytesRecvd += dwRecvd;
  647. }
  648. VOID IncrementBytesSent(DWORD dwSent)
  649. {
  650. _LogContext.m_dwBytesSent += dwSent;
  651. }
  652. VOID
  653. DoWork(
  654. DWORD cbCompletion,
  655. DWORD dwCompletionStatus,
  656. BOOL fIoCompletion
  657. );
  658. BOOL
  659. SetupContext(
  660. HTTP_REQUEST * pUlHttpRequest,
  661. ULATQ_CONTEXT pUlAtqContext
  662. );
  663. VOID
  664. CleanupContext(
  665. VOID
  666. );
  667. VOID
  668. SetFinishedResponse(
  669. VOID
  670. )
  671. {
  672. _nextState = CONTEXT_STATE_RESPONSE;
  673. }
  674. VOID
  675. SetDone(
  676. VOID
  677. )
  678. {
  679. _nextState = CONTEXT_STATE_LOG;
  680. }
  681. VOID
  682. BackupStateMachine(
  683. VOID
  684. );
  685. HRESULT
  686. SetupCertificateContext(
  687. HTTP_SSL_CLIENT_CERT_INFO* pClientCertInfo
  688. );
  689. static
  690. HRESULT
  691. SetupStateMachine(
  692. VOID
  693. );
  694. static
  695. VOID
  696. CleanupStateMachine(
  697. VOID
  698. );
  699. static
  700. HRESULT
  701. Initialize(
  702. VOID
  703. );
  704. static
  705. VOID
  706. Terminate(
  707. VOID
  708. );
  709. static
  710. VOID
  711. WaitForThreadDrain(
  712. VOID
  713. );
  714. static
  715. VOID
  716. AddressResolutionCallback(
  717. ADDRCHECKARG pContext,
  718. BOOL fUnused,
  719. LPSTR pszUnused
  720. );
  721. //
  722. // Completion routines called from ULATQ
  723. //
  724. static
  725. VOID
  726. OnIoCompletion(
  727. PVOID pvContext,
  728. DWORD cbWritten,
  729. DWORD dwCompletionStatus,
  730. OVERLAPPED * lpo
  731. );
  732. static
  733. VOID
  734. OnNewRequest(
  735. ULATQ_CONTEXT pContext
  736. );
  737. static
  738. VOID
  739. OnPostedCompletion(
  740. DWORD dwCompletionStatus,
  741. DWORD cbWritten,
  742. LPOVERLAPPED lpo
  743. );
  744. };
  745. #endif