summaryrefslogtreecommitdiffstats
path: root/src/HTTP
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/HTTP/CMakeLists.txt (renamed from src/HTTPServer/CMakeLists.txt)0
-rw-r--r--src/HTTP/EnvelopeParser.cpp (renamed from src/HTTPServer/EnvelopeParser.cpp)0
-rw-r--r--src/HTTP/EnvelopeParser.h (renamed from src/HTTPServer/EnvelopeParser.h)0
-rw-r--r--src/HTTP/HTTPFormParser.cpp (renamed from src/HTTPServer/HTTPFormParser.cpp)0
-rw-r--r--src/HTTP/HTTPFormParser.h (renamed from src/HTTPServer/HTTPFormParser.h)0
-rw-r--r--src/HTTP/HTTPMessage.cpp (renamed from src/HTTPServer/HTTPMessage.cpp)0
-rw-r--r--src/HTTP/HTTPMessage.h (renamed from src/HTTPServer/HTTPMessage.h)0
-rw-r--r--src/HTTP/HTTPRequestParser.cpp (renamed from src/HTTPServer/HTTPRequestParser.cpp)0
-rw-r--r--src/HTTP/HTTPRequestParser.h (renamed from src/HTTPServer/HTTPRequestParser.h)0
-rw-r--r--src/HTTP/HTTPResponseParser.cpp (renamed from src/HTTPServer/HTTPResponseParser.cpp)8
-rw-r--r--src/HTTP/HTTPResponseParser.h (renamed from src/HTTPServer/HTTPResponseParser.h)0
-rw-r--r--src/HTTP/HTTPServer.cpp (renamed from src/HTTPServer/HTTPServer.cpp)0
-rw-r--r--src/HTTP/HTTPServer.h (renamed from src/HTTPServer/HTTPServer.h)0
-rw-r--r--src/HTTP/HTTPServerConnection.cpp (renamed from src/HTTPServer/HTTPServerConnection.cpp)0
-rw-r--r--src/HTTP/HTTPServerConnection.h (renamed from src/HTTPServer/HTTPServerConnection.h)0
-rw-r--r--src/HTTP/MultipartParser.cpp (renamed from src/HTTPServer/MultipartParser.cpp)0
-rw-r--r--src/HTTP/MultipartParser.h (renamed from src/HTTPServer/MultipartParser.h)0
-rw-r--r--src/HTTP/NameValueParser.cpp (renamed from src/HTTPServer/NameValueParser.cpp)0
-rw-r--r--src/HTTP/NameValueParser.h (renamed from src/HTTPServer/NameValueParser.h)0
-rw-r--r--src/HTTP/SslHTTPServerConnection.cpp (renamed from src/HTTPServer/SslHTTPServerConnection.cpp)0
-rw-r--r--src/HTTP/SslHTTPServerConnection.h (renamed from src/HTTPServer/SslHTTPServerConnection.h)0
-rw-r--r--src/HTTP/TransferEncodingParser.cpp393
-rw-r--r--src/HTTP/TransferEncodingParser.h (renamed from src/HTTPServer/TransferEncodingParser.h)0
-rw-r--r--src/HTTP/UrlParser.cpp (renamed from src/HTTPServer/UrlParser.cpp)0
-rw-r--r--src/HTTP/UrlParser.h (renamed from src/HTTPServer/UrlParser.h)0
-rw-r--r--src/HTTPServer/TransferEncodingParser.cpp132
26 files changed, 400 insertions, 133 deletions
diff --git a/src/HTTPServer/CMakeLists.txt b/src/HTTP/CMakeLists.txt
index 4597f6eda..4597f6eda 100644
--- a/src/HTTPServer/CMakeLists.txt
+++ b/src/HTTP/CMakeLists.txt
diff --git a/src/HTTPServer/EnvelopeParser.cpp b/src/HTTP/EnvelopeParser.cpp
index 407e9dcfc..407e9dcfc 100644
--- a/src/HTTPServer/EnvelopeParser.cpp
+++ b/src/HTTP/EnvelopeParser.cpp
diff --git a/src/HTTPServer/EnvelopeParser.h b/src/HTTP/EnvelopeParser.h
index 2fa930539..2fa930539 100644
--- a/src/HTTPServer/EnvelopeParser.h
+++ b/src/HTTP/EnvelopeParser.h
diff --git a/src/HTTPServer/HTTPFormParser.cpp b/src/HTTP/HTTPFormParser.cpp
index ddf87f540..ddf87f540 100644
--- a/src/HTTPServer/HTTPFormParser.cpp
+++ b/src/HTTP/HTTPFormParser.cpp
diff --git a/src/HTTPServer/HTTPFormParser.h b/src/HTTP/HTTPFormParser.h
index fde6df696..fde6df696 100644
--- a/src/HTTPServer/HTTPFormParser.h
+++ b/src/HTTP/HTTPFormParser.h
diff --git a/src/HTTPServer/HTTPMessage.cpp b/src/HTTP/HTTPMessage.cpp
index ca63397dd..ca63397dd 100644
--- a/src/HTTPServer/HTTPMessage.cpp
+++ b/src/HTTP/HTTPMessage.cpp
diff --git a/src/HTTPServer/HTTPMessage.h b/src/HTTP/HTTPMessage.h
index 50b1f9e19..50b1f9e19 100644
--- a/src/HTTPServer/HTTPMessage.h
+++ b/src/HTTP/HTTPMessage.h
diff --git a/src/HTTPServer/HTTPRequestParser.cpp b/src/HTTP/HTTPRequestParser.cpp
index 9c60c6053..9c60c6053 100644
--- a/src/HTTPServer/HTTPRequestParser.cpp
+++ b/src/HTTP/HTTPRequestParser.cpp
diff --git a/src/HTTPServer/HTTPRequestParser.h b/src/HTTP/HTTPRequestParser.h
index f3d3add91..f3d3add91 100644
--- a/src/HTTPServer/HTTPRequestParser.h
+++ b/src/HTTP/HTTPRequestParser.h
diff --git a/src/HTTPServer/HTTPResponseParser.cpp b/src/HTTP/HTTPResponseParser.cpp
index b3ce9dab6..9411208e2 100644
--- a/src/HTTPServer/HTTPResponseParser.cpp
+++ b/src/HTTP/HTTPResponseParser.cpp
@@ -13,6 +13,7 @@
cHTTPResponseParser::cHTTPResponseParser(cHTTPResponseParser::cCallbacks & a_Callbacks):
Super(mkResponse),
m_Callbacks(a_Callbacks),
+ m_HasHadError(false),
m_IsInHeaders(true),
m_IsFinished(false),
m_EnvelopeParser(*this)
@@ -56,7 +57,7 @@ size_t cHTTPResponseParser::Parse(const char * a_Data, size_t a_Size)
if (!m_Buffer.empty())
{
// Headers finished and there's still data left in the buffer, process it as message body:
- m_IsInHeaders = false;
+ HeadersFinished();
return ParseBody(m_Buffer.data(), m_Buffer.size());
}
return 0;
@@ -132,6 +133,10 @@ void cHTTPResponseParser::HeadersFinished(void)
{
m_TransferEncodingParser = cTransferEncodingParser::Create(*this, "identity", m_ContentLength);
}
+ else
+ {
+ m_TransferEncodingParser = cTransferEncodingParser::Create(*this, transferEncoding->second, m_ContentLength);
+ }
}
@@ -169,6 +174,7 @@ void cHTTPResponseParser::OnBodyData(const void * a_Data, size_t a_Size)
void cHTTPResponseParser::OnBodyFinished(void)
{
+ m_IsFinished = true;
m_Callbacks.OnBodyFinished();
}
diff --git a/src/HTTPServer/HTTPResponseParser.h b/src/HTTP/HTTPResponseParser.h
index 19652ccef..19652ccef 100644
--- a/src/HTTPServer/HTTPResponseParser.h
+++ b/src/HTTP/HTTPResponseParser.h
diff --git a/src/HTTPServer/HTTPServer.cpp b/src/HTTP/HTTPServer.cpp
index 741f5f1c5..741f5f1c5 100644
--- a/src/HTTPServer/HTTPServer.cpp
+++ b/src/HTTP/HTTPServer.cpp
diff --git a/src/HTTPServer/HTTPServer.h b/src/HTTP/HTTPServer.h
index 15202a50e..15202a50e 100644
--- a/src/HTTPServer/HTTPServer.h
+++ b/src/HTTP/HTTPServer.h
diff --git a/src/HTTPServer/HTTPServerConnection.cpp b/src/HTTP/HTTPServerConnection.cpp
index 0ee9f3ce7..0ee9f3ce7 100644
--- a/src/HTTPServer/HTTPServerConnection.cpp
+++ b/src/HTTP/HTTPServerConnection.cpp
diff --git a/src/HTTPServer/HTTPServerConnection.h b/src/HTTP/HTTPServerConnection.h
index af2abb73f..af2abb73f 100644
--- a/src/HTTPServer/HTTPServerConnection.h
+++ b/src/HTTP/HTTPServerConnection.h
diff --git a/src/HTTPServer/MultipartParser.cpp b/src/HTTP/MultipartParser.cpp
index 09f4fd02a..09f4fd02a 100644
--- a/src/HTTPServer/MultipartParser.cpp
+++ b/src/HTTP/MultipartParser.cpp
diff --git a/src/HTTPServer/MultipartParser.h b/src/HTTP/MultipartParser.h
index 4f20b2bed..4f20b2bed 100644
--- a/src/HTTPServer/MultipartParser.h
+++ b/src/HTTP/MultipartParser.h
diff --git a/src/HTTPServer/NameValueParser.cpp b/src/HTTP/NameValueParser.cpp
index f759c4d21..f759c4d21 100644
--- a/src/HTTPServer/NameValueParser.cpp
+++ b/src/HTTP/NameValueParser.cpp
diff --git a/src/HTTPServer/NameValueParser.h b/src/HTTP/NameValueParser.h
index e205079db..e205079db 100644
--- a/src/HTTPServer/NameValueParser.h
+++ b/src/HTTP/NameValueParser.h
diff --git a/src/HTTPServer/SslHTTPServerConnection.cpp b/src/HTTP/SslHTTPServerConnection.cpp
index 547e6de3a..547e6de3a 100644
--- a/src/HTTPServer/SslHTTPServerConnection.cpp
+++ b/src/HTTP/SslHTTPServerConnection.cpp
diff --git a/src/HTTPServer/SslHTTPServerConnection.h b/src/HTTP/SslHTTPServerConnection.h
index 6032a2bd0..6032a2bd0 100644
--- a/src/HTTPServer/SslHTTPServerConnection.h
+++ b/src/HTTP/SslHTTPServerConnection.h
diff --git a/src/HTTP/TransferEncodingParser.cpp b/src/HTTP/TransferEncodingParser.cpp
new file mode 100644
index 000000000..d95b3d08e
--- /dev/null
+++ b/src/HTTP/TransferEncodingParser.cpp
@@ -0,0 +1,393 @@
+
+// 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"
+#include "EnvelopeParser.h"
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// cChunkedTEParser:
+
+class cChunkedTEParser:
+ public cTransferEncodingParser,
+ public cEnvelopeParser::cCallbacks
+{
+ typedef cTransferEncodingParser Super;
+
+public:
+ cChunkedTEParser(Super::cCallbacks & a_Callbacks):
+ Super(a_Callbacks),
+ m_State(psChunkLength),
+ m_ChunkDataLengthLeft(0),
+ m_TrailerParser(*this)
+ {
+ }
+
+
+protected:
+ enum eState
+ {
+ psChunkLength, ///< Parsing the chunk length hex number
+ psChunkLengthTrailer, ///< Any trailer (chunk extension) specified after the chunk length
+ psChunkLengthLF, ///< The LF character after the CR character terminating the chunk length
+ psChunkData, ///< Relaying chunk data
+ psChunkDataCR, ///< Skipping the extra CR character after chunk data
+ psChunkDataLF, ///< Skipping the extra LF character after chunk data
+ psTrailer, ///< Received an empty chunk, parsing the trailer (through the envelope parser)
+ psFinished, ///< The parser has finished parsing, either successfully or with an error
+ };
+
+ /** The current state of the parser (parsing chunk length / chunk data). */
+ eState m_State;
+
+ /** Number of bytes that still belong to the chunk currently being parsed.
+ When in psChunkLength, the value is the currently parsed length digits. */
+ size_t m_ChunkDataLengthLeft;
+
+ cEnvelopeParser m_TrailerParser;
+
+
+ /** Calls the OnError callback and sets parser state to finished. */
+ void Error(const AString & a_ErrorMsg)
+ {
+ m_State = psFinished;
+ m_Callbacks.OnError(a_ErrorMsg);
+ }
+
+
+ /** Parses the incoming data, the current state is psChunkLength.
+ Stops parsing when either the chunk length has been read, or there is no more data in the input.
+ Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */
+ size_t ParseChunkLength(const char * a_Data, size_t a_Size)
+ {
+ // Expected input: <hexnumber>[;<trailer>]<CR><LF>
+ // Only the hexnumber is parsed into m_ChunkDataLengthLeft, the rest is postponed into psChunkLengthTrailer or psChunkLengthLF
+ for (size_t i = 0; i < a_Size; i++)
+ {
+ switch (a_Data[i])
+ {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ {
+ m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 + static_cast<decltype(m_ChunkDataLengthLeft)>(a_Data[i] - '0');
+ break;
+ }
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ {
+ m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 + static_cast<decltype(m_ChunkDataLengthLeft)>(a_Data[i] - 'a' + 10);
+ break;
+ }
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ {
+ m_ChunkDataLengthLeft = m_ChunkDataLengthLeft * 16 + static_cast<decltype(m_ChunkDataLengthLeft)>(a_Data[i] - 'A' + 10);
+ break;
+ }
+ case '\r':
+ {
+ m_State = psChunkLengthLF;
+ return i + 1;
+ }
+ case ';':
+ {
+ m_State = psChunkLengthTrailer;
+ return i + 1;
+ }
+ default:
+ {
+ Error(Printf("Invalid character in chunk length line: 0x%x", a_Data[i]));
+ return AString::npos;
+ }
+ } // switch (a_Data[i])
+ } // for i - a_Data[]
+ return a_Size;
+ }
+
+
+ /** Parses the incoming data, the current state is psChunkLengthTrailer.
+ Stops parsing when either the chunk length trailer has been read, or there is no more data in the input.
+ Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */
+ size_t ParseChunkLengthTrailer(const char * a_Data, size_t a_Size)
+ {
+ // Expected input: <trailer><CR><LF>
+ // The LF itself is not parsed, it is instead postponed into psChunkLengthLF
+ for (size_t i = 0; i < a_Size; i++)
+ {
+ switch (a_Data[i])
+ {
+ case '\r':
+ {
+ m_State = psChunkLengthLF;
+ return i;
+ }
+ default:
+ {
+ if (a_Data[i] < 32)
+ {
+ // Only printable characters are allowed in the trailer
+ Error(Printf("Invalid character in chunk length line: 0x%x", a_Data[i]));
+ return AString::npos;
+ }
+ }
+ } // switch (a_Data[i])
+ } // for i - a_Data[]
+ return a_Size;
+ }
+
+
+ /** Parses the incoming data, the current state is psChunkLengthLF.
+ Only the LF character is expected, if found, moves to psChunkData, otherwise issues an error.
+ If the chunk length that just finished reading is equal to 0, signals the end of stream (via psTrailer).
+ Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */
+ size_t ParseChunkLengthLF(const char * a_Data, size_t a_Size)
+ {
+ // Expected input: <LF>
+ if (a_Size == 0)
+ {
+ return 0;
+ }
+ if (a_Data[0] == '\n')
+ {
+ if (m_ChunkDataLengthLeft == 0)
+ {
+ m_State = psTrailer;
+ }
+ else
+ {
+ m_State = psChunkData;
+ }
+ return 1;
+ }
+ Error(Printf("Invalid character past chunk length's CR: 0x%x", a_Data[0]));
+ return AString::npos;
+ }
+
+
+ /** Consumes as much chunk data from the input as possible.
+ Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error() handler). */
+ size_t ParseChunkData(const char * a_Data, size_t a_Size)
+ {
+ ASSERT(m_ChunkDataLengthLeft > 0);
+ auto bytes = std::min(a_Size, m_ChunkDataLengthLeft);
+ m_ChunkDataLengthLeft -= bytes;
+ m_Callbacks.OnBodyData(a_Data, bytes);
+ if (m_ChunkDataLengthLeft == 0)
+ {
+ m_State = psChunkDataCR;
+ }
+ return bytes;
+ }
+
+
+ /** Parses the incoming data, the current state is psChunkDataCR.
+ Only the CR character is expected, if found, moves to psChunkDataLF, otherwise issues an error.
+ Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */
+ size_t ParseChunkDataCR(const char * a_Data, size_t a_Size)
+ {
+ // Expected input: <CR>
+ if (a_Size == 0)
+ {
+ return 0;
+ }
+ if (a_Data[0] == '\r')
+ {
+ m_State = psChunkDataLF;
+ return 1;
+ }
+ Error(Printf("Invalid character past chunk data: 0x%x", a_Data[0]));
+ return AString::npos;
+ }
+
+
+
+
+ /** Parses the incoming data, the current state is psChunkDataCR.
+ Only the CR character is expected, if found, moves to psChunkDataLF, otherwise issues an error.
+ Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */
+ size_t ParseChunkDataLF(const char * a_Data, size_t a_Size)
+ {
+ // Expected input: <LF>
+ if (a_Size == 0)
+ {
+ return 0;
+ }
+ if (a_Data[0] == '\n')
+ {
+ m_State = psChunkLength;
+ return 1;
+ }
+ Error(Printf("Invalid character past chunk data's CR: 0x%x", a_Data[0]));
+ return AString::npos;
+ }
+
+
+ /** Parses the incoming data, the current state is psChunkDataCR.
+ The trailer is normally a set of "Header: Value" lines, terminated by an empty line. Use the m_TrailerParser for that.
+ Returns the number of bytes consumed from the input, or AString::npos on error (calls the Error handler). */
+ size_t ParseTrailer(const char * a_Data, size_t a_Size)
+ {
+ auto res = m_TrailerParser.Parse(a_Data, a_Size);
+ if (res == AString::npos)
+ {
+ Error("Error while parsing the trailer");
+ }
+ if ((res < a_Size) || !m_TrailerParser.IsInHeaders())
+ {
+ m_Callbacks.OnBodyFinished();
+ m_State = psFinished;
+ }
+ return res;
+ }
+
+
+ // cTransferEncodingParser overrides:
+ virtual size_t Parse(const char * a_Data, size_t a_Size) override
+ {
+ while ((a_Size > 0) && (m_State != psFinished))
+ {
+ size_t consumed = 0;
+ switch (m_State)
+ {
+ case psChunkLength: consumed = ParseChunkLength (a_Data, a_Size); break;
+ case psChunkLengthTrailer: consumed = ParseChunkLengthTrailer(a_Data, a_Size); break;
+ case psChunkLengthLF: consumed = ParseChunkLengthLF (a_Data, a_Size); break;
+ case psChunkData: consumed = ParseChunkData (a_Data, a_Size); break;
+ case psChunkDataCR: consumed = ParseChunkDataCR (a_Data, a_Size); break;
+ case psChunkDataLF: consumed = ParseChunkDataLF (a_Data, a_Size); break;
+ case psTrailer: consumed = ParseTrailer (a_Data, a_Size); break;
+ case psFinished: consumed = 0; break; // Not supposed to happen, but Clang complains without it
+ }
+ if (consumed == AString::npos)
+ {
+ return AString::npos;
+ }
+ a_Data += consumed;
+ a_Size -= consumed;
+ }
+ return a_Size;
+ }
+
+ virtual void Finish(void) override
+ {
+ if (m_State != psFinished)
+ {
+ Error(Printf("ChunkedTransferEncoding: Finish signal received before the data stream ended (state: %d)", m_State));
+ }
+ m_State = psFinished;
+ }
+
+
+ // cEnvelopeParser::cCallbacks overrides:
+ virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override
+ {
+ // Ignored
+ }
+};
+
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// 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 == "identity")
+ {
+ return std::make_shared<cIdentityTEParser>(a_Callbacks, a_ContentLength);
+ }
+ if (a_TransferEncoding.empty())
+ {
+ return std::make_shared<cIdentityTEParser>(a_Callbacks, a_ContentLength);
+ }
+ return nullptr;
+}
+
+
+
+
diff --git a/src/HTTPServer/TransferEncodingParser.h b/src/HTTP/TransferEncodingParser.h
index ce3d01df7..ce3d01df7 100644
--- a/src/HTTPServer/TransferEncodingParser.h
+++ b/src/HTTP/TransferEncodingParser.h
diff --git a/src/HTTPServer/UrlParser.cpp b/src/HTTP/UrlParser.cpp
index 05db3e413..05db3e413 100644
--- a/src/HTTPServer/UrlParser.cpp
+++ b/src/HTTP/UrlParser.cpp
diff --git a/src/HTTPServer/UrlParser.h b/src/HTTP/UrlParser.h
index 15a63e05d..15a63e05d 100644
--- a/src/HTTPServer/UrlParser.h
+++ b/src/HTTP/UrlParser.h
diff --git a/src/HTTPServer/TransferEncodingParser.cpp b/src/HTTPServer/TransferEncodingParser.cpp
deleted file mode 100644
index 8b703fd42..000000000
--- a/src/HTTPServer/TransferEncodingParser.cpp
+++ /dev/null
@@ -1,132 +0,0 @@
-
-// 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;
-}
-
-
-
-