|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name : httphdr.hxx
Abstract: This module declares all the variables and functions for Dictionary manager. It also defines the structure for handling HTTP headers
Author:
Murali R. Krishnan ( MuraliK ) 8-Nov-1996
Environment: User - Win32
Project:
Internet Server DLL
Revision History:
--*/
# ifndef _DICT_HXX_
# define _DICT_HXX_
/************************************************************
* Include Headers ************************************************************/
# include "buffer.hxx"
# include "dbgutil.h"
//
// Format of entries in the ALL_HTTP_FAST_MAP_HEADERS is
// HfmHeader( enumeration-id, string)
//
# define ALL_HTTP_FAST_MAP_HEADERS() \
HfmHeader( HM_MET, "method") \ HfmHeader( HM_URL, "url") \ HfmHeader( HM_VER, "version") \ \ HfmHeader( HM_ACC, "Accept:") \ HfmHeader( HM_ACL, "Accept-Language:") \ HfmHeader( HM_CON, "Connection:") \ HfmHeader( HM_HST, "Host:") \ HfmHeader( HM_REF, "Referer:") \ HfmHeader( HM_UAT, "User-Agent:") \ \ HfmHeader( HM_PRG, "Pragma:") \ HfmHeader( HM_COK, "Cookie:") \ HfmHeader( HM_AUT, "Authorization:") \ \ HfmHeader( HM_IMS, "If-Modified-Since:") \ \ HfmHeader( HM_UPX, "UA-pixels:") \ HfmHeader( HM_UCL, "UA-color:") \ HfmHeader( HM_UOS, "UA-OS:") \ HfmHeader( HM_CPU, "UA-CPU:") \ \ HfmHeader( HM_CLE, "Content-Length:") \ HfmHeader( HM_CTY, "Content-Type:") \ \ HfmHeader( HM_PRA, "Proxy-Authorization:") \ HfmHeader( HM_PRC, "Proxy-Connection:") \ \ HfmHeader( HM_RNG, "Range:") \ HfmHeader( HM_IFR, "If-Range:") \ HfmHeader( HM_IFM, "If-Match:") \ HfmHeader( HM_INM, "If-None-Match:") \ HfmHeader( HM_UMS, "Unless-Modified-Since:")\ HfmHeader( HM_IUM, "If-Unmodified-Since:") \ \ HfmHeader( HM_TEC, "Transfer-Encoding:") \ HfmHeader( HM_VIA, "Via:") \ HfmHeader( HM_FWD, "Forwarded:") \ HfmHeader( HM_LCK, "Lock-Token:") \ HfmHeader( HM_TRN, "Translate:") \ HfmHeader( HM_ISM, "If:") \ HfmHeader( HM_ACE, "Accept-Encoding:") \
/*------------------------------------------------------------
* AVG_HTTP_HEADER_LEN * o empirically calculated based on the header-len of various * headers specified in ALL_HTTP_FAST_MAP_HEADERS * If you add a new header, longer than the average value, make * sure you update the average as well!!! * Include the terminating null-char in your calculation ------------------------------------------------------------*/ # define AVG_HTTP_HEADER_LEN (14)
// generate the enumeration IDs
# define HfmHeader( HfmId, HfmString) HfmId,
enum HTTP_FAST_MAP_HEADERS {
ALL_HTTP_FAST_MAP_HEADERS()
MAX_HTTP_FAST_MAP_HEADERS }; // enum HTTP_FAST_MAP_HEADERS
# undef HfmHeader
inline BOOL IsValidHfm( IN HTTP_FAST_MAP_HEADERS hfm) { return ( (HM_MET <= hfm) && ( hfm < MAX_HTTP_FAST_MAP_HEADERS)); }
//
// _HTTP_IS_LINEAR_SPACE()
// Given a character, this function tests if this character is in
// linear white-space (\t or ' ') character.
// It optimizes for the case where the character is not a linear white-space
//
inline BOOL _HTTP_IS_LINEAR_SPACE( CHAR c) { return ( ((c) <= ' ') && (((c) == ' ') || ((c) == '\t'))); }
/************************************************************
* Type Definitions ************************************************************/
/*++
Dictionary: provides storage for <name, value> pairs. Goals: Insert and lookup has to be fast. Amount of memory consumed should be kept as low as possible.
Objects: DICTIONARY_MAPPER - provides a mapping between the string name and ordinal for fast-mapping. - one instance per collection of <string, ordinal>s.
DICTIONARY provides the storage and lookup for a given collection Multiple instances of this object can be created, one per input datum.
--*/
class DICTIONARY_MAPPER {
public:
dllexp virtual ~DICTIONARY_MAPPER(VOID) {}
dllexp virtual BOOL Initialize( VOID) = 0;
dllexp virtual BOOL FindOrdinal( IN LPCSTR pszName, IN INT cchName, OUT DWORD * pdwOrdinal) const = 0;
dllexp virtual LPCSTR FindName( IN DWORD dwOrdinal) const = 0;
dllexp virtual DWORD NumItems( VOID) const = 0;
dllexp virtual VOID PrintToBuffer( IN CHAR * pchBuffer, IN OUT LPDWORD pcch) const = 0;
dllexp virtual VOID Print( VOID) const = 0;
}; // class DICTIONARY_MAPPER
/*++
class HTTP_HEADER_MAPPER
o Defines the mapper for mapping the HTTP header names to ordinals.
--*/
class HTTP_HEADER_MAPPER : public DICTIONARY_MAPPER {
public:
HTTP_HEADER_MAPPER( IN DWORD sigChar) : m_nItems ( 0), m_nSigChars ( sigChar), m_rgOnNameMapper ( NULL), DICTIONARY_MAPPER() { }
dllexp virtual ~HTTP_HEADER_MAPPER(VOID);
dllexp virtual BOOL Initialize( VOID);
dllexp virtual BOOL FindOrdinal( IN LPCSTR pszName, IN INT cchName, OUT DWORD * pdwOrdinal) const;
dllexp virtual LPCSTR FindName( IN DWORD dwOrdinal) const;
dllexp virtual DWORD NumItems( VOID) const { return ( m_nItems); }
dllexp virtual VOID PrintToBuffer( IN CHAR * pchBuffer, IN OUT LPDWORD pcch) const; dllexp virtual VOID Print( VOID) const;
DWORD SizeOfNameMapper( VOID) const { return (m_nSigChars * m_nSigChars); } VOID SetSigChars( IN DWORD sigChars) { m_nSigChars = sigChars; }
private: DWORD m_nItems; // # items in the linear space
DWORD m_nSigChars; // same as g_OnFieldNameMapper[] for HTTP headers
// int m_rgOnNameMapper[ _HTTP_HEADER_SIG_CHARS * _HTTP_HEADER_SIG_CHARS];
int * m_rgOnNameMapper;
}; // class HTTP_HEADER_MAPPER
# define MAX_HEADERS_PER_CHUNK ( 10)
//
// The following parameter DEFAULT_HTTP_HEADER_LEN is set using empirical data
// to cover the 80% of requests coming in. This definitely includes the requests
// used by performance benchmarks.
// Any revision or change in HTTP or traffic requires that this parameter be
// tweaked.
# define DEFAULT_HTTP_HEADER_LEN ( 1 * 512) // 0.5 KB
// Minimum bytes to maintain in the buffer object of HttpHeader Dictionary
# define HH_MIN (0) // 4 KB
# define HH_GROW_BY (1 * 1024) // 1 KB
//Maximum bytes to maintain in the buffer object of the HttpHeader Dictionary
#define HH_MAX (64 * 1024) //64 KB
struct NAME_VALUE_PAIR { const CHAR * pchName; // pointer to start of the name
DWORD cchName; // length of the name
LPCSTR pchValue; // pointer to value block
DWORD cchValue; // length of the value block
}; // NAME_VALUE_PAIR
struct HH_ITERATOR { PVOID pChunk; DWORD dwOrdinal; DWORD dwPair;
NAME_VALUE_PAIR np; }; // struct HH_ITERATOR
class NAME_VALUE_CHUNK {
public: NAME_VALUE_CHUNK(VOID) { Reset(); }
VOID Reset( VOID) { InitializeListHead( & m_listEntry); ZeroMemory( m_rgNVP, sizeof( m_rgNVP)); m_nPairs = 0; }
BOOL IsSpaceAvailable( VOID) const { return ( m_nPairs < MAX_HEADERS_PER_CHUNK); }
BOOL AddEntry( IN const CHAR * pszHeader, IN DWORD cchHeader, IN const CHAR * pszValue, IN DWORD cchValue );
dllexp NAME_VALUE_PAIR * FindEntry( IN const CHAR * pszHeader, IN DWORD cchHeader);
dllexp NAME_VALUE_PAIR * FindMatchingOrFreeEntry( IN const CHAR * pszHeader, IN DWORD cchHeader, IN LPBOOL pfFound );
dllexp DWORD PrintToBuffer( IN CHAR * pchBuffer, IN OUT LPDWORD pcch) const;
dllexp BOOL UpdatePointers( IN const CHAR * pchOld, IN DWORD cchLen, IN const CHAR * pchNew);
LIST_ENTRY m_listEntry; DWORD m_nPairs; DWORD m_dwPadding; NAME_VALUE_PAIR m_rgNVP[ MAX_HEADERS_PER_CHUNK];
}; // class NAME_VALUE_CHUNK
class HTTP_HEADERS {
public:
// ----------------------------------------
// General functions
// ----------------------------------------
dllexp HTTP_HEADERS(VOID); dllexp ~HTTP_HEADERS( VOID); dllexp VOID Reset( VOID); dllexp BOOL ParseInput( IN const CHAR * pchHeaderBlob, IN DWORD cchLen, OUT DWORD * pcbExtraData );
dllexp VOID InitIterator( OUT HH_ITERATOR * phi) { phi->dwOrdinal = 0; phi->pChunk = (PVOID)m_ActiveList.Flink; phi->dwPair = 0;
} // InitIterator()
// ----------------------------------------
// Fast-Map + Chunks Functions
// ----------------------------------------
dllexp BOOL StoreHeader(IN const CHAR * pszHeader, IN DWORD cchHeader, IN const CHAR * pszValue, IN DWORD cchValue );
dllexp BOOL StoreHeader(IN const CHAR * pszHeader, IN const CHAR * pszValue );
// Finds the value in both fast-map and non-fast-map chunks
dllexp CHAR * FindValue( IN LPCSTR pszName, OUT LPDWORD pcchValue = NULL);
// Cancel an item from the headers
dllexp VOID CancelHeader( IN LPCSTR pszName);
dllexp BOOL NextPair( IN OUT HH_ITERATOR * phi, OUT NAME_VALUE_PAIR ** ppnp );
// ----------------------------------------
// Fast Map functions
// ----------------------------------------
// substitute for GetFastMap()->Store()
dllexp VOID FastMapStore( IN HTTP_FAST_MAP_HEADERS hfm, IN LPCSTR psz) { DBG_ASSERT( IsValidHfm( hfm)); m_rgpszHeaders[ hfm] = psz; if ( (DWORD ) hfm >= m_iMaxFastMapHeader) { m_iMaxFastMapHeader = (DWORD ) hfm + 1; } }
// substitute for GetFastMap()->CheckAndConat()
dllexp BOOL FastMapStoreWithConcat( IN HTTP_FAST_MAP_HEADERS hfm, IN LPCSTR pszValue, IN DWORD cchValue);
// substitute for GetFastMap()->Cancel()
dllexp VOID FastMapCancel( IN HTTP_FAST_MAP_HEADERS hfm) { FastMapStore( hfm, NULL); }
// substitute for GetFastMap()->QueryValue( hfm)
dllexp LPCSTR FastMapQueryValue( IN HTTP_FAST_MAP_HEADERS hfm) const { DBG_ASSERT( IsValidHfm( hfm)); return ( m_rgpszHeaders[ hfm]); }
// substitute for GetFastMap()->QueryStrValue( hfm)
dllexp LPCSTR FastMapQueryStrValue( IN HTTP_FAST_MAP_HEADERS hfm) const { DBG_ASSERT( IsValidHfm( hfm)); return ( (NULL != m_rgpszHeaders[ hfm]) ? m_rgpszHeaders[ hfm] : (LPCSTR ) &m_chNull); }
dllexp DWORD FastMapMaxIndex( VOID) const { return ( m_iMaxFastMapHeader); }
// ----------------------------------------
// Functions on Chunks
// ----------------------------------------
// Finds the <header,value> pair in non-fast-map
dllexp NAME_VALUE_PAIR * FindValueInChunks( IN LPCSTR pszName, IN DWORD cchName);
dllexp BOOL NextPairInChunks( IN OUT HH_ITERATOR * phi, OUT NAME_VALUE_PAIR ** ppnp );
// ----------------------------------------
// Diagnostics/Debugging functions
// ----------------------------------------
dllexp VOID PrintToBuffer( IN CHAR * pchBuffer, IN OUT LPDWORD pcch) const; dllexp VOID Print( VOID) const;
private: DWORD m_iMaxFastMapHeader; // index for the highest filled fast-map header
LPCSTR m_rgpszHeaders[ MAX_HTTP_FAST_MAP_HEADERS]; // fast map headers
CHAR m_chNull; // null string
CHAR m_rcInlinedHeader[ DEFAULT_HTTP_HEADER_LEN]; DWORD m_cchHeaders;
// Buffer containing the header-chunks
DWORD m_cchBuffHeaders; // # of bytes in the buffer
BUFFER m_buffHeaders;
// NYI: Consider using singly-linked list
LIST_ENTRY m_ActiveList; // objects of type NAME_VALUE_CHUNK
LIST_ENTRY m_FreeList; // objects of type NAME_VALUE_CHUNK
BOOL MakeRoomInBuffer( IN DWORD cchReqd, IN LPCSTR * ppszVal); BOOL UpdatePointers( IN const CHAR * pchOld, IN DWORD cchLen, IN const CHAR * pchNew);
dllexp BOOL ConcatToHolder( IN LPCSTR * ppsz, IN LPCSTR pszNew, IN DWORD cchNew );
// Always adds entry in non-fast-map chunks, with concatenation
dllexp BOOL AddEntryToChunks( IN const CHAR * pszHeader, IN DWORD cchHeader, IN const CHAR * pszValue, IN DWORD cchValue, BOOL fCopyValue = FALSE );
dllexp VOID CancelHeaderInChunks( IN LPCSTR pszName, IN DWORD cchName);
BOOL ParseHeaderFirstLine( IN const CHAR * pchFirstLine, IN CHAR * pchScan, IN DWORD cchFirstLine);
public: static dllexp BOOL Initialize( VOID); static dllexp VOID Cleanup( VOID);
#ifdef _PRIVATE_HTTP_HEADERS_TEST
static dllexp HTTP_HEADER_MAPPER * QueryHHMapper(void);
#endif // _PRIVATE_HTTP_HEADERS_TEST
static BOOL FindOrdinalForHeader( LPCSTR pszHeader, DWORD cchHeader, LPDWORD pdwOrdinal) { return ( sm_hhm.FindOrdinal( pszHeader, cchHeader, pdwOrdinal ) ); }
private: dllexp static HTTP_HEADER_MAPPER sm_hhm;
}; // class HTTP_HEADERS
typedef HTTP_HEADERS * PHHEADERS;
# endif // _DICT_HXX_
/************************ End of File ***********************/
|