72 for (
size_t i = 0; i < a_Size; i++)
87 m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 +
static_cast<decltype(m_ChunkDataLengthLeft)
>(a_Data[i] -
'0');
97 m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 +
static_cast<decltype(m_ChunkDataLengthLeft)
>(a_Data[i] -
'a' + 10);
107 m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 +
static_cast<decltype(m_ChunkDataLengthLeft)
>(a_Data[i] -
'A' + 10);
122 Error(
Printf(
"Invalid character in chunk length line: 0x%x", a_Data[i]));
123 return AString::npos;
138 for (
size_t i = 0; i < a_Size; i++)
152 Error(
Printf(
"Invalid character in chunk length line: 0x%x", a_Data[i]));
153 return AString::npos;
173 if (a_Data[0] ==
'\n')
175 if (m_ChunkDataLengthLeft == 0)
185 Error(
Printf(
"Invalid character past chunk length's CR: 0x%x", a_Data[0]));
186 return AString::npos;
194 ASSERT(m_ChunkDataLengthLeft > 0);
195 auto bytes = std::min(a_Size, m_ChunkDataLengthLeft);
196 m_ChunkDataLengthLeft -= bytes;
198 if (m_ChunkDataLengthLeft == 0)
216 if (a_Data[0] ==
'\r')
221 Error(
Printf(
"Invalid character past chunk data: 0x%x", a_Data[0]));
222 return AString::npos;
238 if (a_Data[0] ==
'\n')
243 Error(
Printf(
"Invalid character past chunk data's CR: 0x%x", a_Data[0]));
244 return AString::npos;
253 auto res = m_TrailerParser.
Parse(a_Data, a_Size);
254 if (res == AString::npos)
256 Error(
"Error while parsing the trailer");
258 if ((res < a_Size) || !m_TrailerParser.
IsInHeaders())
268 virtual size_t Parse(
const char * a_Data,
size_t a_Size)
override 270 while ((a_Size > 0) && (m_State !=
psFinished))
284 if (consumed == AString::npos)
286 return AString::npos;
298 Error(
Printf(
"ChunkedTransferEncoding: Finish signal received before the data stream ended (state: %d)", m_State));
326 m_BytesLeft(a_ContentLength)
336 virtual size_t Parse(
const char * a_Data,
size_t a_Size)
override 338 auto size = std::min(a_Size, m_BytesLeft);
344 if (m_BytesLeft == 0)
348 return a_Size - size;
373 const AString & a_TransferEncoding,
374 size_t a_ContentLength
377 if (a_TransferEncoding ==
"chunked")
379 return std::make_shared<cChunkedTEParser>(a_Callbacks);
381 if (a_TransferEncoding ==
"identity")
383 return std::make_shared<cIdentityTEParser>(a_Callbacks, a_ContentLength);
385 if (a_TransferEncoding.empty())
387 return std::make_shared<cIdentityTEParser>(a_Callbacks, a_ContentLength);
size_t ParseChunkLength(const char *a_Data, size_t a_Size)
Parses the incoming data, the current state is psChunkLength.
virtual size_t Parse(const char *a_Data, size_t a_Size) override
Parses the incoming data and calls the appropriate callbacks.
Received an empty chunk, parsing the trailer (through the envelope parser)
size_t ParseChunkData(const char *a_Data, size_t a_Size)
Consumes as much chunk data from the input as possible.
virtual void OnBodyFinished(void)=0
Called when the entire body has been reported by OnBodyData().
size_t m_ChunkDataLengthLeft
Number of bytes that still belong to the chunk currently being parsed.
cTransferEncodingParser Super
size_t Parse(const char *a_Data, size_t a_Size)
Parses the incoming data.
void Error(const AString &a_ErrorMsg)
Calls the OnError callback and sets parser state to finished.
Parsing the chunk length hex number.
virtual void OnBodyData(const void *a_Data, size_t a_Size)=0
Called for each chunk of the incoming body data.
Skipping the extra CR character after chunk data.
size_t ParseChunkDataCR(const char *a_Data, size_t a_Size)
Parses the incoming data, the current state is psChunkDataCR.
bool IsInHeaders(void) const
Returns true if more input is expected for the envelope header.
size_t ParseChunkLengthTrailer(const char *a_Data, size_t a_Size)
Parses the incoming data, the current state is psChunkLengthTrailer.
virtual void Finish(void) override
To be called when the stream is terminated from the source (connection closed).
size_t m_BytesLeft
How many bytes of content are left before the message ends.
The LF character after the CR character terminating the chunk length.
virtual void OnHeaderLine(const AString &a_Key, const AString &a_Value) override
Called when a full header line is parsed.
size_t ParseChunkDataLF(const char *a_Data, size_t a_Size)
Parses the incoming data, the current state is psChunkDataCR.
size_t ParseChunkLengthLF(const char *a_Data, size_t a_Size)
Parses the incoming data, the current state is psChunkLengthLF.
virtual void Finish(void) override
To be called when the stream is terminated from the source (connection closed).
virtual void OnError(const AString &a_ErrorDescription)=0
Called when an error has occured while parsing.
AString & Printf(AString &str, const char *format, fmt::ArgList args)
Output the formatted text into the string.
static cTransferEncodingParserPtr Create(cCallbacks &a_Callbacks, const AString &a_TransferEncoding, size_t a_ContentLength)
Creates a new parser for the specified encoding.
cEnvelopeParser m_TrailerParser
The parser used for the last (empty) chunk's trailer data.
cCallbacks & m_Callbacks
The callbacks used to report progress.
virtual size_t Parse(const char *a_Data, size_t a_Size) override
Parses the incoming data and calls the appropriate callbacks.
Skipping the extra LF character after chunk data.
The parser has finished parsing, either successfully or with an error.
Any trailer (chunk extension) specified after the chunk length.
cTransferEncodingParser Super
cIdentityTEParser(cCallbacks &a_Callbacks, size_t a_ContentLength)
size_t ParseTrailer(const char *a_Data, size_t a_Size)
Parses the incoming data, the current state is psChunkDataCR.
std::shared_ptr< cTransferEncodingParser > cTransferEncodingParserPtr
eState m_State
The current state of the parser (parsing chunk length / chunk data).
cChunkedTEParser(Super::cCallbacks &a_Callbacks)
Used as both the interface that all the parsers share and the (static) factory creating such parsers...