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.

492 lines
15 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name :
  4. httphdr.hxx
  5. Abstract:
  6. This module declares all the variables and functions
  7. for Dictionary manager.
  8. It also defines the structure for handling HTTP headers
  9. Author:
  10. Murali R. Krishnan ( MuraliK ) 8-Nov-1996
  11. Environment:
  12. User - Win32
  13. Project:
  14. Internet Server DLL
  15. Revision History:
  16. --*/
  17. # ifndef _DICT_HXX_
  18. # define _DICT_HXX_
  19. /************************************************************
  20. * Include Headers
  21. ************************************************************/
  22. # include "buffer.hxx"
  23. # include "dbgutil.h"
  24. //
  25. // Format of entries in the ALL_HTTP_FAST_MAP_HEADERS is
  26. // HfmHeader( enumeration-id, string)
  27. //
  28. # define ALL_HTTP_FAST_MAP_HEADERS() \
  29. HfmHeader( HM_MET, "method") \
  30. HfmHeader( HM_URL, "url") \
  31. HfmHeader( HM_VER, "version") \
  32. \
  33. HfmHeader( HM_ACC, "Accept:") \
  34. HfmHeader( HM_ACL, "Accept-Language:") \
  35. HfmHeader( HM_CON, "Connection:") \
  36. HfmHeader( HM_HST, "Host:") \
  37. HfmHeader( HM_REF, "Referer:") \
  38. HfmHeader( HM_UAT, "User-Agent:") \
  39. \
  40. HfmHeader( HM_PRG, "Pragma:") \
  41. HfmHeader( HM_COK, "Cookie:") \
  42. HfmHeader( HM_AUT, "Authorization:") \
  43. \
  44. HfmHeader( HM_IMS, "If-Modified-Since:") \
  45. \
  46. HfmHeader( HM_UPX, "UA-pixels:") \
  47. HfmHeader( HM_UCL, "UA-color:") \
  48. HfmHeader( HM_UOS, "UA-OS:") \
  49. HfmHeader( HM_CPU, "UA-CPU:") \
  50. \
  51. HfmHeader( HM_CLE, "Content-Length:") \
  52. HfmHeader( HM_CTY, "Content-Type:") \
  53. \
  54. HfmHeader( HM_PRA, "Proxy-Authorization:") \
  55. HfmHeader( HM_PRC, "Proxy-Connection:") \
  56. \
  57. HfmHeader( HM_RNG, "Range:") \
  58. HfmHeader( HM_IFR, "If-Range:") \
  59. HfmHeader( HM_IFM, "If-Match:") \
  60. HfmHeader( HM_INM, "If-None-Match:") \
  61. HfmHeader( HM_UMS, "Unless-Modified-Since:")\
  62. HfmHeader( HM_IUM, "If-Unmodified-Since:") \
  63. \
  64. HfmHeader( HM_TEC, "Transfer-Encoding:") \
  65. HfmHeader( HM_VIA, "Via:") \
  66. HfmHeader( HM_FWD, "Forwarded:") \
  67. HfmHeader( HM_LCK, "Lock-Token:") \
  68. HfmHeader( HM_TRN, "Translate:") \
  69. HfmHeader( HM_ISM, "If:") \
  70. HfmHeader( HM_ACE, "Accept-Encoding:") \
  71. /*------------------------------------------------------------
  72. * AVG_HTTP_HEADER_LEN
  73. * o empirically calculated based on the header-len of various
  74. * headers specified in ALL_HTTP_FAST_MAP_HEADERS
  75. * If you add a new header, longer than the average value, make
  76. * sure you update the average as well!!!
  77. * Include the terminating null-char in your calculation
  78. ------------------------------------------------------------*/
  79. # define AVG_HTTP_HEADER_LEN (14)
  80. // generate the enumeration IDs
  81. # define HfmHeader( HfmId, HfmString) HfmId,
  82. enum HTTP_FAST_MAP_HEADERS {
  83. ALL_HTTP_FAST_MAP_HEADERS()
  84. MAX_HTTP_FAST_MAP_HEADERS
  85. }; // enum HTTP_FAST_MAP_HEADERS
  86. # undef HfmHeader
  87. inline BOOL IsValidHfm( IN HTTP_FAST_MAP_HEADERS hfm)
  88. {
  89. return ( (HM_MET <= hfm) && ( hfm < MAX_HTTP_FAST_MAP_HEADERS));
  90. }
  91. //
  92. // _HTTP_IS_LINEAR_SPACE()
  93. // Given a character, this function tests if this character is in
  94. // linear white-space (\t or ' ') character.
  95. // It optimizes for the case where the character is not a linear white-space
  96. //
  97. inline BOOL _HTTP_IS_LINEAR_SPACE( CHAR c)
  98. { return ( ((c) <= ' ') && (((c) == ' ') || ((c) == '\t'))); }
  99. /************************************************************
  100. * Type Definitions
  101. ************************************************************/
  102. /*++
  103. Dictionary: provides storage for <name, value> pairs.
  104. Goals: Insert and lookup has to be fast.
  105. Amount of memory consumed should be kept as low as possible.
  106. Objects:
  107. DICTIONARY_MAPPER
  108. - provides a mapping between the string name and ordinal for fast-mapping.
  109. - one instance per collection of <string, ordinal>s.
  110. DICTIONARY
  111. provides the storage and lookup for a given collection
  112. Multiple instances of this object can be created, one per input datum.
  113. --*/
  114. class DICTIONARY_MAPPER {
  115. public:
  116. dllexp
  117. virtual ~DICTIONARY_MAPPER(VOID) {}
  118. dllexp
  119. virtual BOOL Initialize( VOID) = 0;
  120. dllexp virtual
  121. BOOL FindOrdinal( IN LPCSTR pszName,
  122. IN INT cchName,
  123. OUT DWORD * pdwOrdinal) const = 0;
  124. dllexp virtual
  125. LPCSTR FindName( IN DWORD dwOrdinal) const = 0;
  126. dllexp virtual
  127. DWORD NumItems( VOID) const = 0;
  128. dllexp virtual
  129. VOID PrintToBuffer( IN CHAR * pchBuffer,
  130. IN OUT LPDWORD pcch) const = 0;
  131. dllexp virtual VOID Print( VOID) const = 0;
  132. }; // class DICTIONARY_MAPPER
  133. /*++
  134. class HTTP_HEADER_MAPPER
  135. o Defines the mapper for mapping the HTTP header names to ordinals.
  136. --*/
  137. class HTTP_HEADER_MAPPER : public DICTIONARY_MAPPER {
  138. public:
  139. HTTP_HEADER_MAPPER( IN DWORD sigChar)
  140. : m_nItems ( 0),
  141. m_nSigChars ( sigChar),
  142. m_rgOnNameMapper ( NULL),
  143. DICTIONARY_MAPPER()
  144. {
  145. }
  146. dllexp virtual ~HTTP_HEADER_MAPPER(VOID);
  147. dllexp
  148. virtual BOOL Initialize( VOID);
  149. dllexp virtual
  150. BOOL FindOrdinal( IN LPCSTR pszName,
  151. IN INT cchName,
  152. OUT DWORD * pdwOrdinal) const;
  153. dllexp virtual
  154. LPCSTR FindName( IN DWORD dwOrdinal) const;
  155. dllexp virtual
  156. DWORD NumItems( VOID) const { return ( m_nItems); }
  157. dllexp virtual
  158. VOID PrintToBuffer( IN CHAR * pchBuffer,
  159. IN OUT LPDWORD pcch) const;
  160. dllexp virtual VOID Print( VOID) const;
  161. DWORD SizeOfNameMapper( VOID) const { return (m_nSigChars * m_nSigChars); }
  162. VOID SetSigChars( IN DWORD sigChars) { m_nSigChars = sigChars; }
  163. private:
  164. DWORD m_nItems; // # items in the linear space
  165. DWORD m_nSigChars;
  166. // same as g_OnFieldNameMapper[] for HTTP headers
  167. // int m_rgOnNameMapper[ _HTTP_HEADER_SIG_CHARS * _HTTP_HEADER_SIG_CHARS];
  168. int * m_rgOnNameMapper;
  169. }; // class HTTP_HEADER_MAPPER
  170. # define MAX_HEADERS_PER_CHUNK ( 10)
  171. //
  172. // The following parameter DEFAULT_HTTP_HEADER_LEN is set using empirical data
  173. // to cover the 80% of requests coming in. This definitely includes the requests
  174. // used by performance benchmarks.
  175. // Any revision or change in HTTP or traffic requires that this parameter be
  176. // tweaked.
  177. # define DEFAULT_HTTP_HEADER_LEN ( 1 * 512) // 0.5 KB
  178. // Minimum bytes to maintain in the buffer object of HttpHeader Dictionary
  179. # define HH_MIN (0) // 4 KB
  180. # define HH_GROW_BY (1 * 1024) // 1 KB
  181. //Maximum bytes to maintain in the buffer object of the HttpHeader Dictionary
  182. #define HH_MAX (64 * 1024) //64 KB
  183. struct NAME_VALUE_PAIR {
  184. const CHAR * pchName; // pointer to start of the name
  185. DWORD cchName; // length of the name
  186. LPCSTR pchValue; // pointer to value block
  187. DWORD cchValue; // length of the value block
  188. }; // NAME_VALUE_PAIR
  189. struct HH_ITERATOR {
  190. PVOID pChunk;
  191. DWORD dwOrdinal;
  192. DWORD dwPair;
  193. NAME_VALUE_PAIR np;
  194. }; // struct HH_ITERATOR
  195. class NAME_VALUE_CHUNK {
  196. public:
  197. NAME_VALUE_CHUNK(VOID)
  198. {
  199. Reset();
  200. }
  201. VOID Reset( VOID)
  202. {
  203. InitializeListHead( & m_listEntry);
  204. ZeroMemory( m_rgNVP, sizeof( m_rgNVP));
  205. m_nPairs = 0;
  206. }
  207. BOOL IsSpaceAvailable( VOID) const
  208. { return ( m_nPairs < MAX_HEADERS_PER_CHUNK); }
  209. BOOL AddEntry( IN const CHAR * pszHeader, IN DWORD cchHeader,
  210. IN const CHAR * pszValue, IN DWORD cchValue
  211. );
  212. dllexp NAME_VALUE_PAIR *
  213. FindEntry( IN const CHAR * pszHeader, IN DWORD cchHeader);
  214. dllexp NAME_VALUE_PAIR *
  215. FindMatchingOrFreeEntry( IN const CHAR * pszHeader,
  216. IN DWORD cchHeader,
  217. IN LPBOOL pfFound );
  218. dllexp DWORD PrintToBuffer( IN CHAR * pchBuffer,
  219. IN OUT LPDWORD pcch) const;
  220. dllexp BOOL UpdatePointers( IN const CHAR * pchOld,
  221. IN DWORD cchLen,
  222. IN const CHAR * pchNew);
  223. LIST_ENTRY m_listEntry;
  224. DWORD m_nPairs;
  225. DWORD m_dwPadding;
  226. NAME_VALUE_PAIR m_rgNVP[ MAX_HEADERS_PER_CHUNK];
  227. }; // class NAME_VALUE_CHUNK
  228. class HTTP_HEADERS {
  229. public:
  230. // ----------------------------------------
  231. // General functions
  232. // ----------------------------------------
  233. dllexp HTTP_HEADERS(VOID);
  234. dllexp ~HTTP_HEADERS( VOID);
  235. dllexp VOID Reset( VOID);
  236. dllexp BOOL ParseInput( IN const CHAR * pchHeaderBlob,
  237. IN DWORD cchLen,
  238. OUT DWORD * pcbExtraData
  239. );
  240. dllexp VOID InitIterator( OUT HH_ITERATOR * phi)
  241. {
  242. phi->dwOrdinal = 0;
  243. phi->pChunk = (PVOID)m_ActiveList.Flink;
  244. phi->dwPair = 0;
  245. } // InitIterator()
  246. // ----------------------------------------
  247. // Fast-Map + Chunks Functions
  248. // ----------------------------------------
  249. dllexp BOOL StoreHeader(IN const CHAR * pszHeader, IN DWORD cchHeader,
  250. IN const CHAR * pszValue, IN DWORD cchValue
  251. );
  252. dllexp BOOL StoreHeader(IN const CHAR * pszHeader,
  253. IN const CHAR * pszValue
  254. );
  255. // Finds the value in both fast-map and non-fast-map chunks
  256. dllexp CHAR * FindValue( IN LPCSTR pszName,
  257. OUT LPDWORD pcchValue = NULL);
  258. // Cancel an item from the headers
  259. dllexp VOID CancelHeader( IN LPCSTR pszName);
  260. dllexp BOOL NextPair( IN OUT HH_ITERATOR * phi,
  261. OUT NAME_VALUE_PAIR ** ppnp
  262. );
  263. // ----------------------------------------
  264. // Fast Map functions
  265. // ----------------------------------------
  266. // substitute for GetFastMap()->Store()
  267. dllexp VOID FastMapStore( IN HTTP_FAST_MAP_HEADERS hfm, IN LPCSTR psz)
  268. {
  269. DBG_ASSERT( IsValidHfm( hfm));
  270. m_rgpszHeaders[ hfm] = psz;
  271. if ( (DWORD ) hfm >= m_iMaxFastMapHeader) {
  272. m_iMaxFastMapHeader = (DWORD ) hfm + 1;
  273. }
  274. }
  275. // substitute for GetFastMap()->CheckAndConat()
  276. dllexp BOOL FastMapStoreWithConcat( IN HTTP_FAST_MAP_HEADERS hfm,
  277. IN LPCSTR pszValue, IN DWORD cchValue);
  278. // substitute for GetFastMap()->Cancel()
  279. dllexp VOID FastMapCancel( IN HTTP_FAST_MAP_HEADERS hfm)
  280. { FastMapStore( hfm, NULL); }
  281. // substitute for GetFastMap()->QueryValue( hfm)
  282. dllexp LPCSTR FastMapQueryValue( IN HTTP_FAST_MAP_HEADERS hfm) const
  283. {
  284. DBG_ASSERT( IsValidHfm( hfm));
  285. return ( m_rgpszHeaders[ hfm]);
  286. }
  287. // substitute for GetFastMap()->QueryStrValue( hfm)
  288. dllexp LPCSTR FastMapQueryStrValue( IN HTTP_FAST_MAP_HEADERS hfm) const
  289. {
  290. DBG_ASSERT( IsValidHfm( hfm));
  291. return ( (NULL != m_rgpszHeaders[ hfm]) ?
  292. m_rgpszHeaders[ hfm] : (LPCSTR ) &m_chNull);
  293. }
  294. dllexp DWORD FastMapMaxIndex( VOID) const
  295. { return ( m_iMaxFastMapHeader); }
  296. // ----------------------------------------
  297. // Functions on Chunks
  298. // ----------------------------------------
  299. // Finds the <header,value> pair in non-fast-map
  300. dllexp NAME_VALUE_PAIR *
  301. FindValueInChunks( IN LPCSTR pszName, IN DWORD cchName);
  302. dllexp BOOL
  303. NextPairInChunks( IN OUT HH_ITERATOR * phi,
  304. OUT NAME_VALUE_PAIR ** ppnp
  305. );
  306. // ----------------------------------------
  307. // Diagnostics/Debugging functions
  308. // ----------------------------------------
  309. dllexp VOID PrintToBuffer( IN CHAR * pchBuffer,
  310. IN OUT LPDWORD pcch) const;
  311. dllexp VOID Print( VOID) const;
  312. private:
  313. DWORD m_iMaxFastMapHeader; // index for the highest filled fast-map header
  314. LPCSTR m_rgpszHeaders[ MAX_HTTP_FAST_MAP_HEADERS]; // fast map headers
  315. CHAR m_chNull; // null string
  316. CHAR m_rcInlinedHeader[ DEFAULT_HTTP_HEADER_LEN];
  317. DWORD m_cchHeaders;
  318. // Buffer containing the header-chunks
  319. DWORD m_cchBuffHeaders; // # of bytes in the buffer
  320. BUFFER m_buffHeaders;
  321. // NYI: Consider using singly-linked list
  322. LIST_ENTRY m_ActiveList; // objects of type NAME_VALUE_CHUNK
  323. LIST_ENTRY m_FreeList; // objects of type NAME_VALUE_CHUNK
  324. BOOL MakeRoomInBuffer( IN DWORD cchReqd, IN LPCSTR * ppszVal);
  325. BOOL UpdatePointers( IN const CHAR * pchOld, IN DWORD cchLen,
  326. IN const CHAR * pchNew);
  327. dllexp BOOL ConcatToHolder( IN LPCSTR * ppsz,
  328. IN LPCSTR pszNew,
  329. IN DWORD cchNew
  330. );
  331. // Always adds entry in non-fast-map chunks, with concatenation
  332. dllexp BOOL
  333. AddEntryToChunks( IN const CHAR * pszHeader, IN DWORD cchHeader,
  334. IN const CHAR * pszValue, IN DWORD cchValue,
  335. BOOL fCopyValue = FALSE
  336. );
  337. dllexp VOID
  338. CancelHeaderInChunks( IN LPCSTR pszName, IN DWORD cchName);
  339. BOOL
  340. ParseHeaderFirstLine( IN const CHAR * pchFirstLine,
  341. IN CHAR * pchScan,
  342. IN DWORD cchFirstLine);
  343. public:
  344. static dllexp BOOL Initialize( VOID);
  345. static dllexp VOID Cleanup( VOID);
  346. #ifdef _PRIVATE_HTTP_HEADERS_TEST
  347. static dllexp HTTP_HEADER_MAPPER * QueryHHMapper(void);
  348. #endif // _PRIVATE_HTTP_HEADERS_TEST
  349. static BOOL
  350. FindOrdinalForHeader( LPCSTR pszHeader, DWORD cchHeader,
  351. LPDWORD pdwOrdinal)
  352. { return ( sm_hhm.FindOrdinal( pszHeader, cchHeader,
  353. pdwOrdinal )
  354. );
  355. }
  356. private:
  357. dllexp static HTTP_HEADER_MAPPER sm_hhm;
  358. }; // class HTTP_HEADERS
  359. typedef HTTP_HEADERS * PHHEADERS;
  360. # endif // _DICT_HXX_
  361. /************************ End of File ***********************/