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.

412 lines
12 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. compression.h
  5. Abstract:
  6. Do Http compression
  7. Author:
  8. Anil Ruia (AnilR) 10-Apr-2000
  9. --*/
  10. #ifndef _COMPRESSION_H_
  11. #define _COMPRESSION_H_
  12. #define COMPRESSION_MIN_IO_BUFFER_SIZE 256
  13. #define COMPRESSION_MAX_IO_BUFFER_SIZE 100000
  14. #define COMPRESSION_MIN_COMP_BUFFER_SIZE 1024
  15. #define COMPRESSION_MAX_COMP_BUFFER_SIZE 100000
  16. #define COMPRESSION_MAX_QUEUE_LENGTH 10000
  17. #define COMPRESSION_MIN_FILES_DELETED_PER_DISK_FREE 1
  18. #define COMPRESSION_MAX_FILES_DELETED_PER_DISK_FREE 1024
  19. #define COMPRESSION_MAX_COMPRESSION_LEVEL 10
  20. #define COMPRESSION_DEFAULT_DISK_SPACE_USAGE 100000000
  21. #define COMPRESSION_DEFAULT_BUFFER_SIZE 8192
  22. #define COMPRESSION_DEFAULT_QUEUE_LENGTH 1000
  23. #define COMPRESSION_DEFAULT_FILES_DELETED_PER_DISK_FREE 256
  24. #define COMPRESSION_DEFAULT_FILE_SIZE_FOR_COMPRESSION 1
  25. enum COMP_INIT_STATUS
  26. {
  27. COMP_INIT_NONE,
  28. COMP_INIT_SCHEMES,
  29. COMP_INIT_DIRLOCK,
  30. COMP_INIT_CONTEXT,
  31. COMP_INIT_DONE
  32. };
  33. class COMPRESSION_SCHEME
  34. {
  35. public:
  36. COMPRESSION_SCHEME()
  37. : m_hCompressionDll (NULL),
  38. m_pCompressionContext (NULL),
  39. m_dwPriority (1),
  40. m_dwDynamicCompressionLevel (0),
  41. m_dwOnDemandCompressionLevel (COMPRESSION_MAX_COMPRESSION_LEVEL),
  42. m_dwCreateFlags (0),
  43. m_fDoStaticCompression (TRUE),
  44. m_fDoOnDemandCompression (TRUE),
  45. m_fDoDynamicCompression (TRUE),
  46. m_pfnInitCompression (NULL),
  47. m_pfnDeInitCompression (NULL),
  48. m_pfnCreateCompression (NULL),
  49. m_pfnCompress (NULL),
  50. m_pfnDestroyCompression (NULL),
  51. m_pfnResetCompression (NULL)
  52. {}
  53. HRESULT Initialize(MB *pmb, LPWSTR schemeName);
  54. ~COMPRESSION_SCHEME()
  55. {
  56. if (m_pfnDestroyCompression && m_pCompressionContext)
  57. {
  58. m_pfnDestroyCompression(m_pCompressionContext);
  59. m_pCompressionContext = NULL;
  60. }
  61. if (m_pfnDeInitCompression)
  62. {
  63. m_pfnDeInitCompression();
  64. }
  65. if (m_hCompressionDll)
  66. {
  67. FreeLibrary(m_hCompressionDll);
  68. m_hCompressionDll = NULL;
  69. }
  70. }
  71. STRU m_strCompressionSchemeName;
  72. STRA m_straCompressionSchemeName;
  73. STRU m_strFilePrefix;
  74. MULTISZ m_mszFileExtensions;
  75. MULTISZ m_mszScriptFileExtensions;
  76. DWORD m_dwPriority;
  77. HMODULE m_hCompressionDll;
  78. PFNCODEC_INIT_COMPRESSION m_pfnInitCompression;
  79. PFNCODEC_DEINIT_COMPRESSION m_pfnDeInitCompression;
  80. PFNCODEC_CREATE_COMPRESSION m_pfnCreateCompression;
  81. PFNCODEC_COMPRESS m_pfnCompress;
  82. PFNCODEC_DESTROY_COMPRESSION m_pfnDestroyCompression;
  83. PFNCODEC_RESET_COMPRESSION m_pfnResetCompression;
  84. // The compression context used for static compression
  85. PVOID m_pCompressionContext;
  86. DWORD m_dwDynamicCompressionLevel;
  87. DWORD m_dwOnDemandCompressionLevel;
  88. DWORD m_dwCreateFlags;
  89. BOOL m_fDoDynamicCompression;
  90. BOOL m_fDoStaticCompression;
  91. BOOL m_fDoOnDemandCompression;
  92. };
  93. typedef enum
  94. {
  95. COMPRESSION_WORK_ITEM_COMPRESS,
  96. COMPRESSION_WORK_ITEM_DELETE,
  97. COMPRESSION_WORK_ITEM_TERMINATE,
  98. COMPRESSION_WORK_ITEM_INVALID
  99. } COMPRESSION_WORK_ITEM_TYPE;
  100. class COMPRESSION_WORK_ITEM
  101. {
  102. public:
  103. COMPRESSION_WORK_ITEM()
  104. : WorkItemType (COMPRESSION_WORK_ITEM_INVALID),
  105. scheme (NULL),
  106. pFileInfo (NULL)
  107. {
  108. InitializeListHead(&ListEntry);
  109. }
  110. virtual ~COMPRESSION_WORK_ITEM()
  111. {
  112. InitializeListHead(&ListEntry);
  113. if (pFileInfo != NULL)
  114. {
  115. pFileInfo->DereferenceCacheEntry();
  116. pFileInfo = NULL;
  117. }
  118. }
  119. LIST_ENTRY ListEntry;
  120. COMPRESSION_WORK_ITEM_TYPE WorkItemType;
  121. COMPRESSION_SCHEME *scheme;
  122. STRU strPhysicalPath;
  123. W3_FILE_INFO *pFileInfo;
  124. };
  125. #define MAX_SERVER_SCHEMES 100
  126. typedef enum
  127. {
  128. DO_STATIC_COMPRESSION,
  129. DO_DYNAMIC_COMPRESSION
  130. } COMPRESSION_TO_PERFORM;
  131. #define DYNAMIC_COMPRESSION_BUFFER_SIZE 2000
  132. typedef enum
  133. {
  134. IN_CHUNK_LENGTH,
  135. IN_CHUNK_EXTENSION,
  136. IN_CHUNK_HEADER_NEW_LINE,
  137. AT_CHUNK_DATA_NEW_LINE,
  138. IN_CHUNK_DATA_NEW_LINE,
  139. IN_CHUNK_DATA
  140. } COMPRESS_CHUNK_STATE;
  141. class COMPRESSION_CONTEXT
  142. {
  143. public:
  144. static HRESULT Initialize()
  145. {
  146. ALLOC_CACHE_CONFIGURATION acConfig;
  147. acConfig.nConcurrency = 1;
  148. acConfig.nThreshold = 100;
  149. acConfig.cbSize = sizeof COMPRESSION_CONTEXT;
  150. allocHandler = new ALLOC_CACHE_HANDLER("COMPRESSION_CONTEXT",
  151. &acConfig);
  152. if (allocHandler == NULL)
  153. {
  154. return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
  155. }
  156. return S_OK;
  157. }
  158. static void Terminate()
  159. {
  160. if (allocHandler != NULL)
  161. {
  162. delete allocHandler;
  163. }
  164. }
  165. void *operator new(
  166. #if DBG
  167. size_t size
  168. #else
  169. size_t
  170. #endif
  171. )
  172. {
  173. DBG_ASSERT(size == sizeof COMPRESSION_CONTEXT);
  174. DBG_ASSERT(allocHandler != NULL);
  175. return allocHandler->Alloc();
  176. }
  177. void operator delete(void *pCompressionContext)
  178. {
  179. DBG_ASSERT(pCompressionContext != NULL);
  180. DBG_ASSERT(allocHandler != NULL);
  181. DBG_REQUIRE(allocHandler->Free(pCompressionContext));
  182. }
  183. COMPRESSION_CONTEXT()
  184. : m_pScheme (NULL),
  185. m_fTransferChunkEncoded (FALSE),
  186. m_pCompressionContext (NULL),
  187. m_dwBytesInCurrentEncodedChunk (0),
  188. m_encodedChunkState (IN_CHUNK_LENGTH),
  189. m_fHeadersSent (FALSE),
  190. m_fRequestIsHead (FALSE),
  191. m_fOriginalBodyEmpty (TRUE)
  192. {}
  193. ~COMPRESSION_CONTEXT()
  194. {
  195. if (m_pCompressionContext)
  196. {
  197. m_pScheme->m_pfnDestroyCompression(m_pCompressionContext);
  198. m_pCompressionContext = NULL;
  199. }
  200. }
  201. HRESULT ProcessEncodedChunkHeader();
  202. HRESULT CalculateEncodedChunkByteCount();
  203. VOID DeleteEncodedChunkExtension();
  204. VOID IncrementPointerInULChunk(IN DWORD dwIncr = 1)
  205. {
  206. m_pbOrigData += dwIncr;
  207. m_cbOrigData -= dwIncr;
  208. }
  209. COMPRESSION_SCHEME *m_pScheme;
  210. //
  211. // Is the original response chunk encoded?
  212. //
  213. BOOL m_fTransferChunkEncoded;
  214. //
  215. // If the original response is Chunk encoded, information about the
  216. // current chunk in the response
  217. //
  218. DWORD m_dwBytesInCurrentEncodedChunk;
  219. COMPRESS_CHUNK_STATE m_encodedChunkState;
  220. //
  221. // The context used by the compression routines
  222. //
  223. PVOID m_pCompressionContext;
  224. //
  225. // position in the original response
  226. //
  227. PBYTE m_pbOrigData;
  228. DWORD m_cbOrigData;
  229. static ALLOC_CACHE_HANDLER *allocHandler;
  230. //
  231. // Some members to keep track of HEAD request body suppression
  232. //
  233. BOOL m_fRequestIsHead;
  234. BOOL m_fOriginalBodyEmpty;
  235. //
  236. // Has the end of response headers been seen?
  237. //
  238. BOOL m_fHeadersSent;
  239. //
  240. // A chunk's worth of data
  241. //
  242. BUFFER m_bufChunk;
  243. };
  244. class HTTP_COMPRESSION
  245. {
  246. public:
  247. static HRESULT Initialize();
  248. static VOID Terminate();
  249. static HRESULT DoStaticFileCompression(IN W3_CONTEXT *pW3Context,
  250. IN OUT W3_FILE_INFO **ppFileInfo,
  251. OUT BOOL *pfDoCache);
  252. static HRESULT OnSendResponse(
  253. IN W3_CONTEXT *pW3Context);
  254. static HRESULT DoDynamicCompression(
  255. IN W3_CONTEXT *pW3Context,
  256. IN BOOL fMoreData,
  257. IN HTTP_FILTER_RAW_DATA * pRawData );
  258. static BOOL QueryDoStaticCompression()
  259. {
  260. return sm_fDoStaticCompression;
  261. }
  262. static BOOL QueryDoDynamicCompression()
  263. {
  264. return sm_fDoDynamicCompression;
  265. }
  266. private:
  267. static COMPRESSION_SCHEME *sm_pCompressionSchemes[MAX_SERVER_SCHEMES];
  268. static DWORD sm_dwNumberOfSchemes;
  269. static STRU *sm_pstrCompressionDirectory;
  270. static STRA *sm_pstrCacheControlHeader;
  271. static STRA *sm_pstrExpiresHeader;
  272. static BOOL sm_fDoStaticCompression;
  273. static BOOL sm_fDoDynamicCompression;
  274. static BOOL sm_fDoOnDemandCompression;
  275. static BOOL sm_fDoDiskSpaceLimiting;
  276. static BOOL sm_fNoCompressionForHttp10;
  277. static BOOL sm_fNoCompressionForProxies;
  278. static BOOL sm_fNoCompressionForRange;
  279. static BOOL sm_fSendCacheHeaders;
  280. static DWORD sm_dwMaxDiskSpaceUsage;
  281. static DWORD sm_dwIoBufferSize;
  282. static DWORD sm_dwCompressionBufferSize;
  283. static DWORD sm_dwMaxQueueLength;
  284. static DWORD sm_dwFilesDeletedPerDiskFree;
  285. static DWORD sm_dwMinFileSizeForCompression;
  286. static PBYTE sm_pIoBuffer;
  287. static PBYTE sm_pCompressionBuffer;
  288. static CRITICAL_SECTION sm_CompressionDirectoryLock;
  289. static DWORD sm_dwCurrentDiskSpaceUsage;
  290. static BOOL sm_fCompressionVolumeIsFat;
  291. static LIST_ENTRY sm_CompressionThreadWorkQueue;
  292. static CRITICAL_SECTION sm_CompressionThreadLock;
  293. static HANDLE sm_hThreadEvent;
  294. static HANDLE sm_hCompressionThreadHandle;
  295. static DWORD sm_dwCurrentQueueLength;
  296. static COMP_INIT_STATUS sm_InitStatus;
  297. static BOOL sm_fIsTerminating;
  298. static HRESULT ReadMetadata(MB *pmb);
  299. static HRESULT InitializeCompressionSchemes(MB *pmb);
  300. static HRESULT InitializeCompressionDirectory();
  301. static HRESULT InitializeCompressionThread();
  302. static DWORD WINAPI CompressionThread(LPVOID);
  303. static BOOL QueueWorkItem(
  304. IN COMPRESSION_WORK_ITEM *WorkItem,
  305. IN BOOL fOverrideMaxQueueLength,
  306. IN BOOL fQueueAtHead);
  307. static VOID FindMatchingSchemes(
  308. IN CHAR * pszAcceptEncoding,
  309. IN LPWSTR pszExtension,
  310. IN COMPRESSION_TO_PERFORM performCompr,
  311. OUT DWORD matchingSchemes[],
  312. OUT DWORD *pdwClientCompressionCount);
  313. static HRESULT ConvertPhysicalPathToCompressedPath(
  314. IN COMPRESSION_SCHEME *scheme,
  315. IN STRU *pstrPhysicalPath,
  316. OUT STRU *pstrCompressedFileName);
  317. static BOOL CheckForExistenceOfCompressedFile(
  318. IN W3_FILE_INFO *pOrigFile,
  319. IN STRU *pstrCompressedFileName,
  320. OUT W3_FILE_INFO **ppCompFile,
  321. IN BOOL fDeleteAllowed = TRUE);
  322. static BOOL QueueCompressFile(
  323. IN COMPRESSION_SCHEME *scheme,
  324. IN W3_FILE_INFO *pFileInfo);
  325. static VOID CompressFile(IN COMPRESSION_SCHEME *scheme,
  326. IN W3_FILE_INFO *pFileInfo);
  327. static VOID FreeDiskSpace();
  328. static BOOL CompressAndWriteData(
  329. IN COMPRESSION_SCHEME *scheme,
  330. IN PBYTE InputBuffer,
  331. IN DWORD BytesToCompress,
  332. OUT PDWORD BytesWritten,
  333. IN HANDLE hCompressedFile);
  334. };
  335. #endif _COMPRESSION_H_