|
|
#ifndef _RAWCONNECTION_HXX_
#define _RAWCONNECTION_HXX_
#include <streamfilt.h>
#include "w3filter.hxx"
#define RAW_CONNECTION_SIGNATURE (DWORD)'NOCR'
#define RAW_CONNECTION_SIGNATURE_FREE (DWORD)'nocr'
class RAW_CONNECTION_HASH;
class W3_CONNECTION;
class RAW_CONNECTION { public: RAW_CONNECTION( CONNECTION_INFO * pConnectionInfo ); virtual ~RAW_CONNECTION();
static HRESULT Initialize( VOID ); static VOID Terminate( VOID ); static HRESULT StartListening( VOID ); static HRESULT StopListening( VOID ); static HRESULT GetConnection( CONNECTION_INFO * pConnectionInfo, RAW_CONNECTION ** ppRawConnection ); static HRESULT FindConnection( HTTP_RAW_CONNECTION_ID ConnectionId, RAW_CONNECTION ** ppRawConnection );
static BOOL WINAPI RawFilterServerSupportFunction( HTTP_FILTER_CONTEXT * pfc, enum SF_REQ_TYPE SupportFunction, void * pData, ULONG_PTR ul, ULONG_PTR ul2 ); static BOOL WINAPI RawFilterGetServerVariable( HTTP_FILTER_CONTEXT * pfc, LPSTR lpszVariableName, LPVOID lpvBuffer, LPDWORD lpdwSize ); static BOOL WINAPI RawFilterWriteClient( HTTP_FILTER_CONTEXT * pfc, LPVOID Buffer, LPDWORD lpdwBytes, DWORD dwReserved ); static VOID * WINAPI RawFilterAllocateMemory( HTTP_FILTER_CONTEXT * pfc, DWORD cbSize, DWORD dwReserved ); static BOOL WINAPI RawFilterAddResponseHeaders( HTTP_FILTER_CONTEXT * pfc, LPSTR lpszHeaders, DWORD dwReserved );
static HRESULT ProcessRawRead( RAW_STREAM_INFO * pRawStreamInfo, PVOID pvContext, BOOL * pfReadMore, BOOL * pfComplete, DWORD * pcbNextReadSize );
static VOID ReleaseContext( PVOID pvContext );
static HRESULT ProcessRawWrite( RAW_STREAM_INFO * pRawStreamInfo, PVOID pvContext, BOOL * pfComplete ); static HRESULT ProcessNewConnection( CONNECTION_INFO * pConnectionInfo, PVOID * ppvContext );
static VOID ProcessConnectionClose( VOID * pvContext );
HRESULT NotifyRawReadFilters( RAW_STREAM_INFO * pRawStreamInfo, BOOL * pfReadMore, BOOL * pfComplete );
HRESULT NotifyRawWriteFilters( RAW_STREAM_INFO * pRawStreamInfo, BOOL * pfComplete, DWORD dwStartFilter ); VOID EnableSkip( VOID ) { _skipLock.WriteLock(); _fSkipAtAll = TRUE; _skipLock.WriteUnlock(); } VOID AddSkippedData( ULARGE_INTEGER liData ); BOOL DetermineSkippedData( DWORD cbData, DWORD * pcbOffset ); HRESULT SendResponseHeader( CHAR * pszStatus, CHAR * pszAdditionalHeaders, HTTP_FILTER_CONTEXT * pfc );
HRESULT NotifyEndOfNetSessionFilters( VOID );
VOID CopyAllocatedFilterMemory( W3_FILTER_CONTEXT * pFilterContext );
PVOID AllocateFilterMemory( DWORD cbSize ) { FILTER_POOL_ITEM * pPoolItem; pPoolItem = FILTER_POOL_ITEM::CreateMemPoolItem( cbSize ); if ( pPoolItem != NULL ) { InsertHeadList( &_PoolHead, &(pPoolItem->_ListEntry) ); return pPoolItem->_pvData; } return NULL; } BOOL CheckSignature( VOID ) const { return _dwSignature == RAW_CONNECTION_SIGNATURE; } HTTP_RAW_CONNECTION_ID QueryRawConnectionId( VOID ) const { return _RawConnectionId; } HTTP_RAW_CONNECTION_ID * QueryRawConnectionIdKey( VOID ) const { return (HTTP_RAW_CONNECTION_ID*) &_RawConnectionId; } W3_MAIN_CONTEXT * GetAndReferenceMainContext( VOID ) { W3_MAIN_CONTEXT * pMainContext; _lock.WriteLock(); pMainContext = _pMainContext; if ( pMainContext != NULL ) { pMainContext->ReferenceMainContext(); } _lock.WriteUnlock(); return pMainContext; } VOID SetMainContext( W3_MAIN_CONTEXT * pNewContext ) { _lock.WriteLock(); if ( _pMainContext != NULL ) { _pMainContext->DereferenceMainContext(); } if ( pNewContext != NULL ) { pNewContext->ReferenceMainContext(); } _pMainContext = pNewContext; _lock.WriteUnlock(); } HRESULT DisableNotification( DWORD dwNotification ); HRESULT AddResponseHeaders( LPSTR pszAddResponseHeaders ) { return _strAddResponseHeaders.Append( pszAddResponseHeaders ); } HRESULT AddDenialHeaders( LPSTR pszAddDenialHeaders ) { return _strAddDenialHeaders.Append( pszAddDenialHeaders ); } VOID ReferenceRawConnection( VOID ) { LONG cRefs; cRefs = InterlockedIncrement( &_cRefs ); if ( sm_pTraceLog != NULL ) { WriteRefTraceLog( sm_pTraceLog, cRefs, this ); } } VOID DereferenceRawConnection( VOID ) { LONG cRefs; cRefs = InterlockedDecrement( &_cRefs );
if ( sm_pTraceLog != NULL ) { WriteRefTraceLog( sm_pTraceLog, cRefs, this ); } if ( cRefs == 0 ) { delete this; } } DWORD QueryNextReadSize( VOID ) const { return _cbNextReadSize; } VOID SetNextReadSize( DWORD cbNextReadSize ) { _cbNextReadSize = cbNextReadSize; } //
// A bunch of functions which need to gate their execution on whether
// or not we have an associated W3_CONNECTION with the this raw connection
//
FILTER_LIST * QueryFilterList( VOID ); BOOL QueryNotificationChanged( VOID ); BOOL QueryRawConnectionNotificationChanged( VOID );
BOOL IsDisableNotificationNeeded( DWORD dwFilter, DWORD dwNotification );
BOOL IsRawConnectionDisableNotificationNeeded( DWORD dwFilter, DWORD dwNotification ); PVOID QueryClientContext( DWORD dwFilter ); VOID SetClientContext( DWORD dwFilter, PVOID pvContext );
VOID SetLocalClientContext( DWORD dwFilter, PVOID pvContext );
VOID CopyContextPointers( W3_FILTER_CONTEXT * pFilterContext ); HRESULT CopyHeaders( W3_FILTER_CONTEXT * pFilterContext );
HRESULT GetLimitedServerVariables( LPSTR pszVariableName, PVOID pvBuffer, PDWORD pdwSize ); static HRESULT AssociateW3Connection( HTTP_RAW_CONNECTION_ID rawConnectionId, W3_CONNECTION * pW3Connection ); static BOOL QueryDoReadRawFiltering( VOID ) { return sm_fNotifyRawReadData; } private: DWORD _dwSignature; LONG _cRefs;
//
// Filter opaque contexts
//
PVOID _rgContexts[ MAX_FILTERS ];
//
// List of pool items allocated by client. These pool items will be
// migrated to the W3_FILTER_CONNECTION_CONTEXT when possible
//
LIST_ENTRY _PoolHead;
//
// The filter descriptor passed to filters
//
HTTP_FILTER_CONTEXT _hfc;
//
// Current filter. This is used to handle WriteClient()s from
// read/write raw data filters
//
DWORD _dwCurrentFilter;
//
// A function/context to call back into stream filter
//
PFN_SEND_DATA_BACK _pfnSendDataBack; PVOID _pvStreamContext;
//
// Local/remote socket address info
// AF_INET[6], SOCKADDR_IN[6]
//
USHORT _LocalAddressType; USHORT _RemoteAddressType;
SockAddress _SockLocalAddress; SockAddress _SockRemoteAddress;
//
// Raw connection id
//
HTTP_RAW_CONNECTION_ID _RawConnectionId;
//
// A response object which is needed if a raw read notification sends
// a response and then expects a send-response notification.
// (triple AAARRRRGGGGHH)
//
W3_RESPONSE _response;
//
// Main context which applies to this connection. There may be several
// during the life of this connection
//
W3_MAIN_CONTEXT * _pMainContext;
//
// Synchronize retrieval of main contexts
//
CSpinLock _lock;
//
// While we haven't associated with a WP request, we need to keep track
// of our own additional response/denial headers
//
STRA _strAddDenialHeaders; STRA _strAddResponseHeaders;
//
// Next read size (0 means use default size)
//
DWORD _cbNextReadSize; //
// Disable notifications
//
BOOL _fNotificationsDisabled; BUFFER _BuffSecureArray; BUFFER _BuffNonSecureArray; DWORD _dwSecureNotifications; DWORD _dwNonSecureNotifications;
//
// For backward compat mode, keep track of whether the worker process
// is handling the given connection by keeping tracking of bytes sent
//
ULARGE_INTEGER _liWorkerProcessData; BOOL _fSkipAtAll; CSpinLock _skipLock;
static RAW_CONNECTION_HASH * sm_pRawConnectionHash; static BOOL sm_fNotifyRawReadData; static PTRACE_LOG sm_pTraceLog; };
//
// RAW_CONNECTION_HASH
//
class RAW_CONNECTION_HASH : public CTypedHashTable< RAW_CONNECTION_HASH, RAW_CONNECTION, ULONGLONG * > { public: RAW_CONNECTION_HASH() : CTypedHashTable< RAW_CONNECTION_HASH, RAW_CONNECTION, ULONGLONG * > ( "RAW_CONNECTION_HASH" ) { } static ULONGLONG * ExtractKey( const RAW_CONNECTION * pRawConnection ) { return pRawConnection->QueryRawConnectionIdKey(); } static DWORD CalcKeyHash( ULONGLONG * ullKey ) { return HashBlob( ullKey, sizeof( ULONGLONG ) ); } static bool EqualKeys( ULONGLONG * ullKey1, ULONGLONG * ullKey2 ) { return *ullKey1 == *ullKey2; } static void AddRefRecord( RAW_CONNECTION * pEntry, int nIncr ) { if ( nIncr == +1 ) { pEntry->ReferenceRawConnection(); } else if ( nIncr == -1 ) { pEntry->DereferenceRawConnection(); } } }; #endif
|