diff options
Diffstat (limited to '')
-rw-r--r-- | src/HTTPServer/TransferEncodingParser.cpp | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/HTTPServer/TransferEncodingParser.cpp b/src/HTTPServer/TransferEncodingParser.cpp new file mode 100644 index 000000000..8b703fd42 --- /dev/null +++ b/src/HTTPServer/TransferEncodingParser.cpp @@ -0,0 +1,132 @@ + +// TransferEncodingParser.cpp + +// Implements the cTransferEncodingParser class and its descendants representing the parser for the various transfer encodings (chunked etc.) + +#include "Globals.h" +#include "TransferEncodingParser.h" + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cChunkedTEParser: + +class cChunkedTEParser: + public cTransferEncodingParser +{ + typedef cTransferEncodingParser Super; + +public: + cChunkedTEParser(cCallbacks & a_Callbacks): + Super(a_Callbacks), + m_IsFinished(false) + { + } + + +protected: + + /** True if the datastream has finished (zero-length chunk received). */ + bool m_IsFinished; + + + // cTransferEncodingParser overrides: + virtual size_t Parse(const char * a_Data, size_t a_Size) override + { + // TODO + m_Callbacks.OnError("cChunkedTEParser not implemented yet"); + return AString::npos; + } + + virtual void Finish(void) override + { + if (!m_IsFinished) + { + m_Callbacks.OnError("ChunkedTransferEncoding: Finish signal received before the data stream ended"); + } + m_IsFinished = true; + } +}; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cIdentityTEParser: + +class cIdentityTEParser: + public cTransferEncodingParser +{ + typedef cTransferEncodingParser Super; + +public: + cIdentityTEParser(cCallbacks & a_Callbacks, size_t a_ContentLength): + Super(a_Callbacks), + m_BytesLeft(a_ContentLength) + { + } + + +protected: + /** How many bytes of content are left before the message ends. */ + size_t m_BytesLeft; + + // cTransferEncodingParser overrides: + virtual size_t Parse(const char * a_Data, size_t a_Size) override + { + auto size = std::min(a_Size, m_BytesLeft); + if (size > 0) + { + m_Callbacks.OnBodyData(a_Data, size); + } + m_BytesLeft -= size; + if (m_BytesLeft == 0) + { + m_Callbacks.OnBodyFinished(); + } + return a_Size - size; + } + + virtual void Finish(void) override + { + if (m_BytesLeft > 0) + { + m_Callbacks.OnError("IdentityTransferEncoding: body was truncated"); + } + else + { + // BodyFinished has already been called, just bail out + } + } +}; + + + + + +//////////////////////////////////////////////////////////////////////////////// +// cTransferEncodingParser: + +cTransferEncodingParserPtr cTransferEncodingParser::Create( + cCallbacks & a_Callbacks, + const AString & a_TransferEncoding, + size_t a_ContentLength +) +{ + if (a_TransferEncoding == "chunked") + { + return std::make_shared<cChunkedTEParser>(a_Callbacks); + } + if (a_TransferEncoding.empty()) + { + return std::make_shared<cIdentityTEParser>(a_Callbacks, a_ContentLength); + } + return nullptr; +} + + + + |