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
412 lines
12 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
compression.h
|
|
|
|
Abstract:
|
|
|
|
Do Http compression
|
|
|
|
Author:
|
|
|
|
Anil Ruia (AnilR) 10-Apr-2000
|
|
|
|
--*/
|
|
|
|
#ifndef _COMPRESSION_H_
|
|
#define _COMPRESSION_H_
|
|
|
|
#define COMPRESSION_MIN_IO_BUFFER_SIZE 256
|
|
#define COMPRESSION_MAX_IO_BUFFER_SIZE 100000
|
|
#define COMPRESSION_MIN_COMP_BUFFER_SIZE 1024
|
|
#define COMPRESSION_MAX_COMP_BUFFER_SIZE 100000
|
|
#define COMPRESSION_MAX_QUEUE_LENGTH 10000
|
|
#define COMPRESSION_MIN_FILES_DELETED_PER_DISK_FREE 1
|
|
#define COMPRESSION_MAX_FILES_DELETED_PER_DISK_FREE 1024
|
|
#define COMPRESSION_MAX_COMPRESSION_LEVEL 10
|
|
|
|
#define COMPRESSION_DEFAULT_DISK_SPACE_USAGE 100000000
|
|
#define COMPRESSION_DEFAULT_BUFFER_SIZE 8192
|
|
#define COMPRESSION_DEFAULT_QUEUE_LENGTH 1000
|
|
#define COMPRESSION_DEFAULT_FILES_DELETED_PER_DISK_FREE 256
|
|
#define COMPRESSION_DEFAULT_FILE_SIZE_FOR_COMPRESSION 1
|
|
|
|
enum COMP_INIT_STATUS
|
|
{
|
|
COMP_INIT_NONE,
|
|
COMP_INIT_SCHEMES,
|
|
COMP_INIT_DIRLOCK,
|
|
COMP_INIT_CONTEXT,
|
|
COMP_INIT_DONE
|
|
};
|
|
|
|
class COMPRESSION_SCHEME
|
|
{
|
|
public:
|
|
COMPRESSION_SCHEME()
|
|
: m_hCompressionDll (NULL),
|
|
m_pCompressionContext (NULL),
|
|
m_dwPriority (1),
|
|
m_dwDynamicCompressionLevel (0),
|
|
m_dwOnDemandCompressionLevel (COMPRESSION_MAX_COMPRESSION_LEVEL),
|
|
m_dwCreateFlags (0),
|
|
m_fDoStaticCompression (TRUE),
|
|
m_fDoOnDemandCompression (TRUE),
|
|
m_fDoDynamicCompression (TRUE),
|
|
m_pfnInitCompression (NULL),
|
|
m_pfnDeInitCompression (NULL),
|
|
m_pfnCreateCompression (NULL),
|
|
m_pfnCompress (NULL),
|
|
m_pfnDestroyCompression (NULL),
|
|
m_pfnResetCompression (NULL)
|
|
{}
|
|
|
|
HRESULT Initialize(MB *pmb, LPWSTR schemeName);
|
|
|
|
~COMPRESSION_SCHEME()
|
|
{
|
|
if (m_pfnDestroyCompression && m_pCompressionContext)
|
|
{
|
|
m_pfnDestroyCompression(m_pCompressionContext);
|
|
m_pCompressionContext = NULL;
|
|
}
|
|
|
|
if (m_pfnDeInitCompression)
|
|
{
|
|
m_pfnDeInitCompression();
|
|
}
|
|
|
|
if (m_hCompressionDll)
|
|
{
|
|
FreeLibrary(m_hCompressionDll);
|
|
m_hCompressionDll = NULL;
|
|
}
|
|
}
|
|
|
|
STRU m_strCompressionSchemeName;
|
|
STRA m_straCompressionSchemeName;
|
|
STRU m_strFilePrefix;
|
|
MULTISZ m_mszFileExtensions;
|
|
MULTISZ m_mszScriptFileExtensions;
|
|
|
|
DWORD m_dwPriority;
|
|
|
|
HMODULE m_hCompressionDll;
|
|
PFNCODEC_INIT_COMPRESSION m_pfnInitCompression;
|
|
PFNCODEC_DEINIT_COMPRESSION m_pfnDeInitCompression;
|
|
PFNCODEC_CREATE_COMPRESSION m_pfnCreateCompression;
|
|
PFNCODEC_COMPRESS m_pfnCompress;
|
|
PFNCODEC_DESTROY_COMPRESSION m_pfnDestroyCompression;
|
|
PFNCODEC_RESET_COMPRESSION m_pfnResetCompression;
|
|
|
|
// The compression context used for static compression
|
|
PVOID m_pCompressionContext;
|
|
|
|
DWORD m_dwDynamicCompressionLevel;
|
|
DWORD m_dwOnDemandCompressionLevel;
|
|
DWORD m_dwCreateFlags;
|
|
BOOL m_fDoDynamicCompression;
|
|
BOOL m_fDoStaticCompression;
|
|
BOOL m_fDoOnDemandCompression;
|
|
};
|
|
|
|
typedef enum
|
|
{
|
|
COMPRESSION_WORK_ITEM_COMPRESS,
|
|
COMPRESSION_WORK_ITEM_DELETE,
|
|
COMPRESSION_WORK_ITEM_TERMINATE,
|
|
COMPRESSION_WORK_ITEM_INVALID
|
|
} COMPRESSION_WORK_ITEM_TYPE;
|
|
|
|
class COMPRESSION_WORK_ITEM
|
|
{
|
|
public:
|
|
COMPRESSION_WORK_ITEM()
|
|
: WorkItemType (COMPRESSION_WORK_ITEM_INVALID),
|
|
scheme (NULL),
|
|
pFileInfo (NULL)
|
|
{
|
|
InitializeListHead(&ListEntry);
|
|
}
|
|
|
|
virtual ~COMPRESSION_WORK_ITEM()
|
|
{
|
|
InitializeListHead(&ListEntry);
|
|
|
|
if (pFileInfo != NULL)
|
|
{
|
|
pFileInfo->DereferenceCacheEntry();
|
|
pFileInfo = NULL;
|
|
}
|
|
}
|
|
|
|
LIST_ENTRY ListEntry;
|
|
COMPRESSION_WORK_ITEM_TYPE WorkItemType;
|
|
COMPRESSION_SCHEME *scheme;
|
|
STRU strPhysicalPath;
|
|
W3_FILE_INFO *pFileInfo;
|
|
};
|
|
|
|
#define MAX_SERVER_SCHEMES 100
|
|
|
|
typedef enum
|
|
{
|
|
DO_STATIC_COMPRESSION,
|
|
DO_DYNAMIC_COMPRESSION
|
|
} COMPRESSION_TO_PERFORM;
|
|
|
|
#define DYNAMIC_COMPRESSION_BUFFER_SIZE 2000
|
|
|
|
typedef enum
|
|
{
|
|
IN_CHUNK_LENGTH,
|
|
IN_CHUNK_EXTENSION,
|
|
IN_CHUNK_HEADER_NEW_LINE,
|
|
AT_CHUNK_DATA_NEW_LINE,
|
|
IN_CHUNK_DATA_NEW_LINE,
|
|
IN_CHUNK_DATA
|
|
} COMPRESS_CHUNK_STATE;
|
|
|
|
class COMPRESSION_CONTEXT
|
|
{
|
|
public:
|
|
static HRESULT Initialize()
|
|
{
|
|
ALLOC_CACHE_CONFIGURATION acConfig;
|
|
|
|
acConfig.nConcurrency = 1;
|
|
acConfig.nThreshold = 100;
|
|
acConfig.cbSize = sizeof COMPRESSION_CONTEXT;
|
|
|
|
allocHandler = new ALLOC_CACHE_HANDLER("COMPRESSION_CONTEXT",
|
|
&acConfig);
|
|
if (allocHandler == NULL)
|
|
{
|
|
return HRESULT_FROM_WIN32(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
static void Terminate()
|
|
{
|
|
if (allocHandler != NULL)
|
|
{
|
|
delete allocHandler;
|
|
}
|
|
}
|
|
|
|
void *operator new(
|
|
#if DBG
|
|
size_t size
|
|
#else
|
|
size_t
|
|
#endif
|
|
)
|
|
{
|
|
DBG_ASSERT(size == sizeof COMPRESSION_CONTEXT);
|
|
DBG_ASSERT(allocHandler != NULL);
|
|
return allocHandler->Alloc();
|
|
}
|
|
|
|
void operator delete(void *pCompressionContext)
|
|
{
|
|
DBG_ASSERT(pCompressionContext != NULL);
|
|
DBG_ASSERT(allocHandler != NULL);
|
|
DBG_REQUIRE(allocHandler->Free(pCompressionContext));
|
|
}
|
|
|
|
COMPRESSION_CONTEXT()
|
|
: m_pScheme (NULL),
|
|
m_fTransferChunkEncoded (FALSE),
|
|
m_pCompressionContext (NULL),
|
|
m_dwBytesInCurrentEncodedChunk (0),
|
|
m_encodedChunkState (IN_CHUNK_LENGTH),
|
|
m_fHeadersSent (FALSE),
|
|
m_fRequestIsHead (FALSE),
|
|
m_fOriginalBodyEmpty (TRUE)
|
|
{}
|
|
|
|
~COMPRESSION_CONTEXT()
|
|
{
|
|
if (m_pCompressionContext)
|
|
{
|
|
m_pScheme->m_pfnDestroyCompression(m_pCompressionContext);
|
|
m_pCompressionContext = NULL;
|
|
}
|
|
}
|
|
|
|
HRESULT ProcessEncodedChunkHeader();
|
|
|
|
HRESULT CalculateEncodedChunkByteCount();
|
|
|
|
VOID DeleteEncodedChunkExtension();
|
|
|
|
VOID IncrementPointerInULChunk(IN DWORD dwIncr = 1)
|
|
{
|
|
m_pbOrigData += dwIncr;
|
|
m_cbOrigData -= dwIncr;
|
|
}
|
|
|
|
COMPRESSION_SCHEME *m_pScheme;
|
|
|
|
//
|
|
// Is the original response chunk encoded?
|
|
//
|
|
BOOL m_fTransferChunkEncoded;
|
|
|
|
//
|
|
// If the original response is Chunk encoded, information about the
|
|
// current chunk in the response
|
|
//
|
|
DWORD m_dwBytesInCurrentEncodedChunk;
|
|
COMPRESS_CHUNK_STATE m_encodedChunkState;
|
|
|
|
//
|
|
// The context used by the compression routines
|
|
//
|
|
PVOID m_pCompressionContext;
|
|
|
|
//
|
|
// position in the original response
|
|
//
|
|
PBYTE m_pbOrigData;
|
|
DWORD m_cbOrigData;
|
|
|
|
static ALLOC_CACHE_HANDLER *allocHandler;
|
|
|
|
//
|
|
// Some members to keep track of HEAD request body suppression
|
|
//
|
|
BOOL m_fRequestIsHead;
|
|
BOOL m_fOriginalBodyEmpty;
|
|
|
|
//
|
|
// Has the end of response headers been seen?
|
|
//
|
|
BOOL m_fHeadersSent;
|
|
|
|
//
|
|
// A chunk's worth of data
|
|
//
|
|
BUFFER m_bufChunk;
|
|
};
|
|
|
|
class HTTP_COMPRESSION
|
|
{
|
|
public:
|
|
|
|
static HRESULT Initialize();
|
|
|
|
static VOID Terminate();
|
|
|
|
static HRESULT DoStaticFileCompression(IN W3_CONTEXT *pW3Context,
|
|
IN OUT W3_FILE_INFO **ppFileInfo,
|
|
OUT BOOL *pfDoCache);
|
|
|
|
static HRESULT OnSendResponse(
|
|
IN W3_CONTEXT *pW3Context);
|
|
|
|
static HRESULT DoDynamicCompression(
|
|
IN W3_CONTEXT *pW3Context,
|
|
IN BOOL fMoreData,
|
|
IN HTTP_FILTER_RAW_DATA * pRawData );
|
|
|
|
static BOOL QueryDoStaticCompression()
|
|
{
|
|
return sm_fDoStaticCompression;
|
|
}
|
|
|
|
static BOOL QueryDoDynamicCompression()
|
|
{
|
|
return sm_fDoDynamicCompression;
|
|
}
|
|
|
|
private:
|
|
|
|
static COMPRESSION_SCHEME *sm_pCompressionSchemes[MAX_SERVER_SCHEMES];
|
|
static DWORD sm_dwNumberOfSchemes;
|
|
static STRU *sm_pstrCompressionDirectory;
|
|
static STRA *sm_pstrCacheControlHeader;
|
|
static STRA *sm_pstrExpiresHeader;
|
|
static BOOL sm_fDoStaticCompression;
|
|
static BOOL sm_fDoDynamicCompression;
|
|
static BOOL sm_fDoOnDemandCompression;
|
|
static BOOL sm_fDoDiskSpaceLimiting;
|
|
static BOOL sm_fNoCompressionForHttp10;
|
|
static BOOL sm_fNoCompressionForProxies;
|
|
static BOOL sm_fNoCompressionForRange;
|
|
static BOOL sm_fSendCacheHeaders;
|
|
static DWORD sm_dwMaxDiskSpaceUsage;
|
|
static DWORD sm_dwIoBufferSize;
|
|
static DWORD sm_dwCompressionBufferSize;
|
|
static DWORD sm_dwMaxQueueLength;
|
|
static DWORD sm_dwFilesDeletedPerDiskFree;
|
|
static DWORD sm_dwMinFileSizeForCompression;
|
|
static PBYTE sm_pIoBuffer;
|
|
static PBYTE sm_pCompressionBuffer;
|
|
static CRITICAL_SECTION sm_CompressionDirectoryLock;
|
|
static DWORD sm_dwCurrentDiskSpaceUsage;
|
|
static BOOL sm_fCompressionVolumeIsFat;
|
|
static LIST_ENTRY sm_CompressionThreadWorkQueue;
|
|
static CRITICAL_SECTION sm_CompressionThreadLock;
|
|
static HANDLE sm_hThreadEvent;
|
|
static HANDLE sm_hCompressionThreadHandle;
|
|
static DWORD sm_dwCurrentQueueLength;
|
|
static COMP_INIT_STATUS sm_InitStatus;
|
|
static BOOL sm_fIsTerminating;
|
|
|
|
static HRESULT ReadMetadata(MB *pmb);
|
|
|
|
static HRESULT InitializeCompressionSchemes(MB *pmb);
|
|
|
|
static HRESULT InitializeCompressionDirectory();
|
|
|
|
static HRESULT InitializeCompressionThread();
|
|
|
|
static DWORD WINAPI CompressionThread(LPVOID);
|
|
|
|
static BOOL QueueWorkItem(
|
|
IN COMPRESSION_WORK_ITEM *WorkItem,
|
|
IN BOOL fOverrideMaxQueueLength,
|
|
IN BOOL fQueueAtHead);
|
|
|
|
static VOID FindMatchingSchemes(
|
|
IN CHAR * pszAcceptEncoding,
|
|
IN LPWSTR pszExtension,
|
|
IN COMPRESSION_TO_PERFORM performCompr,
|
|
OUT DWORD matchingSchemes[],
|
|
OUT DWORD *pdwClientCompressionCount);
|
|
|
|
static HRESULT ConvertPhysicalPathToCompressedPath(
|
|
IN COMPRESSION_SCHEME *scheme,
|
|
IN STRU *pstrPhysicalPath,
|
|
OUT STRU *pstrCompressedFileName);
|
|
|
|
static BOOL CheckForExistenceOfCompressedFile(
|
|
IN W3_FILE_INFO *pOrigFile,
|
|
IN STRU *pstrCompressedFileName,
|
|
OUT W3_FILE_INFO **ppCompFile,
|
|
IN BOOL fDeleteAllowed = TRUE);
|
|
|
|
static BOOL QueueCompressFile(
|
|
IN COMPRESSION_SCHEME *scheme,
|
|
IN W3_FILE_INFO *pFileInfo);
|
|
|
|
static VOID CompressFile(IN COMPRESSION_SCHEME *scheme,
|
|
IN W3_FILE_INFO *pFileInfo);
|
|
|
|
static VOID FreeDiskSpace();
|
|
|
|
static BOOL CompressAndWriteData(
|
|
IN COMPRESSION_SCHEME *scheme,
|
|
IN PBYTE InputBuffer,
|
|
IN DWORD BytesToCompress,
|
|
OUT PDWORD BytesWritten,
|
|
IN HANDLE hCompressedFile);
|
|
};
|
|
|
|
#endif _COMPRESSION_H_
|