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.

469 lines
9.5 KiB

  1. #ifndef _WORKERREQUEST_HXX_
  2. #define _WORKERREQUEST_HXX_
  3. #include "asynccontext.hxx"
  4. #include <reftrace.h>
  5. #include <acache.hxx>
  6. //
  7. // We are either reading a new request, or are processing the request
  8. //
  9. enum NREQ_STATE
  10. {
  11. NREQ_STATE_START = 0,
  12. NREQ_STATE_READ,
  13. NREQ_STATE_PROCESS,
  14. NREQ_STATE_ERROR,
  15. NREQ_STATE_CLIENT_CERT
  16. };
  17. enum NREQ_STATUS
  18. {
  19. NSTATUS_NEXT = 0,
  20. NSTATUS_PENDING
  21. };
  22. #define INLINE_REQUEST_BUFFER_LEN (sizeof(HTTP_REQUEST)+2048)
  23. #ifdef _WIN64
  24. #define INLINE_ALLOCATION_BUFFER_LEN (8192)
  25. #else
  26. #define INLINE_ALLOCATION_BUFFER_LEN (5120)
  27. #endif
  28. #define UL_NATIVE_REQUEST_CS_SPINS (200)
  29. #define DESIRED_PENDING_REQUESTS (20)
  30. #define DEFAULT_MAX_FREE_REQUESTS (250)
  31. //
  32. // When we're getting a client cert, the initialize buffer size we'll use
  33. //
  34. #define INITIAL_CERT_INFO_SIZE (1500)
  35. //
  36. // UL_NATIVE_REQUEST. Each object represents the context of handling a
  37. // single HTTP_REQUEST
  38. //
  39. #define UL_NATIVE_REQUEST_SIGNATURE CREATE_SIGNATURE( 'NREQ')
  40. #define UL_NATIVE_REQUEST_SIGNATURE_FREE CREATE_SIGNATURE( 'nreq')
  41. class UL_NATIVE_REQUEST : public ASYNC_CONTEXT
  42. {
  43. public:
  44. UL_NATIVE_REQUEST(
  45. VOID
  46. );
  47. ~UL_NATIVE_REQUEST(
  48. VOID
  49. );
  50. VOID *
  51. operator new(
  52. size_t size
  53. )
  54. {
  55. if ( size != sizeof( UL_NATIVE_REQUEST ) )
  56. {
  57. DBG_ASSERT( size == sizeof( UL_NATIVE_REQUEST ) );
  58. return NULL;
  59. }
  60. DBG_ASSERT( sm_pachNativeRequests != NULL );
  61. return sm_pachNativeRequests->Alloc();
  62. }
  63. VOID
  64. operator delete(
  65. VOID * pNativeRequest
  66. )
  67. {
  68. DBG_ASSERT( pNativeRequest != NULL );
  69. DBG_ASSERT( sm_pachNativeRequests != NULL );
  70. DBG_REQUIRE( sm_pachNativeRequests->Free( pNativeRequest ) );
  71. }
  72. //
  73. // The state machine advancer
  74. //
  75. VOID
  76. DoWork(
  77. DWORD cbData,
  78. DWORD dwError,
  79. LPOVERLAPPED lpo
  80. );
  81. //
  82. // Global list of worker requests
  83. //
  84. VOID
  85. RemoveFromRequestList(
  86. VOID
  87. );
  88. VOID
  89. AddToRequestList(
  90. VOID
  91. );
  92. //
  93. // Reference counting
  94. //
  95. VOID
  96. ReferenceWorkerRequest(
  97. VOID
  98. );
  99. VOID
  100. DereferenceWorkerRequest(
  101. VOID
  102. );
  103. //
  104. // Configure # of requests to serve
  105. //
  106. static
  107. VOID
  108. SetRestartCount(
  109. ULONG cRequests
  110. )
  111. {
  112. sm_cRestart = cRequests;
  113. }
  114. HTTP_REQUEST *
  115. QueryHttpRequest(
  116. VOID
  117. ) const
  118. {
  119. return (HTTP_REQUEST *) _pbBuffer;
  120. }
  121. VOID
  122. ResetContext(
  123. VOID
  124. );
  125. VOID
  126. SetContext(
  127. PVOID pvContext
  128. )
  129. {
  130. _pvContext = pvContext;
  131. }
  132. HRESULT
  133. SendResponse(
  134. BOOL fAsync,
  135. DWORD dwFlags,
  136. HTTP_RESPONSE *pResponse,
  137. HTTP_CACHE_POLICY *pCachePolicy,
  138. DWORD *pcbSent,
  139. HTTP_LOG_FIELDS_DATA *pUlLogData
  140. );
  141. HRESULT
  142. SendEntity(
  143. BOOL fAsync,
  144. DWORD dwFlags,
  145. USHORT cChunks,
  146. HTTP_DATA_CHUNK * pChunks,
  147. DWORD *pcbSent,
  148. HTTP_LOG_FIELDS_DATA *pUlLogData
  149. );
  150. HRESULT
  151. ReceiveEntity(
  152. BOOL fAsync,
  153. DWORD dwFlags,
  154. VOID * pBuffer,
  155. DWORD cbBuffer,
  156. DWORD * pBytesReceived
  157. );
  158. HRESULT
  159. ReceiveClientCertificate(
  160. BOOL fAsync,
  161. BOOL fDoCertMap,
  162. HTTP_SSL_CLIENT_CERT_INFO **ppClientCertInfo
  163. );
  164. BOOL
  165. CheckSignature(
  166. VOID
  167. ) const
  168. {
  169. return _dwSignature == UL_NATIVE_REQUEST_SIGNATURE;
  170. }
  171. //
  172. // Allocate some per-request memory
  173. //
  174. VOID *
  175. AllocateMemory(
  176. DWORD cbSize
  177. );
  178. //
  179. // Global UL_NATIVE_REQUEST methods
  180. //
  181. static
  182. HRESULT
  183. Initialize(
  184. VOID
  185. );
  186. static
  187. VOID
  188. StopListening(
  189. VOID
  190. );
  191. static
  192. VOID
  193. Terminate(
  194. VOID
  195. );
  196. static
  197. HRESULT
  198. AddPendingRequests(
  199. DWORD cItems
  200. );
  201. static
  202. HRESULT
  203. ReleaseAllWorkerRequests(
  204. VOID
  205. );
  206. static
  207. HRESULT
  208. StartPendingRequestsMonitor(
  209. VOID
  210. );
  211. static
  212. VOID
  213. StopPendingRequestsMonitor(
  214. VOID
  215. );
  216. static
  217. VOID
  218. WINAPI
  219. PendingRequestsMonitorHandler(
  220. PVOID,
  221. BOOLEAN
  222. );
  223. static
  224. DWORD
  225. QueryCurrentRequests(
  226. VOID
  227. )
  228. {
  229. return sm_cRequests - sm_cRequestsPending;
  230. }
  231. static
  232. VOID
  233. FreeWorkerRequest(
  234. UL_NATIVE_REQUEST * pWorkerRequest
  235. );
  236. static
  237. UL_NATIVE_REQUEST *
  238. AllocateWorkerRequest(
  239. VOID
  240. );
  241. static
  242. VOID
  243. PushFreeList(
  244. UL_NATIVE_REQUEST * pWorkerRequest
  245. )
  246. {
  247. #ifdef _WIN64
  248. sm_FreeListLock.WriteLock();
  249. PushEntryList( &sm_FreeList, &pWorkerRequest->_FreeListEntry );
  250. sm_FreeListLock.WriteUnlock();
  251. #else
  252. RtlInterlockedPushEntrySList( &sm_FreeList, &pWorkerRequest->_FreeListEntry );
  253. #endif
  254. }
  255. static
  256. UL_NATIVE_REQUEST *
  257. PopFreeList(
  258. VOID
  259. )
  260. {
  261. SINGLE_LIST_ENTRY * pListEntry;
  262. UL_NATIVE_REQUEST * pRequest = NULL;
  263. #ifdef _WIN64
  264. sm_FreeListLock.WriteLock();
  265. pListEntry = PopEntryList( &sm_FreeList );
  266. sm_FreeListLock.WriteUnlock();
  267. #else
  268. pListEntry = RtlInterlockedPopEntrySList( &sm_FreeList );
  269. #endif
  270. if ( pListEntry != NULL )
  271. {
  272. pRequest = CONTAINING_RECORD( pListEntry,
  273. UL_NATIVE_REQUEST,
  274. _FreeListEntry );
  275. }
  276. return pRequest;
  277. }
  278. private:
  279. HTTP_CONNECTION_ID
  280. QueryConnectionId(
  281. VOID
  282. ) const
  283. {
  284. return QueryHttpRequest()->ConnectionId;
  285. }
  286. HTTP_REQUEST_ID
  287. QueryRequestId(
  288. VOID
  289. ) const
  290. {
  291. return QueryHttpRequest()->RequestId;
  292. }
  293. //
  294. // private helper for destructor and Reset()
  295. //
  296. VOID
  297. Cleanup(
  298. VOID
  299. );
  300. //
  301. // Reset the worker process to its pristine state
  302. //
  303. VOID
  304. Reset(
  305. VOID
  306. );
  307. //
  308. // State implementors
  309. //
  310. NREQ_STATUS
  311. DoStateStart(
  312. VOID
  313. );
  314. NREQ_STATUS
  315. DoStateRead(
  316. VOID
  317. );
  318. NREQ_STATUS
  319. DoStateProcess(
  320. VOID
  321. );
  322. NREQ_STATUS
  323. DoStateClientCertificate(
  324. VOID
  325. );
  326. //
  327. // Determine if we need to send a "restart count reached" message to
  328. // the admin process. Note that we want to send this once, thus the
  329. // use of InterlockedExchange() on the static member. Note also that
  330. // we first test the flag with non-interlocked access to avoid bus
  331. // thrash.
  332. //
  333. static
  334. BOOL
  335. NeedToSendRestartMsg(
  336. VOID
  337. )
  338. {
  339. if( sm_RestartMsgSent == 1 )
  340. {
  341. return FALSE;
  342. }
  343. return InterlockedExchange( &sm_RestartMsgSent, 1 ) == 0;
  344. }
  345. DWORD _dwSignature;
  346. LONG _cRefs;
  347. SINGLE_LIST_ENTRY _FreeListEntry;
  348. NREQ_STATE _ExecState;
  349. LIST_ENTRY _ListEntry;
  350. PVOID _pvContext;
  351. DWORD _cbAsyncIOData; // Data transferred in the last Async IO
  352. DWORD _dwAsyncIOError; // Error code from the last Async IO
  353. UCHAR _achBuffer[ INLINE_REQUEST_BUFFER_LEN ];
  354. UCHAR * _pbBuffer;
  355. DWORD _cbBuffer;
  356. BUFFER _buffClientCertInfo;
  357. DWORD _dwClientCertFlags;
  358. HTTP_SSL_CLIENT_CERT_INFO * _pClientCertInfo;
  359. BYTE _abAllocateMemory[ INLINE_ALLOCATION_BUFFER_LEN ];
  360. DWORD _cbAllocateMemoryOffset;
  361. //
  362. // static members
  363. //
  364. static ULONG sm_cRequestsServed;
  365. static ULONG sm_cRestart;
  366. static LONG sm_RestartMsgSent;
  367. static LIST_ENTRY sm_RequestListHead;
  368. static CRITICAL_SECTION sm_csRequestList;
  369. static DWORD sm_cRequests;
  370. static PTRACE_LOG sm_pTraceLog;
  371. #ifdef _WIN64
  372. static SINGLE_LIST_ENTRY sm_FreeList;
  373. static CSpinLock sm_FreeListLock;
  374. #else
  375. static SLIST_HEADER sm_FreeList;
  376. #endif
  377. static DWORD sm_cFreeRequests;
  378. static DWORD sm_cMaxFreeRequests;
  379. static DWORD sm_cRequestsPending;
  380. static DWORD sm_cDesiredPendingRequests;
  381. static BOOL sm_fAddingRequests;
  382. static ALLOC_CACHE_HANDLER * sm_pachNativeRequests;
  383. // timer for the pending requests monitor
  384. static HANDLE sm_hPendingRequestsTimer;
  385. };
  386. #endif