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.

1282 lines
28 KiB

  1. #ifndef _ULCONTEXT_HXX_
  2. #define _ULCONTEXT_HXX_
  3. #define UL_CONTEXT_DESIRED_OUTSTANDING 20
  4. #define UL_CONTEXT_INIT_BUFFER 1024
  5. #define DEFAULT_RAW_READ_SIZE 32768
  6. #define DEFAULT_APP_READ_SIZE 32768
  7. #define DEFAULT_RENEGOTIATION_TIMEOUT_IN_SEC 300
  8. #define MINIMUM_RENEGOTIATION_TIMEOUT_IN_SEC 5
  9. //
  10. // number of critical sections to be used for
  11. // FILTER_CHANNEL_CONTEXT synchronization
  12. // Splitting this lock should improve the scaling
  13. //
  14. #define NUM_CS_FILT_CHANNEL_CONTEXTS 4
  15. #define SZ_REG_DEFAULT_RAW_READ_SIZE L"DefaultRawReadSize"
  16. #define SZ_REG_DEFAULT_APP_READ_SIZE L"DefaultAppReadSize"
  17. #define SZ_REG_CONTEXT_DESIRED_OUTSTANDING L"DesiredOutstandingContexts"
  18. #define SZ_REG_ENABLE_TEMPORARY_BUFFERS L"EnableTemporaryBuffers"
  19. //
  20. // SSL Renegotiation timeout
  21. //
  22. #define SZ_RENEGOTIATION_TIMEOUT L"RenegotiationTimeout"
  23. #define UL_CONTEXT_FLAG_ASYNC 0x00000001
  24. #define UL_CONTEXT_FLAG_SYNC 0x00000002
  25. #define UL_CONTEXT_FLAG_BUFFERED 0x00000004
  26. #define UL_CONTEXT_FLAG_COMPLETION_CALLBACK 0x00000008
  27. //
  28. // The time (in seconds) of how long the threads
  29. // can stay alive when there is no IO operation happening on
  30. // that thread.
  31. //
  32. #define STRMFILT_THREAD_POOL_DEF_THREAD_TIMEOUT 10 * 60
  33. //
  34. // The number of threads to start (to minimize footprint start with only 1 thread)
  35. //
  36. #define STRMFILT_THREAD_POOL_DEF_THREAD_COUNT 1
  37. enum UL_OVERLAPPED_CONTEXT_TYPE
  38. {
  39. UL_OVERLAPPED_CONTEXT_RAW_READ = 0,
  40. UL_OVERLAPPED_CONTEXT_RAW_WRITE,
  41. UL_OVERLAPPED_CONTEXT_APP_READ,
  42. UL_OVERLAPPED_CONTEXT_APP_WRITE,
  43. UL_OVERLAPPED_CONTEXT_CLOSE
  44. };
  45. //
  46. // context subtype ( currently used for only for RawWrite )
  47. //
  48. enum UL_OVERLAPPED_CONTEXT_SUBTYPE
  49. {
  50. UL_OVERLAPPED_CONTEXT_DEFAULT = 0,
  51. UL_OVERLAPPED_CONTEXT_DATA,
  52. //
  53. // some overlapped contexts can be created on fly
  54. // (eg. when synchronous sends are converted to asynchronous ones)
  55. // if subtype is OVERLAPPED_CONTEXT_TEMPORARY then OVERLAPPED_CONTEXT
  56. // will be deleted upon completion
  57. //
  58. UL_OVERLAPPED_CONTEXT_TEMPORARY,
  59. UL_OVERLAPPED_CONTEXT_COMPLETION_CALLBACK
  60. };
  61. class FILTER_CHANNEL_CONTEXT;
  62. class FILTER_CHANNEL;
  63. class STREAM_CONTEXT;
  64. class ENDPOINT_CONFIG;
  65. class UL_OVERLAPPED_CONTEXT
  66. {
  67. public:
  68. UL_OVERLAPPED_CONTEXT(
  69. UL_OVERLAPPED_CONTEXT_TYPE type,
  70. UL_OVERLAPPED_CONTEXT_SUBTYPE subtype = UL_OVERLAPPED_CONTEXT_DEFAULT
  71. );
  72. ~UL_OVERLAPPED_CONTEXT()
  73. {
  74. FreeDataBuffer();
  75. }
  76. VOID *
  77. operator new(
  78. size_t size
  79. )
  80. {
  81. UNREFERENCED_PARAMETER( size );
  82. DBG_ASSERT( size == sizeof( UL_OVERLAPPED_CONTEXT ) );
  83. DBG_ASSERT( sm_pachUlOverlappedContexts != NULL );
  84. return sm_pachUlOverlappedContexts->Alloc();
  85. }
  86. VOID
  87. operator delete(
  88. VOID * pUlOverlappedContext
  89. )
  90. {
  91. DBG_ASSERT( pUlOverlappedContext != NULL );
  92. DBG_ASSERT( sm_pachUlOverlappedContexts != NULL );
  93. DBG_REQUIRE( sm_pachUlOverlappedContexts->Free( pUlOverlappedContext ) );
  94. }
  95. static
  96. HRESULT
  97. Initialize(
  98. VOID
  99. );
  100. static
  101. VOID
  102. Terminate(
  103. VOID
  104. );
  105. static
  106. UL_OVERLAPPED_CONTEXT *
  107. GetUlOverlappedContext(
  108. LPOVERLAPPED lpOverlapped
  109. )
  110. {
  111. return CONTAINING_RECORD( lpOverlapped,
  112. UL_OVERLAPPED_CONTEXT,
  113. _Overlapped );
  114. }
  115. static
  116. UL_OVERLAPPED_CONTEXT *
  117. GetUlOverlappedContext(
  118. SINGLE_LIST_ENTRY * pListEntry
  119. )
  120. {
  121. return CONTAINING_RECORD( pListEntry,
  122. UL_OVERLAPPED_CONTEXT,
  123. _listEntry );
  124. }
  125. UL_OVERLAPPED_CONTEXT_TYPE
  126. QueryType(
  127. VOID
  128. ) const
  129. {
  130. return _type;
  131. }
  132. UL_OVERLAPPED_CONTEXT_SUBTYPE
  133. QuerySubtype(
  134. VOID
  135. ) const
  136. {
  137. return _subtype;
  138. }
  139. VOID
  140. SetContext(
  141. FILTER_CHANNEL_CONTEXT * pContext
  142. )
  143. {
  144. _pContext = pContext;
  145. }
  146. FILTER_CHANNEL_CONTEXT *
  147. QueryContext(
  148. VOID
  149. ) const
  150. {
  151. return _pContext;
  152. }
  153. SINGLE_LIST_ENTRY *
  154. QueryListEntry(
  155. VOID
  156. )
  157. {
  158. return &_listEntry;
  159. }
  160. OVERLAPPED *
  161. QueryOverlapped(
  162. VOID
  163. )
  164. {
  165. return &_Overlapped;
  166. }
  167. PBYTE
  168. QueryDataBuffer(
  169. VOID
  170. )
  171. {
  172. return _pbData;
  173. }
  174. DWORD
  175. QueryDataBufferSize(
  176. VOID
  177. )
  178. {
  179. return _cbData;
  180. }
  181. BOOL
  182. ResizeDataBuffer(
  183. DWORD cbNewSize
  184. );
  185. VOID
  186. FreeDataBuffer(
  187. VOID
  188. );
  189. typedef HRESULT (* PFN_CALLBACK)(PVOID pvParam );
  190. VOID
  191. SetCallBack (
  192. PFN_CALLBACK pCallback,
  193. PVOID pParam
  194. )
  195. {
  196. _pCallback = pCallback;
  197. _pCallbackParam = pParam;
  198. }
  199. HRESULT
  200. DoCallback(
  201. VOID
  202. )
  203. {
  204. if ( _pCallback != NULL )
  205. {
  206. return _pCallback( _pCallbackParam );
  207. }
  208. return S_OK;
  209. }
  210. private:
  211. OVERLAPPED _Overlapped;
  212. FILTER_CHANNEL_CONTEXT * _pContext;
  213. UL_OVERLAPPED_CONTEXT_TYPE _type;
  214. UL_OVERLAPPED_CONTEXT_SUBTYPE _subtype;
  215. PFN_CALLBACK _pCallback;
  216. PVOID _pCallbackParam;
  217. SINGLE_LIST_ENTRY _listEntry;
  218. //
  219. // some asynchronous operations may prefer to use
  220. // buffer from OVERLAPPED_CONTEXT. That way
  221. // OVERLAPPED_CONTEXT controls the lifetime of the buffer
  222. //
  223. PBYTE _pbData;
  224. DWORD _cbData;
  225. // current ACACHE to be used for _pbData
  226. // (depending on the UL_OVERLAPPED_CONTEXT_TYPE)
  227. ALLOC_CACHE_HANDLER * _pCurrentACache;
  228. DWORD _cbCurrentACacheElementSize;
  229. // flag if _pbData was allocated on the heap
  230. BOOL _fDynAllocated;
  231. // Lookasides
  232. static ALLOC_CACHE_HANDLER * sm_pachUlOverlappedContexts;
  233. static ALLOC_CACHE_HANDLER * sm_pachRawWriteBuffers;
  234. static ALLOC_CACHE_HANDLER * sm_pachRawReadBuffers;
  235. static ALLOC_CACHE_HANDLER * sm_pachAppReadBuffers;
  236. };
  237. VOID
  238. OverlappedCompletionRoutine(
  239. DWORD dwErrorCode,
  240. DWORD dwNumberOfBytesTransfered,
  241. LPOVERLAPPED lpOverlapped
  242. );
  243. class FILTER_CHANNEL
  244. {
  245. public:
  246. friend FILTER_CHANNEL_CONTEXT;
  247. FILTER_CHANNEL( LPWSTR pwszFilterChannelName );
  248. ~FILTER_CHANNEL();
  249. HRESULT
  250. Initialize(
  251. VOID
  252. );
  253. VOID
  254. Terminate(
  255. VOID
  256. );
  257. virtual
  258. HRESULT
  259. CreateContext(
  260. FILTER_CHANNEL_CONTEXT ** ppFiltChannelContext
  261. ) = NULL;
  262. HRESULT
  263. StartListening(
  264. VOID
  265. );
  266. VOID
  267. StopListening(
  268. VOID
  269. );
  270. HRESULT
  271. ManageOutstandingContexts(
  272. VOID
  273. );
  274. HRESULT
  275. DecrementAndManageOutstandingContexts(
  276. VOID
  277. );
  278. VOID
  279. IncrementOutstandingContexts(
  280. VOID
  281. )
  282. {
  283. InterlockedIncrement( &_cOutstandingContexts );
  284. };
  285. VOID AddWorkerThread(
  286. VOID
  287. )
  288. {
  289. DBG_ASSERT( _pThreadPool != NULL );
  290. _pThreadPool->SetInfo( ThreadPoolIncMaxPoolThreads, 0 );
  291. }
  292. VOID RemoveWorkerThread(
  293. VOID
  294. )
  295. {
  296. DBG_ASSERT( _pThreadPool != NULL );
  297. _pThreadPool->SetInfo( ThreadPoolDecMaxPoolThreads, 0 );
  298. }
  299. HRESULT
  300. EnableISAPIFilters(
  301. ISAPI_FILTERS_CALLBACKS * pConfig
  302. );
  303. VOID
  304. DisableISAPIFilters(
  305. VOID
  306. );
  307. static
  308. DWORD
  309. QueryDefaultRawReadSize(
  310. VOID
  311. )
  312. {
  313. return sm_dwDefaultRawReadSize;
  314. };
  315. static
  316. DWORD
  317. QueryDefaultAppReadSize(
  318. VOID
  319. )
  320. {
  321. return sm_dwDefaultAppReadSize;
  322. };
  323. static
  324. DWORD
  325. QueryDefaultRawWriteSize(
  326. VOID
  327. )
  328. {
  329. //
  330. // Default Raw Write is not configurable
  331. // in the registry (unlike the other 2)
  332. //
  333. // This value is to be used for the outgoing stream
  334. // Filter received data from App Read
  335. // (the max size matchas the sm_dwDefaultAppReadSize)
  336. // filter does some changes on that data and sends it out
  337. // We will make assumption that RawWrite will not
  338. // be typically more than up to 3% more than App Read
  339. // (the overhead would account for e.g. SSL encryption
  340. // header and trailer)
  341. //
  342. return sm_dwDefaultAppReadSize +
  343. ( sm_dwDefaultAppReadSize > 100 ) ?
  344. ( ( sm_dwDefaultAppReadSize / 100 ) * 3 ) /*add 3 %*/ :
  345. 20 /*under the size of 100 (which is very unlikely
  346. to be configured choose to add pragmatic value of 20*/;
  347. };
  348. VOID
  349. WriteRefTraceLog(
  350. DWORD cRefs,
  351. FILTER_CHANNEL_CONTEXT * pFiltChannelContext,
  352. IN PVOID Context1 = NULL, // optional extra context
  353. IN PVOID Context2 = NULL, // optional extra context
  354. IN PVOID Context3 = NULL // optional extra context
  355. )
  356. {
  357. if ( _pTraceLog != NULL )
  358. {
  359. ::WriteRefTraceLogEx( _pTraceLog,
  360. cRefs,
  361. pFiltChannelContext,
  362. Context1,
  363. Context2,
  364. Context3);
  365. }
  366. }
  367. protected:
  368. BOOL
  369. QueryNotifyISAPIFilters(
  370. VOID
  371. )
  372. {
  373. return _lNotifyISAPIFilters;
  374. }
  375. private:
  376. VOID
  377. InsertFiltChannelContext(
  378. FILTER_CHANNEL_CONTEXT *
  379. );
  380. VOID
  381. RemoveFiltChannelContext(
  382. FILTER_CHANNEL_CONTEXT *
  383. );
  384. VOID
  385. InsertFiltChannelContextToTimerList(
  386. FILTER_CHANNEL_CONTEXT *
  387. );
  388. VOID
  389. RemoveFiltChannelContextFromTimerList(
  390. FILTER_CHANNEL_CONTEXT *
  391. );
  392. VOID
  393. WaitForContextDrain(
  394. VOID
  395. );
  396. HANDLE
  397. QueryFilterHandle(
  398. VOID
  399. )
  400. {
  401. return _hFilterHandle;
  402. }
  403. BOOL
  404. SetNotifyISAPIFilters(
  405. BOOL fNotify
  406. )
  407. {
  408. return InterlockedExchange( &_lNotifyISAPIFilters, (LONG) fNotify );
  409. }
  410. static
  411. VOID
  412. WINAPI
  413. TimerCallback(
  414. PVOID pParam,
  415. BOOLEAN TimerOrWaitFired
  416. );
  417. // head of the list of FILTER_CHANNEL_CONTEXTs representing
  418. // individual connections (multiple sublists are maintained
  419. // to improve scalability)
  420. LIST_ENTRY _ListHead[ NUM_CS_FILT_CHANNEL_CONTEXTS ];
  421. // head of the list of FILTER_CHANNEL_CONTEXTs that posted
  422. // async operation that needs to be timed in the lack of completion
  423. // (multiple sublists are maintained to improve scalability)
  424. LIST_ENTRY _TimerListHead[ NUM_CS_FILT_CHANNEL_CONTEXTS ];
  425. // CS to synchronize List operations
  426. CRITICAL_SECTION _csFiltChannelContexts[NUM_CS_FILT_CHANNEL_CONTEXTS];
  427. // counter of how many critical sections were initialized
  428. DWORD _dwInitcsFiltChannelContexts;
  429. // Global counter for the Filter channel contexts handled
  430. // by the FILTER_CHANNEL. It is limited by DWORD scope. It's only purpose
  431. // is to control the selection of the index for
  432. // the critical sections/sublists (_csFiltChannelContexts, _TimerListHead,
  433. // _TimerListHead
  434. // so wrapping around is not a problem
  435. DWORD _dwTotalFilterChannelContexts;
  436. // Timer handle
  437. HANDLE _hTimer;
  438. // number of FILTER_CHANNEL_CONTEXTs on the list
  439. DWORD _cFiltChannelContexts;
  440. // handle to HTTP.sys Filter channel
  441. HANDLE _hFilterHandle;
  442. // flag that FILTER_CHANNEL started listening
  443. LONG _lStartedListening;
  444. // private threadpool
  445. THREAD_POOL * _pThreadPool;
  446. // FILTER_CHANNEL_CONTEXTs with pending FilterAccept() call
  447. LONG _cOutstandingContexts;
  448. // flag that new outstanding contexts are being added
  449. LONG _lEnteredOutstandingContextsAddingLoop;
  450. // how many outstanding FILTER_CHANNEL_CONTEXTs should be maintained
  451. LONG _cDesiredOutstanding;
  452. // trace log used only in DBG build
  453. PTRACE_LOG _pTraceLog;
  454. // name of the FILTER Channel
  455. LPWSTR _pwszFilterChannelName;
  456. // flag that Raw ISAPI Filters are installed and for each connection
  457. // they have to be notified as appropriate
  458. // (used only for the SSL_SERVER_FILTER_CHANNEL)
  459. LONG _lNotifyISAPIFilters;
  460. // defaults read from Registry
  461. static
  462. DWORD sm_dwDefaultRawReadSize;
  463. static
  464. DWORD sm_dwDefaultAppReadSize;
  465. static
  466. DWORD sm_dwContextDesiredOutstanding;
  467. static
  468. BOOL sm_fEnableTemporaryBuffers;
  469. static
  470. DWORD sm_dwHandshakeTimeoutInSec;
  471. };
  472. class FILTER_CHANNEL_CONTEXT
  473. {
  474. public:
  475. friend FILTER_CHANNEL;
  476. FILTER_CHANNEL_CONTEXT(
  477. FILTER_CHANNEL *
  478. );
  479. virtual ~FILTER_CHANNEL_CONTEXT();
  480. virtual
  481. BOOL
  482. CheckSignature(
  483. VOID
  484. ) const = NULL;
  485. OVERLAPPED *
  486. QueryRawReadOverlapped(
  487. VOID
  488. )
  489. {
  490. return _RawReadOverlapped.QueryOverlapped();
  491. }
  492. OVERLAPPED *
  493. QueryAppWriteOverlapped(
  494. VOID
  495. )
  496. {
  497. return _AppWriteOverlapped.QueryOverlapped();
  498. }
  499. OVERLAPPED *
  500. QueryAppReadOverlapped(
  501. VOID
  502. )
  503. {
  504. return _AppReadOverlapped.QueryOverlapped();
  505. }
  506. OVERLAPPED *
  507. QueryCloseOverlapped(
  508. VOID
  509. )
  510. {
  511. return _CloseOverlapped.QueryOverlapped();
  512. }
  513. HTTP_RAW_CONNECTION_INFO *
  514. QueryConnectionInfo(
  515. VOID
  516. ) const
  517. {
  518. return _pConnectionInfo;
  519. }
  520. DWORD
  521. QueryLockIndex(
  522. VOID
  523. ) const
  524. {
  525. return _dwLockIndex;
  526. }
  527. VOID
  528. SetLockIndex(
  529. DWORD dwIndex
  530. )
  531. {
  532. _dwLockIndex = dwIndex;
  533. }
  534. VOID
  535. ReferenceFiltChannelContext(
  536. VOID
  537. );
  538. VOID
  539. DereferenceFiltChannelContext(
  540. VOID
  541. );
  542. VOID
  543. SetIsSecure(
  544. BOOL fIsSecure
  545. )
  546. {
  547. _connectionContext.fIsSecure = fIsSecure;
  548. }
  549. HRESULT
  550. OnNewConnection(
  551. VOID
  552. );
  553. HRESULT
  554. OnRawReadCompletion(
  555. DWORD cbCompletion,
  556. DWORD dwCompletionStatus
  557. );
  558. HRESULT
  559. OnRawWriteCompletion(
  560. DWORD cbCompletion,
  561. DWORD dwCompletionStatus,
  562. UL_OVERLAPPED_CONTEXT * pContextOverlapped
  563. );
  564. HRESULT
  565. OnAppWriteCompletion(
  566. DWORD cbCompletion,
  567. DWORD dwCompletionStatus
  568. );
  569. HRESULT
  570. OnAppReadCompletion(
  571. DWORD cbCompletion,
  572. DWORD dwCompletionStatus
  573. );
  574. HRESULT
  575. TryAppRead(
  576. VOID
  577. );
  578. HRESULT
  579. DoRawRead(
  580. DWORD dwFlags,
  581. PVOID pvBuffer,
  582. DWORD cbBuffer,
  583. DWORD * pcbRead
  584. );
  585. HRESULT
  586. DoRawWrite(
  587. DWORD dwFlags,
  588. PVOID pvBuffer,
  589. DWORD cbBuffer,
  590. DWORD * pcbWritten,
  591. UL_OVERLAPPED_CONTEXT::PFN_CALLBACK pfnCallback = NULL,
  592. PVOID pCallbackParam = NULL
  593. );
  594. HRESULT
  595. AcquireRawWriteBuffer(
  596. PBYTE * ppbBuffer,
  597. DWORD cbBufferRequired
  598. )
  599. /*++
  600. Routine Description:
  601. acquire one of the 2 RawWrite context buffers to be used
  602. for next send (we need 2 buffers to support 2 outstanding RawWrites)
  603. Note: Only the last filter (currently only SSL should be using it)
  604. before the DoRawWrite should use this call
  605. Otherwise other filters could change the output buffer pointer and
  606. RawWriteBuffer would never be released
  607. Arguments:
  608. ppbBuffer - pointer to the buffer to be returned
  609. cbBufferRequired - number of bytes needed for the buffer
  610. Return Value:
  611. HRESULT
  612. --*/
  613. {
  614. if ( ppbBuffer == NULL )
  615. {
  616. return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
  617. }
  618. SINGLE_LIST_ENTRY * pListEntry;
  619. UL_OVERLAPPED_CONTEXT * pOverlappedContext;
  620. _RawWriteOverlappedListLock.WriteLock();
  621. pListEntry = PopEntryList( &_RawWriteOverlappedFreeList );
  622. _RawWriteOverlappedListLock.WriteUnlock();
  623. if ( pListEntry != NULL )
  624. {
  625. pOverlappedContext = UL_OVERLAPPED_CONTEXT::GetUlOverlappedContext( pListEntry );
  626. _pLastAcquiredRawWriteOverlapped = pOverlappedContext;
  627. if ( ! pOverlappedContext->ResizeDataBuffer( cbBufferRequired ) )
  628. {
  629. return HRESULT_FROM_WIN32( GetLastError() );
  630. }
  631. *ppbBuffer = (PBYTE) pOverlappedContext->QueryDataBuffer();
  632. return S_OK;
  633. }
  634. else
  635. {
  636. pOverlappedContext = NULL;
  637. //
  638. // CODEWORK: this is error case - we don't assume more
  639. // then 2 outstanding RawWrite buffers
  640. //
  641. DBG_ASSERT( FALSE );
  642. return E_FAIL;
  643. }
  644. }
  645. VOID
  646. ReleaseRawWriteBuffer(
  647. UL_OVERLAPPED_CONTEXT * pUlOverlapped
  648. )
  649. /*++
  650. Routine Description:
  651. release buffer to be available next use.
  652. (actually the whole OVERLAPPED_CONTEXT gets available for next use)
  653. Arguments:
  654. pUlOverlapped
  655. Return Value:
  656. VOID
  657. --*/
  658. {
  659. if ( pUlOverlapped != NULL )
  660. {
  661. if ( FILTER_CHANNEL::sm_fEnableTemporaryBuffers )
  662. {
  663. pUlOverlapped->FreeDataBuffer();
  664. }
  665. _RawWriteOverlappedListLock.WriteLock();
  666. PushEntryList( &_RawWriteOverlappedFreeList, pUlOverlapped->QueryListEntry() );
  667. _RawWriteOverlappedListLock.WriteUnlock();
  668. }
  669. //
  670. // Assert if buffer not coming from the FILTER_CHANNEL_POOL
  671. // was attempted to be released
  672. //
  673. DBG_ASSERT( pUlOverlapped != NULL );
  674. }
  675. UL_OVERLAPPED_CONTEXT *
  676. QueryLastAcquiredRawWriteBufferOverlapped(
  677. VOID
  678. )
  679. /*++
  680. Routine Description:
  681. return UL_OVERLAPPED_CONTEXT that owns the buffer that was returned
  682. on the last AcquireRawWriteBuffer call
  683. Arguments:
  684. Return Value:
  685. UL_OVERLAPPED_CONTEXT *
  686. --*/
  687. {
  688. return _pLastAcquiredRawWriteOverlapped;
  689. }
  690. VOID
  691. TryReleaseLastAcquiredRawWriteBuffer(
  692. VOID
  693. )
  694. /*++
  695. Routine Description:
  696. release buffer to be available next use.
  697. BUGBUG: better comment
  698. Arguments:
  699. pvBuffer - buffer to be released
  700. Return Value:
  701. VOID
  702. --*/
  703. {
  704. //
  705. // release the buffer as needed
  706. //
  707. if ( _pLastAcquiredRawWriteOverlapped != NULL )
  708. {
  709. ReleaseRawWriteBuffer( _pLastAcquiredRawWriteOverlapped );
  710. }
  711. _pLastAcquiredRawWriteOverlapped = NULL;
  712. }
  713. HRESULT
  714. DoAppRead(
  715. DWORD dwFlags,
  716. HTTP_FILTER_BUFFER * pFilterBuffer,
  717. DWORD * pcbRead
  718. );
  719. HRESULT
  720. DoAppWrite(
  721. DWORD dwFlags,
  722. HTTP_FILTER_BUFFER * pFilterBuffer,
  723. DWORD * pcbWritten
  724. );
  725. HRESULT
  726. DoAppWriteAndRawRead(
  727. DWORD dwFlags,
  728. PHTTP_FILTER_BUFFER_PLUS pHttpBufferPlus
  729. );
  730. DWORD
  731. QueryNextRawReadSize(
  732. VOID
  733. ) const
  734. {
  735. return _cbNextRawReadSize;
  736. }
  737. VOID
  738. SetNextRawReadSize(
  739. DWORD dwRawReadSize
  740. )
  741. {
  742. DBG_ASSERT( dwRawReadSize != 0 );
  743. _cbNextRawReadSize = dwRawReadSize;
  744. }
  745. HTTP_FILTER_BUFFER_TYPE
  746. QueryFilterBufferType(
  747. VOID
  748. ) const
  749. {
  750. DBG_ASSERT( _ulFilterBufferType != (HTTP_FILTER_BUFFER_TYPE)-1 );
  751. return _ulFilterBufferType;
  752. }
  753. HRESULT
  754. SendDataBack(
  755. RAW_STREAM_INFO * pRawStreamInfo
  756. );
  757. VOID
  758. StartClose(
  759. VOID
  760. );
  761. virtual
  762. HRESULT
  763. Create(
  764. VOID
  765. ) = NULL;
  766. HRESULT
  767. DoAccept(
  768. VOID
  769. );
  770. VOID AddWorkerThread(
  771. VOID
  772. )
  773. {
  774. DBG_ASSERT( _pManager != NULL );
  775. _pManager->AddWorkerThread();
  776. }
  777. VOID RemoveWorkerThread(
  778. VOID
  779. )
  780. {
  781. DBG_ASSERT( _pManager != NULL );
  782. _pManager->RemoveWorkerThread();
  783. }
  784. VOID StartTimeoutTimer(
  785. VOID
  786. )
  787. {
  788. _pManager->InsertFiltChannelContextToTimerList( this );
  789. }
  790. VOID StopTimeoutTimer(
  791. VOID
  792. )
  793. {
  794. if ( QueryIsAlreadyOnTimerList() )
  795. {
  796. _pManager->RemoveFiltChannelContextFromTimerList( this );
  797. }
  798. }
  799. VOID CloseNotify(
  800. VOID
  801. );
  802. protected:
  803. DWORD _dwSignature;
  804. //
  805. // SSL stream context
  806. //
  807. STREAM_CONTEXT * _pSSLContext;
  808. //
  809. // ISAPI raw data filter context
  810. //
  811. STREAM_CONTEXT * _pISAPIContext;
  812. VOID
  813. SetTimerTickCount(
  814. DWORD TimerTickCount
  815. )
  816. {
  817. _dwTimerTickCount = TimerTickCount;
  818. _fTimerTickCountSet = TRUE;
  819. }
  820. DWORD
  821. QueryTimerTickCount(
  822. VOID
  823. ) const
  824. {
  825. return _dwTimerTickCount;
  826. }
  827. VOID
  828. ResetTimerTickCount(
  829. VOID
  830. )
  831. {
  832. _fTimerTickCountSet = FALSE;
  833. }
  834. BOOL
  835. QueryIsAlreadyOnTimerList(
  836. VOID
  837. )
  838. {
  839. return _fTimerTickCountSet;
  840. }
  841. private:
  842. //
  843. // Reference count
  844. //
  845. LONG _cRefs;
  846. //
  847. // Keep a list of UL_CONTEXTs
  848. //
  849. LIST_ENTRY _ListEntry;
  850. LIST_ENTRY _TimerListEntry;
  851. //
  852. // overlapped structures
  853. //
  854. UL_OVERLAPPED_CONTEXT _RawReadOverlapped;
  855. UL_OVERLAPPED_CONTEXT _RawWriteData1Overlapped;
  856. UL_OVERLAPPED_CONTEXT _RawWriteData2Overlapped;
  857. UL_OVERLAPPED_CONTEXT _AppReadOverlapped;
  858. UL_OVERLAPPED_CONTEXT _AppWriteOverlapped;
  859. UL_OVERLAPPED_CONTEXT _CloseOverlapped;
  860. //
  861. // The initial ULFilterAccept structure
  862. //
  863. HTTP_RAW_CONNECTION_INFO* _pConnectionInfo;
  864. BUFFER _buffConnectionInfo;
  865. BYTE _abConnectionInfo[ UL_CONTEXT_INIT_BUFFER ];
  866. CONNECTION_INFO _connectionContext;
  867. //
  868. // Size of read raw (stream) data
  869. // the actual buffer is member of _RawReadOverlapped structure
  870. //
  871. DWORD _cbRawReadData;
  872. //
  873. // Indicate how many oustanding AppReads we have
  874. // strmfilt supports 2 outstanding RawWrites
  875. // (completion of RawWrite causes subsequent AppRead)
  876. // but AppReads must be serialized to prevent losing the order
  877. // of app read data blocks
  878. //
  879. LONG _lQueuedAppReads;
  880. //
  881. // Indicate that there is currently one app read in progress
  882. //
  883. BOOL _fAppReadInProgress;
  884. //
  885. // Maintain a list of (2) buffers -
  886. // _RawWriteData1Overlapped and _RawWriteData2Overlapped
  887. //
  888. SINGLE_LIST_ENTRY _RawWriteOverlappedFreeList;
  889. CSmallSpinLock _RawWriteOverlappedListLock;
  890. UL_OVERLAPPED_CONTEXT * _pLastAcquiredRawWriteOverlapped;
  891. //
  892. //
  893. CSmallSpinLock _AppReadQueueLock;
  894. HTTP_FILTER_BUFFER _ulAppReadFilterBuffer;
  895. HTTP_FILTER_BUFFER _ulAppWriteFilterBuffer;
  896. HTTP_FILTER_BUFFER_PLUS _ulAppWriteAndRawReadFilterBuffer;
  897. //
  898. // Close flag. One thread takes the responsibility of doing the close
  899. // dereference of this object (leading to its destruction once down
  900. // stream user (STREAM_CONTEXT) has cleaned up
  901. //
  902. BOOL _fCloseConnection;
  903. //
  904. // If this a new connection?
  905. //
  906. BOOL _fNewConnection;
  907. //
  908. // Next read size
  909. //
  910. DWORD _cbNextRawReadSize;
  911. //
  912. // Filter buffer type read from application
  913. //
  914. HTTP_FILTER_BUFFER_TYPE _ulFilterBufferType;
  915. //
  916. // Pointer to the manager
  917. //
  918. FILTER_CHANNEL * _pManager;
  919. ENDPOINT_CONFIG * _pEndpointConfig;
  920. //
  921. // TickCount indicating when entry was added
  922. // to the timer list
  923. //
  924. DWORD _dwTimerTickCount;
  925. //
  926. // Flag that TickCount was set
  927. //
  928. BOOL _fTimerTickCountSet;
  929. //
  930. // Filter channel Context lock is split
  931. // for better scalability
  932. // _dwLockIndex is the index of lock, sublists to
  933. // be used for this context
  934. //
  935. DWORD _dwLockIndex;
  936. };
  937. class SSL_SERVER_FILTER_CHANNEL;
  938. #define SSL_SERVER_FILTER_CHANNEL_CONTEXT_SIGNATURE (DWORD)'XCLU'
  939. #define SSL_SERVER_FILTER_CHANNEL_CONTEXT_SIGNATURE_FREE (DWORD)'xclu'
  940. class SSL_SERVER_FILTER_CHANNEL_CONTEXT : public FILTER_CHANNEL_CONTEXT
  941. {
  942. public:
  943. SSL_SERVER_FILTER_CHANNEL_CONTEXT(
  944. SSL_SERVER_FILTER_CHANNEL *
  945. );
  946. virtual ~SSL_SERVER_FILTER_CHANNEL_CONTEXT();
  947. VOID *
  948. operator new(
  949. size_t size
  950. )
  951. {
  952. UNREFERENCED_PARAMETER( size );
  953. DBG_ASSERT( size == sizeof( SSL_SERVER_FILTER_CHANNEL_CONTEXT ) );
  954. DBG_ASSERT( sm_pachFilterChannelContexts != NULL );
  955. return sm_pachFilterChannelContexts->Alloc();
  956. }
  957. VOID
  958. operator delete(
  959. VOID * pFilterChannelContext
  960. )
  961. {
  962. DBG_ASSERT( pFilterChannelContext != NULL );
  963. DBG_ASSERT( sm_pachFilterChannelContexts != NULL );
  964. DBG_REQUIRE( sm_pachFilterChannelContexts->Free( pFilterChannelContext ) );
  965. }
  966. static
  967. HRESULT
  968. Initialize(
  969. VOID
  970. );
  971. static
  972. VOID
  973. Terminate(
  974. VOID
  975. );
  976. virtual
  977. BOOL
  978. CheckSignature(
  979. VOID
  980. ) const
  981. {
  982. return _dwSignature == SSL_SERVER_FILTER_CHANNEL_CONTEXT_SIGNATURE;
  983. }
  984. virtual
  985. HRESULT
  986. Create(
  987. VOID
  988. );
  989. private:
  990. // Lookaside
  991. static ALLOC_CACHE_HANDLER * sm_pachFilterChannelContexts;
  992. };
  993. class SSL_SERVER_FILTER_CHANNEL : public FILTER_CHANNEL
  994. {
  995. public:
  996. SSL_SERVER_FILTER_CHANNEL(): FILTER_CHANNEL( HTTP_SSL_SERVER_FILTER_CHANNEL_NAME ) {};
  997. virtual ~SSL_SERVER_FILTER_CHANNEL() {};
  998. private:
  999. virtual
  1000. HRESULT
  1001. CreateContext(
  1002. FILTER_CHANNEL_CONTEXT ** ppFiltChannelContext
  1003. )
  1004. {
  1005. DBG_ASSERT( ppFiltChannelContext != NULL );
  1006. HRESULT hr = E_FAIL;
  1007. SSL_SERVER_FILTER_CHANNEL_CONTEXT * pSslFiltContext =
  1008. new SSL_SERVER_FILTER_CHANNEL_CONTEXT( this );
  1009. if ( pSslFiltContext != NULL )
  1010. {
  1011. hr = pSslFiltContext->Create();
  1012. if ( FAILED( hr ) )
  1013. {
  1014. delete pSslFiltContext;
  1015. pSslFiltContext = NULL;
  1016. }
  1017. }
  1018. else
  1019. {
  1020. hr = HRESULT_FROM_WIN32( ERROR_OUTOFMEMORY );
  1021. }
  1022. *ppFiltChannelContext = pSslFiltContext;
  1023. return hr;
  1024. }
  1025. };
  1026. #endif