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

/*++
Copyright (c) 1998-2002 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_
//
// Zombie connection timer period in seconds. A zombie connection
// may live; 30 < T < 60 seconds.
//
#define DEFAULT_ZOMBIE_HTTP_CONNECTION_TIMER_PERIOD_IN_SECONDS (30)
typedef struct _UL_ZOMBIE_HTTP_CONNECTION_LIST
{
LOCKED_LIST_HEAD LockList;
//
// Private timer stuff.
//
KTIMER Timer;
KDPC DpcObject;
UL_SPIN_LOCK TimerSpinLock;
BOOLEAN TimerInitialized;
UL_WORK_ITEM WorkItem;
LONG TimerRunning;
#ifdef ENABLE_HTTP_CONN_STATS
//
// Http connection statistics.
//
ULONG MaxZombieCount;
ULONG TotalCount;
ULONG TotalZombieCount;
ULONG TotalZombieRefusal;
#endif
} UL_ZOMBIE_HTTP_CONNECTION_LIST, *PUL_ZOMBIE_HTTP_CONNECTION_LIST;
//
// 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 ) \
HAS_VALID_SIGNATURE(entry, 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
);
ULONG
UlGetGlobalConnectionLimit(
VOID
);
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 // !REFERENCE_DEBUG
#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 \
); \
} else
#endif // !REFERENCE_DEBUG
#define INIT_HTTP_REQUEST(pRequest) \
do { \
pRequest->RefCount = 1; \
\
pRequest->ParseState = ParseVerbState; \
\
InitializeListHead( &pRequest->UnknownHeaderList ); \
InitializeListHead( &pRequest->IrpHead ); \
InitializeListHead( &pRequest->ResponseHead ); \
UlInitializeWorkItem( &pRequest->WorkItem ); \
\
pRequest->HeadersAppended = FALSE; \
\
pRequest->NextUnknownHeaderIndex = 0; \
pRequest->UnknownHeaderCount = 0; \
\
HTTP_SET_NULL_ID(&pRequest->RequestId); \
\
pRequest->RequestIdCopy = pRequest->RequestId; \
\
pRequest->HeaderIndex[0] = HttpHeaderRequestMaximum; \
\
pRequest->AllocRefBuffers = 1; \
pRequest->UsedRefBuffers = 0; \
pRequest->pRefBuffers = pRequest->pInlineRefBuffers; \
\
UlInitializeSpinLock( \
&pRequest->SpinLock, \
"RequestSpinLock" \
); \
\
pRequest->SendsPending = 0; \
pRequest->pLogData = NULL; \
pRequest->pLogDataCopy = NULL; \
pRequest->LogStatus = STATUS_SUCCESS; \
\
UlInitializeUrlInfo(&pRequest->ConfigInfo); \
\
RtlZeroMemory( \
(PUCHAR)pRequest + FIELD_OFFSET(UL_INTERNAL_REQUEST, HeaderValid), \
sizeof(*pRequest) - FIELD_OFFSET(UL_INTERNAL_REQUEST, HeaderValid) \
); \
\
pRequest->LoadBalancerCapability \
= HttpLoadBalancerSophisticatedCapability; \
} while (0, 0)
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 // !REFERENCE_DEBUG
#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 \
); \
} else
#endif // !REFERENCE_DEBUG
VOID
UlCancelRequestIo(
IN PUL_INTERNAL_REQUEST pRequest
);
PUL_REQUEST_BUFFER
UlCreateRequestBuffer(
ULONG BufferSize,
ULONG BufferNumber,
BOOLEAN UseLookaside
);
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 ) \
{ \
if ((pbuf)->FromLookaside) \
{ \
UlPplFreeRequestBuffer( ( pbuf ) ); \
} \
else \
{ \
UL_FREE_POOL_WITH_SIG( ( pbuf ), UL_REQUEST_BUFFER_POOL_TAG ); \
} \
}
__inline
PUL_HTTP_CONNECTION
UlGetConnectionFromId(
IN HTTP_CONNECTION_ID ConnectionId
)
{
return (PUL_HTTP_CONNECTION) UlGetObjectFromOpaqueId(
ConnectionId,
UlOpaqueIdTypeHttpConnection,
UlReferenceHttpConnection
);
}
NTSTATUS
UlAllocateRequestId(
IN PUL_INTERNAL_REQUEST pRequest
);
VOID
UlFreeRequestId(
IN PUL_INTERNAL_REQUEST pRequest
);
PUL_INTERNAL_REQUEST
UlGetRequestFromId(
IN HTTP_REQUEST_ID RequestId,
IN PUL_APP_POOL_PROCESS pProcess
);
//
// Zombie connection list stuff
//
NTSTATUS
UlInitializeHttpConnection(
VOID
);
VOID
UlTerminateHttpConnection(
VOID
);
typedef
BOOLEAN
(*PUL_PURGE_ROUTINE)(
IN PUL_HTTP_CONNECTION pHttpConnection,
IN PVOID pPurgeContext
);
VOID
UlPurgeZombieConnections(
IN PUL_PURGE_ROUTINE pPurgeRoutine,
IN PVOID pPurgeContext
);
BOOLEAN
UlPurgeListeningEndpoint(
IN PUL_HTTP_CONNECTION pHttpConnection,
IN PVOID pListeningContext
);
BOOLEAN
UlPurgeAppPoolProcess(
IN PUL_HTTP_CONNECTION pHttpConnection,
IN PVOID pProcessContext
);
VOID
UlZombieTimerDpcRoutine(
PKDPC Dpc,
PVOID DeferredContext,
PVOID SystemArgument1,
PVOID SystemArgument2
);
NTSTATUS
UlLogZombieConnection(
IN PUL_INTERNAL_REQUEST pRequest,
IN PUL_HTTP_CONNECTION pHttpConn,
IN PHTTP_LOG_FIELDS_DATA pUserLogData,
IN KPROCESSOR_MODE RequestorMode
);
NTSTATUS
UlDisconnectHttpConnection(
IN PUL_HTTP_CONNECTION pHttpConnection,
IN PUL_COMPLETION_ROUTINE pCompletionRoutine,
IN PVOID pCompletionContext
);
#endif // _HTTPCONN_H_