summaryrefslogtreecommitdiffstats
path: root/src/HTTPServer/TransferEncodingParser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/HTTPServer/TransferEncodingParser.cpp')
-rw-r--r--src/HTTPServer/TransferEncodingParser.cpp132
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;
+}
+
+
+
+