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.

447 lines
9.2 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. DWORD
  208. QueryCurrentRequests(
  209. VOID
  210. )
  211. {
  212. return sm_cRequests - sm_cRequestsPending;
  213. }
  214. static
  215. VOID
  216. FreeWorkerRequest(
  217. UL_NATIVE_REQUEST * pWorkerRequest
  218. );
  219. static
  220. UL_NATIVE_REQUEST *
  221. AllocateWorkerRequest(
  222. VOID
  223. );
  224. static
  225. VOID
  226. PushFreeList(
  227. UL_NATIVE_REQUEST * pWorkerRequest
  228. )
  229. {
  230. #ifdef _WIN64
  231. sm_FreeListLock.WriteLock();
  232. PushEntryList( &sm_FreeList, &pWorkerRequest->_FreeListEntry );
  233. sm_FreeListLock.WriteUnlock();
  234. #else
  235. RtlInterlockedPushEntrySList( &sm_FreeList, &pWorkerRequest->_FreeListEntry );
  236. #endif
  237. }
  238. static
  239. UL_NATIVE_REQUEST *
  240. PopFreeList(
  241. VOID
  242. )
  243. {
  244. SINGLE_LIST_ENTRY * pListEntry;
  245. UL_NATIVE_REQUEST * pRequest = NULL;
  246. #ifdef _WIN64
  247. sm_FreeListLock.WriteLock();
  248. pListEntry = PopEntryList( &sm_FreeList );
  249. sm_FreeListLock.WriteUnlock();
  250. #else
  251. pListEntry = RtlInterlockedPopEntrySList( &sm_FreeList );
  252. #endif
  253. if ( pListEntry != NULL )
  254. {
  255. pRequest = CONTAINING_RECORD( pListEntry,
  256. UL_NATIVE_REQUEST,
  257. _FreeListEntry );
  258. }
  259. return pRequest;
  260. }
  261. private:
  262. HTTP_CONNECTION_ID
  263. QueryConnectionId(
  264. VOID
  265. ) const
  266. {
  267. return QueryHttpRequest()->ConnectionId;
  268. }
  269. HTTP_REQUEST_ID
  270. QueryRequestId(
  271. VOID
  272. ) const
  273. {
  274. return QueryHttpRequest()->RequestId;
  275. }
  276. //
  277. // private helper for destructor and Reset()
  278. //
  279. VOID
  280. Cleanup(
  281. VOID
  282. );
  283. //
  284. // Reset the worker process to its pristine state
  285. //
  286. VOID
  287. Reset(
  288. VOID
  289. );
  290. //
  291. // State implementors
  292. //
  293. NREQ_STATUS
  294. DoStateStart(
  295. VOID
  296. );
  297. NREQ_STATUS
  298. DoStateRead(
  299. VOID
  300. );
  301. NREQ_STATUS
  302. DoStateProcess(
  303. VOID
  304. );
  305. NREQ_STATUS
  306. DoStateClientCertificate(
  307. VOID
  308. );
  309. //
  310. // Determine if we need to send a "restart count reached" message to
  311. // the admin process. Note that we want to send this once, thus the
  312. // use of InterlockedExchange() on the static member. Note also that
  313. // we first test the flag with non-interlocked access to avoid bus
  314. // thrash.
  315. //
  316. static
  317. BOOL
  318. NeedToSendRestartMsg(
  319. VOID
  320. )
  321. {
  322. if( sm_RestartMsgSent == 1 )
  323. {
  324. return FALSE;
  325. }
  326. return InterlockedExchange( &sm_RestartMsgSent, 1 ) == 0;
  327. }
  328. DWORD _dwSignature;
  329. LONG _cRefs;
  330. SINGLE_LIST_ENTRY _FreeListEntry;
  331. NREQ_STATE _ExecState;
  332. LIST_ENTRY _ListEntry;
  333. PVOID _pvContext;
  334. DWORD _cbAsyncIOData; // Data transferred in the last Async IO
  335. DWORD _dwAsyncIOError; // Error code from the last Async IO
  336. UCHAR _achBuffer[ INLINE_REQUEST_BUFFER_LEN ];
  337. UCHAR * _pbBuffer;
  338. DWORD _cbBuffer;
  339. BUFFER _buffClientCertInfo;
  340. DWORD _dwClientCertFlags;
  341. HTTP_SSL_CLIENT_CERT_INFO * _pClientCertInfo;
  342. BYTE _abAllocateMemory[ INLINE_ALLOCATION_BUFFER_LEN ];
  343. DWORD _cbAllocateMemoryOffset;
  344. //
  345. // static members
  346. //
  347. static ULONG sm_cRequestsServed;
  348. static ULONG sm_cRestart;
  349. static LONG sm_RestartMsgSent;
  350. static LIST_ENTRY sm_RequestListHead;
  351. static CRITICAL_SECTION sm_csRequestList;
  352. static DWORD sm_cRequests;
  353. static PTRACE_LOG sm_pTraceLog;
  354. #ifdef _WIN64
  355. static SINGLE_LIST_ENTRY sm_FreeList;
  356. static CSpinLock sm_FreeListLock;
  357. #else
  358. static SLIST_HEADER sm_FreeList;
  359. #endif
  360. static DWORD sm_cFreeRequests;
  361. static DWORD sm_cMaxFreeRequests;
  362. static DWORD sm_cRequestsPending;
  363. static DWORD sm_cDesiredPendingRequests;
  364. static BOOL sm_fAddingRequests;
  365. static ALLOC_CACHE_HANDLER * sm_pachNativeRequests;
  366. };
  367. #endif