Renamed HTTPServer folder to HTTP.
It contains client code as well.
This commit is contained in:
parent
fce68dc8f3
commit
fea556ca1b
@ -36,7 +36,7 @@
|
|||||||
#include "../StringCompression.h"
|
#include "../StringCompression.h"
|
||||||
#include "../CommandOutput.h"
|
#include "../CommandOutput.h"
|
||||||
#include "../BuildInfo.h"
|
#include "../BuildInfo.h"
|
||||||
#include "../HTTPServer/UrlParser.h"
|
#include "../HTTP/UrlParser.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/polarssl/include
|
|||||||
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/libevent/include")
|
include_directories (SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/../lib/libevent/include")
|
||||||
|
|
||||||
set(FOLDERS
|
set(FOLDERS
|
||||||
OSSupport HTTPServer Items Blocks Protocol Generating PolarSSL++ Bindings
|
OSSupport HTTP Items Blocks Protocol Generating PolarSSL++ Bindings
|
||||||
WorldStorage Mobs Entities Simulator Simulator/IncrementalRedstoneSimulator
|
WorldStorage Mobs Entities Simulator Simulator/IncrementalRedstoneSimulator
|
||||||
BlockEntities UI Noise
|
BlockEntities UI Noise
|
||||||
)
|
)
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
cHTTPResponseParser::cHTTPResponseParser(cHTTPResponseParser::cCallbacks & a_Callbacks):
|
cHTTPResponseParser::cHTTPResponseParser(cHTTPResponseParser::cCallbacks & a_Callbacks):
|
||||||
Super(mkResponse),
|
Super(mkResponse),
|
||||||
m_Callbacks(a_Callbacks),
|
m_Callbacks(a_Callbacks),
|
||||||
|
m_HasHadError(false),
|
||||||
m_IsInHeaders(true),
|
m_IsInHeaders(true),
|
||||||
m_IsFinished(false),
|
m_IsFinished(false),
|
||||||
m_EnvelopeParser(*this)
|
m_EnvelopeParser(*this)
|
||||||
@ -56,7 +57,7 @@ size_t cHTTPResponseParser::Parse(const char * a_Data, size_t a_Size)
|
|||||||
if (!m_Buffer.empty())
|
if (!m_Buffer.empty())
|
||||||
{
|
{
|
||||||
// Headers finished and there's still data left in the buffer, process it as message body:
|
// 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 ParseBody(m_Buffer.data(), m_Buffer.size());
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -132,6 +133,10 @@ void cHTTPResponseParser::HeadersFinished(void)
|
|||||||
{
|
{
|
||||||
m_TransferEncodingParser = cTransferEncodingParser::Create(*this, "identity", m_ContentLength);
|
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)
|
void cHTTPResponseParser::OnBodyFinished(void)
|
||||||
{
|
{
|
||||||
|
m_IsFinished = true;
|
||||||
m_Callbacks.OnBodyFinished();
|
m_Callbacks.OnBodyFinished();
|
||||||
}
|
}
|
||||||
|
|
393
src/HTTP/TransferEncodingParser.cpp
Normal file
393
src/HTTP/TransferEncodingParser.cpp
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#include "Protocol/Authenticator.h"
|
#include "Protocol/Authenticator.h"
|
||||||
#include "Protocol/MojangAPI.h"
|
#include "Protocol/MojangAPI.h"
|
||||||
#include "HTTPServer/HTTPServer.h"
|
#include "HTTP/HTTPServer.h"
|
||||||
#include "Defines.h"
|
#include "Defines.h"
|
||||||
#include "RankManager.h"
|
#include "RankManager.h"
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
#include "Server.h"
|
#include "Server.h"
|
||||||
#include "Root.h"
|
#include "Root.h"
|
||||||
|
|
||||||
#include "HTTPServer/HTTPRequestParser.h"
|
#include "HTTP/HTTPRequestParser.h"
|
||||||
#include "HTTPServer/HTTPServerConnection.h"
|
#include "HTTP/HTTPServerConnection.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
|
|
||||||
#include "Bindings/LuaState.h"
|
#include "Bindings/LuaState.h"
|
||||||
#include "IniFile.h"
|
#include "IniFile.h"
|
||||||
#include "HTTPServer/HTTPServer.h"
|
#include "HTTP/HTTPServer.h"
|
||||||
#include "HTTPServer/HTTPFormParser.h"
|
#include "HTTP/HTTPFormParser.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user