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.

525 lines
16 KiB

  1. /*++
  2. Copyright (c) 1998-2002 Microsoft Corporation
  3. Module Name:
  4. httpconn.h
  5. Abstract:
  6. This module contains declarations for manipulation HTTP_CONNECTION
  7. objects.
  8. Author:
  9. Keith Moore (keithmo) 08-Jul-1998
  10. Revision History:
  11. --*/
  12. /*
  13. there is a bit of refcount madness going on. basically, these are the
  14. object we have.
  15. OPAQUE_ID_TABLE
  16. |
  17. |--> UL_INTERNAL_REQUEST
  18. |
  19. | o
  20. | |
  21. |--> UL_HTTP_CONNECTION
  22. |
  23. o
  24. o
  25. |
  26. UL_CONNECTION
  27. there is a circular reference from UL_CONNECTION to UL_HTTP_CONNECTION.
  28. the chain that brings down a connection starts with UlConnectionDestroyed
  29. notifcation which releases the reference from the UL_CONNECTION.
  30. at this time the opaque id's are also deleted, releasing their references.
  31. when the http_connection refcount hits 0, it releases the reference on the
  32. UL_CONNECTION and the HTTP_REQUEST's.
  33. poof. everyone is gone now.
  34. CODEWORK: think about making hardref's everywhere and adding "letgo"
  35. terminate methods
  36. */
  37. #ifndef _HTTPCONN_H_
  38. #define _HTTPCONN_H_
  39. //
  40. // Zombie connection timer period in seconds. A zombie connection
  41. // may live; 30 < T < 60 seconds.
  42. //
  43. #define DEFAULT_ZOMBIE_HTTP_CONNECTION_TIMER_PERIOD_IN_SECONDS (30)
  44. typedef struct _UL_ZOMBIE_HTTP_CONNECTION_LIST
  45. {
  46. LOCKED_LIST_HEAD LockList;
  47. //
  48. // Private timer stuff.
  49. //
  50. KTIMER Timer;
  51. KDPC DpcObject;
  52. UL_SPIN_LOCK TimerSpinLock;
  53. BOOLEAN TimerInitialized;
  54. UL_WORK_ITEM WorkItem;
  55. LONG TimerRunning;
  56. #ifdef ENABLE_HTTP_CONN_STATS
  57. //
  58. // Http connection statistics.
  59. //
  60. ULONG MaxZombieCount;
  61. ULONG TotalCount;
  62. ULONG TotalZombieCount;
  63. ULONG TotalZombieRefusal;
  64. #endif
  65. } UL_ZOMBIE_HTTP_CONNECTION_LIST, *PUL_ZOMBIE_HTTP_CONNECTION_LIST;
  66. //
  67. // Refcounted structure to hold the number of conn for each Site.
  68. // Multiple connections may try to reach to the same entry thru the
  69. // the corresponding ( means the last request's happening on the connection )
  70. // cgroup. This entry get allocated when cgroup created with connection
  71. // limit is enabled.
  72. //
  73. typedef struct _UL_CONNECTION_COUNT_ENTRY {
  74. //
  75. // Signature is UL_CONNECTION_COUNT_ENTRY_POOL_TAG
  76. //
  77. ULONG Signature;
  78. //
  79. // Ref count for this Site Counter Entry
  80. //
  81. LONG RefCount;
  82. //
  83. // Current number of connections
  84. //
  85. ULONG CurConnections;
  86. //
  87. // Maximum allowed connections
  88. //
  89. ULONG MaxConnections;
  90. } UL_CONNECTION_COUNT_ENTRY, *PUL_CONNECTION_COUNT_ENTRY;
  91. #define IS_VALID_CONNECTION_COUNT_ENTRY( entry ) \
  92. HAS_VALID_SIGNATURE(entry, UL_CONNECTION_COUNT_ENTRY_POOL_TAG)
  93. VOID
  94. UlDereferenceConnectionCountEntry(
  95. IN PUL_CONNECTION_COUNT_ENTRY pEntry
  96. REFERENCE_DEBUG_FORMAL_PARAMS
  97. );
  98. #define DEREFERENCE_CONNECTION_COUNT_ENTRY( pEntry ) \
  99. UlDereferenceConnectionCountEntry( \
  100. (pEntry) \
  101. REFERENCE_DEBUG_ACTUAL_PARAMS \
  102. )
  103. VOID
  104. UlReferenceConnectionCountEntry(
  105. IN PUL_CONNECTION_COUNT_ENTRY pEntry
  106. REFERENCE_DEBUG_FORMAL_PARAMS
  107. );
  108. #define REFERENCE_CONNECTION_COUNT_ENTRY( pEntry ) \
  109. UlReferenceConnectionCountEntry( \
  110. (pEntry) \
  111. REFERENCE_DEBUG_ACTUAL_PARAMS \
  112. )
  113. NTSTATUS
  114. UlCreateConnectionCountEntry(
  115. IN OUT PUL_CONFIG_GROUP_OBJECT pConfigGroup,
  116. IN ULONG MaxConnections
  117. );
  118. ULONG
  119. UlSetMaxConnections(
  120. IN OUT PULONG pCurMaxConnection,
  121. IN ULONG NewMaxConnection
  122. );
  123. ULONG
  124. UlGetGlobalConnectionLimit(
  125. VOID
  126. );
  127. NTSTATUS
  128. UlInitGlobalConnectionLimits(
  129. VOID
  130. );
  131. BOOLEAN
  132. UlAcceptConnection(
  133. IN PULONG pMaxConnection,
  134. IN OUT PULONG pCurConnection
  135. );
  136. LONG
  137. UlDecrementConnections(
  138. IN OUT PULONG pCurConnection
  139. );
  140. BOOLEAN
  141. UlCheckSiteConnectionLimit(
  142. IN OUT PUL_HTTP_CONNECTION pConnection,
  143. IN OUT PUL_URL_CONFIG_GROUP_INFO pConfigInfo
  144. );
  145. BOOLEAN
  146. UlAcceptGlobalConnection(
  147. VOID
  148. );
  149. //
  150. // function prototypes
  151. //
  152. NTSTATUS
  153. UlCreateHttpConnection(
  154. OUT PUL_HTTP_CONNECTION *ppHttpConnection,
  155. IN PUL_CONNECTION pConnection
  156. );
  157. NTSTATUS
  158. UlCreateHttpConnectionId(
  159. IN PUL_HTTP_CONNECTION pHttpConnection
  160. );
  161. VOID
  162. UlConnectionDestroyedWorker(
  163. IN PUL_WORK_ITEM pWorkItem
  164. );
  165. NTSTATUS
  166. UlBindConnectionToProcess(
  167. IN PUL_HTTP_CONNECTION pHttpConnection,
  168. IN PUL_APP_POOL_OBJECT pAppPool,
  169. IN PUL_APP_POOL_PROCESS pProcess
  170. );
  171. PUL_APP_POOL_PROCESS
  172. UlQueryProcessBinding(
  173. IN PUL_HTTP_CONNECTION pHttpConnection,
  174. IN PUL_APP_POOL_OBJECT pAppPool
  175. );
  176. VOID
  177. UlUnlinkHttpRequest(
  178. IN PUL_INTERNAL_REQUEST pRequest
  179. );
  180. VOID
  181. UlCleanupHttpConnection(
  182. IN PUL_HTTP_CONNECTION pHttpConnection
  183. );
  184. VOID
  185. UlDeleteHttpConnection(
  186. IN PUL_WORK_ITEM pWorkItem
  187. );
  188. VOID
  189. UlReferenceHttpConnection(
  190. IN PVOID pObject
  191. REFERENCE_DEBUG_FORMAL_PARAMS
  192. );
  193. VOID
  194. UlDereferenceHttpConnection(
  195. IN PUL_HTTP_CONNECTION pHttpConnection
  196. REFERENCE_DEBUG_FORMAL_PARAMS
  197. );
  198. #if REFERENCE_DEBUG
  199. #define UL_REFERENCE_HTTP_CONNECTION( pconn ) \
  200. UlReferenceHttpConnection( \
  201. (pconn) \
  202. REFERENCE_DEBUG_ACTUAL_PARAMS \
  203. )
  204. #define UL_DEREFERENCE_HTTP_CONNECTION( pconn ) \
  205. UlDereferenceHttpConnection( \
  206. (pconn) \
  207. REFERENCE_DEBUG_ACTUAL_PARAMS \
  208. )
  209. #else // !REFERENCE_DEBUG
  210. #define UL_REFERENCE_HTTP_CONNECTION( pconn ) \
  211. InterlockedIncrement( &( pconn )->RefCount )
  212. #define UL_DEREFERENCE_HTTP_CONNECTION( pconn ) \
  213. if ( InterlockedDecrement( &( pconn )->RefCount ) == 0 ) \
  214. { \
  215. UL_CALL_PASSIVE( \
  216. &( ( pconn )->WorkItem ), \
  217. &UlDeleteHttpConnection \
  218. ); \
  219. } else
  220. #endif // !REFERENCE_DEBUG
  221. #define INIT_HTTP_REQUEST(pRequest) \
  222. do { \
  223. pRequest->RefCount = 1; \
  224. \
  225. pRequest->ParseState = ParseVerbState; \
  226. \
  227. InitializeListHead( &pRequest->UnknownHeaderList ); \
  228. InitializeListHead( &pRequest->IrpHead ); \
  229. InitializeListHead( &pRequest->ResponseHead ); \
  230. UlInitializeWorkItem( &pRequest->WorkItem ); \
  231. \
  232. pRequest->HeadersAppended = FALSE; \
  233. \
  234. pRequest->NextUnknownHeaderIndex = 0; \
  235. pRequest->UnknownHeaderCount = 0; \
  236. \
  237. HTTP_SET_NULL_ID(&pRequest->RequestId); \
  238. \
  239. pRequest->RequestIdCopy = pRequest->RequestId; \
  240. \
  241. pRequest->HeaderIndex[0] = HttpHeaderRequestMaximum; \
  242. \
  243. pRequest->AllocRefBuffers = 1; \
  244. pRequest->UsedRefBuffers = 0; \
  245. pRequest->pRefBuffers = pRequest->pInlineRefBuffers; \
  246. \
  247. UlInitializeSpinLock( \
  248. &pRequest->SpinLock, \
  249. "RequestSpinLock" \
  250. ); \
  251. \
  252. pRequest->SendsPending = 0; \
  253. pRequest->pLogData = NULL; \
  254. pRequest->pLogDataCopy = NULL; \
  255. pRequest->LogStatus = STATUS_SUCCESS; \
  256. \
  257. UlInitializeUrlInfo(&pRequest->ConfigInfo); \
  258. \
  259. RtlZeroMemory( \
  260. (PUCHAR)pRequest + FIELD_OFFSET(UL_INTERNAL_REQUEST, HeaderValid), \
  261. sizeof(*pRequest) - FIELD_OFFSET(UL_INTERNAL_REQUEST, HeaderValid) \
  262. ); \
  263. \
  264. pRequest->LoadBalancerCapability \
  265. = HttpLoadBalancerSophisticatedCapability; \
  266. } while (0, 0)
  267. NTSTATUS
  268. UlpCreateHttpRequest(
  269. IN PUL_HTTP_CONNECTION pHttpConnection,
  270. OUT PUL_INTERNAL_REQUEST *ppRequest
  271. );
  272. VOID
  273. UlpFreeHttpRequest(
  274. IN PUL_WORK_ITEM pWorkItem
  275. );
  276. VOID
  277. UlReferenceHttpRequest(
  278. IN PVOID pObject
  279. REFERENCE_DEBUG_FORMAL_PARAMS
  280. );
  281. VOID
  282. UlDereferenceHttpRequest(
  283. IN PUL_INTERNAL_REQUEST pRequest
  284. REFERENCE_DEBUG_FORMAL_PARAMS
  285. );
  286. #if REFERENCE_DEBUG
  287. #define UL_REFERENCE_INTERNAL_REQUEST( preq ) \
  288. UlReferenceHttpRequest( \
  289. (preq) \
  290. REFERENCE_DEBUG_ACTUAL_PARAMS \
  291. )
  292. #define UL_DEREFERENCE_INTERNAL_REQUEST( preq ) \
  293. UlDereferenceHttpRequest( \
  294. (preq) \
  295. REFERENCE_DEBUG_ACTUAL_PARAMS \
  296. )
  297. #else // !REFERENCE_DEBUG
  298. #define UL_REFERENCE_INTERNAL_REQUEST( preq ) \
  299. InterlockedIncrement( &( preq )->RefCount )
  300. #define UL_DEREFERENCE_INTERNAL_REQUEST( preq ) \
  301. if ( InterlockedDecrement( &( preq )->RefCount ) == 0 ) \
  302. { \
  303. UL_CALL_PASSIVE( \
  304. &( ( preq )->WorkItem ), \
  305. &UlpFreeHttpRequest \
  306. ); \
  307. } else
  308. #endif // !REFERENCE_DEBUG
  309. VOID
  310. UlCancelRequestIo(
  311. IN PUL_INTERNAL_REQUEST pRequest
  312. );
  313. PUL_REQUEST_BUFFER
  314. UlCreateRequestBuffer(
  315. ULONG BufferSize,
  316. ULONG BufferNumber,
  317. BOOLEAN UseLookaside
  318. );
  319. VOID
  320. UlFreeRequestBuffer(
  321. PUL_REQUEST_BUFFER pBuffer
  322. );
  323. #define UL_REFERENCE_REQUEST_BUFFER( pbuf ) \
  324. InterlockedIncrement( &( pbuf )->RefCount )
  325. #define UL_DEREFERENCE_REQUEST_BUFFER( pbuf ) \
  326. if ( InterlockedDecrement( &( pbuf )->RefCount ) == 0 ) \
  327. { \
  328. if ((pbuf)->FromLookaside) \
  329. { \
  330. UlPplFreeRequestBuffer( ( pbuf ) ); \
  331. } \
  332. else \
  333. { \
  334. UL_FREE_POOL_WITH_SIG( ( pbuf ), UL_REQUEST_BUFFER_POOL_TAG ); \
  335. } \
  336. }
  337. __inline
  338. PUL_HTTP_CONNECTION
  339. UlGetConnectionFromId(
  340. IN HTTP_CONNECTION_ID ConnectionId
  341. )
  342. {
  343. return (PUL_HTTP_CONNECTION) UlGetObjectFromOpaqueId(
  344. ConnectionId,
  345. UlOpaqueIdTypeHttpConnection,
  346. UlReferenceHttpConnection
  347. );
  348. }
  349. NTSTATUS
  350. UlAllocateRequestId(
  351. IN PUL_INTERNAL_REQUEST pRequest
  352. );
  353. VOID
  354. UlFreeRequestId(
  355. IN PUL_INTERNAL_REQUEST pRequest
  356. );
  357. PUL_INTERNAL_REQUEST
  358. UlGetRequestFromId(
  359. IN HTTP_REQUEST_ID RequestId,
  360. IN PUL_APP_POOL_PROCESS pProcess
  361. );
  362. //
  363. // Zombie connection list stuff
  364. //
  365. NTSTATUS
  366. UlInitializeHttpConnection(
  367. VOID
  368. );
  369. VOID
  370. UlTerminateHttpConnection(
  371. VOID
  372. );
  373. typedef
  374. BOOLEAN
  375. (*PUL_PURGE_ROUTINE)(
  376. IN PUL_HTTP_CONNECTION pHttpConnection,
  377. IN PVOID pPurgeContext
  378. );
  379. VOID
  380. UlPurgeZombieConnections(
  381. IN PUL_PURGE_ROUTINE pPurgeRoutine,
  382. IN PVOID pPurgeContext
  383. );
  384. BOOLEAN
  385. UlPurgeListeningEndpoint(
  386. IN PUL_HTTP_CONNECTION pHttpConnection,
  387. IN PVOID pListeningContext
  388. );
  389. BOOLEAN
  390. UlPurgeAppPoolProcess(
  391. IN PUL_HTTP_CONNECTION pHttpConnection,
  392. IN PVOID pProcessContext
  393. );
  394. VOID
  395. UlZombieTimerDpcRoutine(
  396. PKDPC Dpc,
  397. PVOID DeferredContext,
  398. PVOID SystemArgument1,
  399. PVOID SystemArgument2
  400. );
  401. NTSTATUS
  402. UlLogZombieConnection(
  403. IN PUL_INTERNAL_REQUEST pRequest,
  404. IN PUL_HTTP_CONNECTION pHttpConn,
  405. IN PHTTP_LOG_FIELDS_DATA pUserLogData,
  406. IN KPROCESSOR_MODE RequestorMode
  407. );
  408. NTSTATUS
  409. UlDisconnectHttpConnection(
  410. IN PUL_HTTP_CONNECTION pHttpConnection,
  411. IN PUL_COMPLETION_ROUTINE pCompletionRoutine,
  412. IN PVOID pCompletionContext
  413. );
  414. #endif // _HTTPCONN_H_