2025-04-27 07:49:33 -04:00

303 lines
7.3 KiB
C++

/*++
Copyright (c) 2001 Microsoft Corporation
Module Name:
chunkflt.hxx
Abstract:
Contains a filter for encoding and decoding chunked transfers.
Contents:
BaseFilter
FILTER_LIST
ChunkDecodeContext
ChunkFilter
Author:
Oliver Wallace (oliverw) 13-Feb-2001
Revision History:
13-Feb-2001 oliverw
Created
--*/
// Base class meant for when additional filters will be available.
class BaseFilter
{
public:
virtual HRESULT Reset(DWORD_PTR dwContext)
{
UNREFERENCED_PARAMETER(dwContext);
return E_NOTIMPL;
}
virtual HRESULT
Decode(
IN DWORD_PTR dwContext,
IN OUT LPBYTE pInBuffer,
IN DWORD dwInBufSize,
IN OUT LPBYTE *ppOutBuffer,
IN OUT LPDWORD pdwOutBufSize,
OUT LPDWORD pdwBytesRead,
OUT LPDWORD pdwBytesWritten
)
{
UNREFERENCED_PARAMETER(dwContext);
UNREFERENCED_PARAMETER(pInBuffer);
UNREFERENCED_PARAMETER(dwInBufSize);
UNREFERENCED_PARAMETER(ppOutBuffer);
UNREFERENCED_PARAMETER(pdwOutBufSize);
UNREFERENCED_PARAMETER(pdwBytesRead);
UNREFERENCED_PARAMETER(pdwBytesWritten);
return E_NOTIMPL;
}
virtual HRESULT
Encode(
DWORD_PTR dwContext,
IN OUT LPBYTE pInBuffer,
IN DWORD dwInBufSize,
IN OUT LPBYTE *ppOutBuffer,
IN OUT LPDWORD pdwOutBufSize,
OUT LPDWORD pdwBytesRead,
OUT LPDWORD pdwBytesWritten
)
{
UNREFERENCED_PARAMETER(dwContext);
UNREFERENCED_PARAMETER(pInBuffer);
UNREFERENCED_PARAMETER(dwInBufSize);
UNREFERENCED_PARAMETER(ppOutBuffer);
UNREFERENCED_PARAMETER(pdwOutBufSize);
UNREFERENCED_PARAMETER(pdwBytesRead);
UNREFERENCED_PARAMETER(pdwBytesWritten);
return E_NOTIMPL;
}
virtual HRESULT RegisterContext(OUT DWORD_PTR *pdwContext)
{
UNREFERENCED_PARAMETER(pdwContext);
return E_NOTIMPL;
}
virtual HRESULT UnregisterContext(IN DWORD_PTR dwContext)
{
UNREFERENCED_PARAMETER(dwContext);
return E_NOTIMPL;
}
virtual BOOL IsFinished(IN DWORD_PTR dwContext)
{
UNREFERENCED_PARAMETER(dwContext);
return FALSE;
}
};
typedef struct FILTER_LIST_ENTRY
{
DWORD_PTR dwContext; // Registered context associated with pFilter
BaseFilter *pFilter; // Data Filter used to encode/decode dwContext
FILTER_LIST_ENTRY *pNext;
}
FILTER_LIST_ENTRY, * LPFILTER_LIST_ENTRY;
class FILTER_LIST
{
/*++
Class Description:
The FILTER_LIST class defines the data filter list used to encode/decode
data when sending/receiving data.
Post v5, this will need some extensions:
- Make this a priority list to accommodate mroe flexible encoding order.
- Implement Encode method to process upload filters once support is added.
- Add smartness to Encode/Decode methods to buffer data.
--*/
public:
FILTER_LIST()
{
_pFilterEntry = NULL;
_uFilterCount = 0;
}
~FILTER_LIST()
{
ClearList();
}
// Always inserts as the beginning of the list
BOOL
Insert(IN BaseFilter *pFilter, IN DWORD_PTR dwContext);
VOID
ClearList();
DWORD
Decode(
IN OUT LPBYTE pInBuffer,
IN DWORD dwInBufSize,
IN OUT LPBYTE *ppOutBuffer,
IN OUT LPDWORD pdwOutBufSize,
OUT LPDWORD pdwBytesRead,
OUT LPDWORD pdwBytesWritten
);
// Right now, there should never be more than just the chunk filter.
BOOL IsFinished()
{
if (_pFilterEntry)
return _pFilterEntry->pFilter->IsFinished(_pFilterEntry->dwContext);
else
return FALSE;
}
private:
LPFILTER_LIST_ENTRY _pFilterEntry;
UINT _uFilterCount;
};
// Chunk filter state table, data and object prototypes.
// Various token flags to describe the current byte being parsed.
//
// NOTE: Make sure you update the global table in chunkflt.cxx
// if this list is modified.
typedef enum
{
CHUNK_TOKEN_DIGIT = 0,
CHUNK_TOKEN_CR,
CHUNK_TOKEN_LF,
CHUNK_TOKEN_COLON,
CHUNK_TOKEN_DATA,
CHUNK_TOKEN_LAST = CHUNK_TOKEN_DATA
} CHUNK_TOKEN_VALUE;
// NOTE: Do NOT update this without updating the table in chunkflt.cxx
// which maps tokens for the current state to the next state.
typedef enum
{
CHUNK_DECODE_STATE_START = 0,
CHUNK_DECODE_STATE_SIZE,
CHUNK_DECODE_STATE_SIZE_CRLF,
CHUNK_DECODE_STATE_EXT,
CHUNK_DECODE_STATE_DATA,
CHUNK_DECODE_STATE_DATA_CRLF,
CHUNK_DECODE_STATE_FOOTER_NAME,
CHUNK_DECODE_STATE_FOOTER_VALUE,
CHUNK_DECODE_STATE_FOOTER_CRLF,
CHUNK_DECODE_STATE_FINAL_CRLF,
CHUNK_DECODE_STATE_QUOTED_DATA,
CHUNK_DECODE_STATE_ERROR,
CHUNK_DECODE_STATE_FINISHED,
CHUNK_DECODE_STATE_LAST = CHUNK_DECODE_STATE_FINISHED
} CHUNK_DECODE_STATE, *LPCHUNK_DECODE_STATE;
class ChunkDecodeContext
{
private:
CHUNK_DECODE_STATE m_eDecodeState;
CHUNK_DECODE_STATE m_eQuoteExitState;
DWORD m_dwParsedSize;
friend class ChunkFilter;
public:
ChunkDecodeContext() { Reset(); }
// TODO: Consider subclassing contexts because they share common
// properties/methods that could be virtual (e.g. Get/SetState).
CHUNK_DECODE_STATE
GetState()
{
return m_eDecodeState;
}
VOID
SetState(CHUNK_DECODE_STATE eNewState)
{
m_eDecodeState = eNewState;
}
VOID SetStateEnterQuotedData()
{
m_eQuoteExitState = m_eDecodeState;
SetState(CHUNK_DECODE_STATE_QUOTED_DATA);
}
VOID SetStateLeaveQuotedData()
{
SetState(m_eQuoteExitState);
m_eQuoteExitState = CHUNK_DECODE_STATE_ERROR;
}
VOID Reset()
{
m_eDecodeState = CHUNK_DECODE_STATE_START;
m_eQuoteExitState = CHUNK_DECODE_STATE_ERROR;
m_dwParsedSize = 0;
}
};
class ChunkFilter : public BaseFilter
{
public:
// TODO: Provide an init method that is chunked-specific
// (e.g. set size for chunked uploads)
HRESULT Reset(DWORD_PTR dwContext);
HRESULT
Decode(
IN DWORD_PTR dwContext,
IN OUT LPBYTE pInBuffer,
IN DWORD dwInBufSize,
IN OUT LPBYTE *ppOutBuffer,
IN OUT LPDWORD pdwOutBufSize,
OUT LPDWORD pdwBytesRead,
OUT LPDWORD pdwBytesWritten
);
HRESULT
Encode(
IN DWORD_PTR dwContext,
IN OUT LPBYTE pInBuffer,
IN DWORD dwInBufSize,
OUT LPBYTE *ppOutBuffer,
OUT LPDWORD pdwOutBufSize,
OUT LPDWORD pdwBytesRead,
OUT LPDWORD pdwBytesWritten
);
HRESULT RegisterContext(OUT DWORD_PTR *pdwContext);
HRESULT UnregisterContext(IN DWORD_PTR dwContext);
BOOL
IsFinished(IN DWORD_PTR dwContext)
{
if (dwContext)
return ((reinterpret_cast<ChunkDecodeContext *>(dwContext))->GetState() ==
CHUNK_DECODE_STATE_FINISHED ? TRUE : FALSE);
else
return FALSE;
}
};