#ifndef _RAWCONNECTION_HXX_ #define _RAWCONNECTION_HXX_ #include #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 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 ); 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; } W3_MAIN_CONTEXT * QueryMainContext( VOID ) { return _pMainContext; } VOID SetMainContext( W3_MAIN_CONTEXT * pNewContext ) { if ( _pMainContext != NULL ) { _pMainContext->DereferenceMainContext(); } if ( pNewContext != NULL ) { pNewContext->ReferenceMainContext(); } _pMainContext = pNewContext; } HRESULT AddResponseHeaders( LPSTR pszAddResponseHeaders ) { return _strAddResponseHeaders.Append( pszAddResponseHeaders ); } HRESULT AddDenialHeaders( LPSTR pszAddDenialHeaders ) { return _strAddDenialHeaders.Append( pszAddDenialHeaders ); } VOID ReferenceRawConnection( VOID ) { InterlockedIncrement( &_cRefs ); } VOID DereferenceRawConnection( VOID ) { if ( !InterlockedDecrement( &_cRefs ) ) { 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 IsDisableNotificationNeeded( DWORD dwFilter, DWORD dwNotification ); PVOID QueryClientContext( DWORD dwFilter ); VOID SetClientContext( 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 ); 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 port info // USHORT _LocalPort; DWORD _LocalAddress; USHORT _RemotePort; DWORD _RemoteAddress; // // 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; // // 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; static RAW_CONNECTION_HASH * sm_pRawConnectionHash; }; // // 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->QueryRawConnectionId(); } static DWORD CalcKeyHash( ULONGLONG ullKey ) { return Hash( (DWORD) ullKey ); } 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