/*++ Copyright (c) 1998-2001 Microsoft Corporation Module Name: httpconn.h Abstract: This module contains declarations for manipulation HTTP_CONNECTION objects. Author: Keith Moore (keithmo) 08-Jul-1998 Revision History: --*/ /* there is a bit of refcount madness going on. basically, these are the object we have. OPAQUE_ID_TABLE | |--> UL_INTERNAL_REQUEST | | o | | |--> UL_HTTP_CONNECTION | o o | UL_CONNECTION there is a circular reference from UL_CONNECTION to UL_HTTP_CONNECTION. the chain that brings down a connection starts with UlConnectionDestroyed notifcation which releases the reference from the UL_CONNECTION. at this time the opaque id's are also deleted, releasing their references. when the http_connection refcount hits 0, it releases the reference on the UL_CONNECTION and the HTTP_REQUEST's. poof. everyone is gone now. CODEWORK: think about making hardref's everywhere and adding "letgo" terminate methods */ #ifndef _HTTPCONN_H_ #define _HTTPCONN_H_ #ifdef __cplusplus extern "C" { #endif // // Refcounted structure to hold the number of conn for each Site. // Multiple connections may try to reach to the same entry thru the // the corresponding ( means the last request's happening on the connection ) // cgroup. This entry get allocated when cgroup created with connection // limit is enabled. // typedef struct _UL_CONNECTION_COUNT_ENTRY { // // Signature is UL_CONNECTION_COUNT_ENTRY_POOL_TAG // ULONG Signature; // // Ref count for this Site Counter Entry // LONG RefCount; // // Current number of connections // ULONG CurConnections; // // Maximum allowed connections // ULONG MaxConnections; } UL_CONNECTION_COUNT_ENTRY, *PUL_CONNECTION_COUNT_ENTRY; #define IS_VALID_CONNECTION_COUNT_ENTRY( entry ) \ ( (entry != NULL) && ((entry)->Signature == UL_CONNECTION_COUNT_ENTRY_POOL_TAG) ) VOID UlDereferenceConnectionCountEntry( IN PUL_CONNECTION_COUNT_ENTRY pEntry REFERENCE_DEBUG_FORMAL_PARAMS ); #define DEREFERENCE_CONNECTION_COUNT_ENTRY( pEntry ) \ UlDereferenceConnectionCountEntry( \ (pEntry) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ ) VOID UlReferenceConnectionCountEntry( IN PUL_CONNECTION_COUNT_ENTRY pEntry REFERENCE_DEBUG_FORMAL_PARAMS ); #define REFERENCE_CONNECTION_COUNT_ENTRY( pEntry ) \ UlReferenceConnectionCountEntry( \ (pEntry) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ ) NTSTATUS UlCreateConnectionCountEntry( IN OUT PUL_CONFIG_GROUP_OBJECT pConfigGroup, IN ULONG MaxConnections ); ULONG UlSetMaxConnections( IN OUT PULONG pCurMaxConnection, IN ULONG NewMaxConnection ); VOID UlSetGlobalConnectionLimit( IN ULONG Limit ); NTSTATUS UlInitGlobalConnectionLimits( VOID ); BOOLEAN UlAcceptConnection( IN PULONG pMaxConnection, IN OUT PULONG pCurConnection ); LONG UlDecrementConnections( IN OUT PULONG pCurConnection ); BOOLEAN UlCheckSiteConnectionLimit( IN OUT PUL_HTTP_CONNECTION pConnection, IN OUT PUL_URL_CONFIG_GROUP_INFO pConfigInfo ); BOOLEAN UlAcceptGlobalConnection( VOID ); // // function prototypes // NTSTATUS UlCreateHttpConnection( OUT PUL_HTTP_CONNECTION *ppHttpConnection, IN PUL_CONNECTION pConnection ); NTSTATUS UlCreateHttpConnectionId( IN PUL_HTTP_CONNECTION pHttpConnection ); VOID UlConnectionDestroyedWorker( IN PUL_WORK_ITEM pWorkItem ); NTSTATUS UlBindConnectionToProcess( IN PUL_HTTP_CONNECTION pHttpConnection, IN PUL_APP_POOL_OBJECT pAppPool, IN PUL_APP_POOL_PROCESS pProcess ); PUL_APP_POOL_PROCESS UlQueryProcessBinding( IN PUL_HTTP_CONNECTION pHttpConnection, IN PUL_APP_POOL_OBJECT pAppPool ); VOID UlUnlinkHttpRequest( IN PUL_INTERNAL_REQUEST pRequest ); VOID UlCleanupHttpConnection( IN PUL_HTTP_CONNECTION pHttpConnection ); VOID UlDeleteHttpConnection( IN PUL_WORK_ITEM pWorkItem ); VOID UlReferenceHttpConnection( IN PVOID pObject REFERENCE_DEBUG_FORMAL_PARAMS ); VOID UlDereferenceHttpConnection( IN PUL_HTTP_CONNECTION pHttpConnection REFERENCE_DEBUG_FORMAL_PARAMS ); #if REFERENCE_DEBUG #define UL_REFERENCE_HTTP_CONNECTION( pconn ) \ UlReferenceHttpConnection( \ (pconn) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ ) #define UL_DEREFERENCE_HTTP_CONNECTION( pconn ) \ UlDereferenceHttpConnection( \ (pconn) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ ) #else #define UL_REFERENCE_HTTP_CONNECTION( pconn ) \ InterlockedIncrement( &( pconn )->RefCount ) #define UL_DEREFERENCE_HTTP_CONNECTION( pconn ) \ if ( InterlockedDecrement( &( pconn )->RefCount ) == 0 ) \ { \ UL_CALL_PASSIVE( \ &( ( pconn )->WorkItem ), \ &UlDeleteHttpConnection \ ); \ } #endif NTSTATUS UlpCreateHttpRequest( IN PUL_HTTP_CONNECTION pHttpConnection, OUT PUL_INTERNAL_REQUEST *ppRequest ); VOID UlpFreeHttpRequest( IN PUL_WORK_ITEM pWorkItem ); VOID UlReferenceHttpRequest( IN PVOID pObject REFERENCE_DEBUG_FORMAL_PARAMS ); VOID UlDereferenceHttpRequest( IN PUL_INTERNAL_REQUEST pRequest REFERENCE_DEBUG_FORMAL_PARAMS ); #if REFERENCE_DEBUG #define UL_REFERENCE_INTERNAL_REQUEST( preq ) \ UlReferenceHttpRequest( \ (preq) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ ) #define UL_DEREFERENCE_INTERNAL_REQUEST( preq ) \ UlDereferenceHttpRequest( \ (preq) \ REFERENCE_DEBUG_ACTUAL_PARAMS \ ) #else #define UL_REFERENCE_INTERNAL_REQUEST( preq ) \ InterlockedIncrement( &( preq )->RefCount ) #define UL_DEREFERENCE_INTERNAL_REQUEST( preq ) \ if ( InterlockedDecrement( &( preq )->RefCount ) == 0 ) \ { \ UL_CALL_PASSIVE( \ &( ( preq )->WorkItem ), \ &UlpFreeHttpRequest \ ); \ } #endif VOID UlCancelRequestIo( IN PUL_INTERNAL_REQUEST pRequest ); PUL_REQUEST_BUFFER UlCreateRequestBuffer( ULONG BufferSize, ULONG BufferNumber ); VOID UlFreeRequestBuffer( PUL_REQUEST_BUFFER pBuffer ); #define UL_REFERENCE_REQUEST_BUFFER( pbuf ) \ InterlockedIncrement( &( pbuf )->RefCount ) #define UL_DEREFERENCE_REQUEST_BUFFER( pbuf ) \ if ( InterlockedDecrement( &( pbuf )->RefCount ) == 0 ) \ { \ (pbuf)->Signature = MAKE_FREE_TAG(UL_REQUEST_BUFFER_POOL_TAG); \ \ if ((pbuf)->AllocBytes > DEFAULT_MAX_REQUEST_BUFFER_SIZE) \ { \ UL_FREE_POOL_WITH_SIG((pbuf), UL_REQUEST_BUFFER_POOL_TAG); \ } \ else \ { \ UlPplFreeRequestBuffer((pbuf)); \ } \ } __inline PUL_HTTP_CONNECTION FASTCALL UlGetConnectionFromId( IN HTTP_CONNECTION_ID ConnectionId ) { return (PUL_HTTP_CONNECTION) UlGetObjectFromOpaqueId( ConnectionId, UlOpaqueIdTypeHttpConnection, UlReferenceHttpConnection ); } #define REUSE_CONNECTION_OPAQUE_ID #ifdef REUSE_CONNECTION_OPAQUE_ID NTSTATUS UlAllocateRequestId( IN PUL_INTERNAL_REQUEST pRequest ); VOID UlFreeRequestId( IN PUL_INTERNAL_REQUEST pRequest ); PUL_INTERNAL_REQUEST UlGetRequestFromId( IN HTTP_REQUEST_ID RequestId ); #else __inline NTSTATUS UlAllocateRequestId( IN PUL_INTERNAL_REQUEST pRequest ) { return UlAllocateOpaqueId( &pRequest->RequestId, UlOpaqueIdTypeHttpRequest, pRequest ); } __inline NTSTATUS UlFreeRequestId( IN PUL_INTERNAL_REQUEST pRequest ) { return UlFreeOpaqueId( &pRequest->RequestId, UlOpaqueIdTypeHttpRequest ); } __inline PUL_INTERNAL_REQUEST FASTCALL UlGetRequestFromId( IN HTTP_REQUEST_ID RequestId ) { return (PUL_INTERNAL_REQUEST) UlGetObjectFromOpaqueId( RequestId, UlOpaqueIdTypeHttpRequest, UlReferenceHttpRequest ); } #endif #ifdef __cplusplus }; // extern "C" #endif #endif // _HTTPCONN_H_