summaryrefslogtreecommitdiffstats
path: root/src/HTTPServer
diff options
context:
space:
mode:
Diffstat (limited to 'src/HTTPServer')
-rw-r--r--src/HTTPServer/EnvelopeParser.cpp14
-rw-r--r--src/HTTPServer/EnvelopeParser.h26
-rw-r--r--src/HTTPServer/HTTPConnection.cpp10
-rw-r--r--src/HTTPServer/HTTPConnection.h36
-rw-r--r--src/HTTPServer/HTTPFormParser.cpp6
-rw-r--r--src/HTTPServer/HTTPFormParser.h42
-rw-r--r--src/HTTPServer/HTTPMessage.cpp10
-rw-r--r--src/HTTPServer/HTTPMessage.h66
-rw-r--r--src/HTTPServer/HTTPServer.cpp32
-rw-r--r--src/HTTPServer/HTTPServer.h30
-rw-r--r--src/HTTPServer/MultipartParser.cpp28
-rw-r--r--src/HTTPServer/MultipartParser.h32
-rw-r--r--src/HTTPServer/NameValueParser.cpp30
-rw-r--r--src/HTTPServer/NameValueParser.h24
-rw-r--r--src/HTTPServer/SslHTTPConnection.cpp8
-rw-r--r--src/HTTPServer/SslHTTPConnection.h10
16 files changed, 202 insertions, 202 deletions
diff --git a/src/HTTPServer/EnvelopeParser.cpp b/src/HTTPServer/EnvelopeParser.cpp
index fd4f3836d..407e9dcfc 100644
--- a/src/HTTPServer/EnvelopeParser.cpp
+++ b/src/HTTPServer/EnvelopeParser.cpp
@@ -26,20 +26,20 @@ size_t cEnvelopeParser::Parse(const char * a_Data, size_t a_Size)
{
return 0;
}
-
+
// Start searching 1 char from the end of the already received data, if available:
size_t SearchStart = m_IncomingData.size();
SearchStart = (SearchStart > 1) ? SearchStart - 1 : 0;
-
+
m_IncomingData.append(a_Data, a_Size);
-
+
size_t idxCRLF = m_IncomingData.find("\r\n", SearchStart);
if (idxCRLF == AString::npos)
{
// Not a complete line yet, all input consumed:
return a_Size;
}
-
+
// Parse as many lines as found:
size_t Last = 0;
do
@@ -61,7 +61,7 @@ size_t cEnvelopeParser::Parse(const char * a_Data, size_t a_Size)
idxCRLF = m_IncomingData.find("\r\n", idxCRLF + 2);
} while (idxCRLF != AString::npos);
m_IncomingData.erase(0, Last);
-
+
// Parsed all lines and still expecting more
return a_Size;
}
@@ -110,7 +110,7 @@ bool cEnvelopeParser::ParseLine(const char * a_Data, size_t a_Size)
m_LastValue.append(a_Data, a_Size);
return true;
}
-
+
// This is a line with a new key:
NotifyLast();
for (size_t i = 0; i < a_Size; i++)
@@ -122,7 +122,7 @@ bool cEnvelopeParser::ParseLine(const char * a_Data, size_t a_Size)
return true;
}
} // for i - a_Data[]
-
+
// No colon was found, key-less header??
return false;
}
diff --git a/src/HTTPServer/EnvelopeParser.h b/src/HTTPServer/EnvelopeParser.h
index fe226d1f8..2fa930539 100644
--- a/src/HTTPServer/EnvelopeParser.h
+++ b/src/HTTPServer/EnvelopeParser.h
@@ -21,49 +21,49 @@ public:
public:
// Force a virtual destructor in descendants:
virtual ~cCallbacks() {}
-
+
/** Called when a full header line is parsed */
virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) = 0;
} ;
-
-
+
+
cEnvelopeParser(cCallbacks & a_Callbacks);
-
+
/** Parses the incoming data.
Returns the number of bytes consumed from the input. The bytes not consumed are not part of the envelope header.
Returns AString::npos on error
*/
size_t Parse(const char * a_Data, size_t a_Size);
-
+
/** Makes the parser forget everything parsed so far, so that it can be reused for parsing another datastream */
void Reset(void);
-
+
/** Returns true if more input is expected for the envelope header */
bool IsInHeaders(void) const { return m_IsInHeaders; }
-
+
/** Sets the IsInHeaders flag; used by cMultipartParser to simplify the parser initial conditions */
void SetIsInHeaders(bool a_IsInHeaders) { m_IsInHeaders = a_IsInHeaders; }
-
+
public:
/** Callbacks to call for the various events */
cCallbacks & m_Callbacks;
-
+
/** Set to true while the parser is still parsing the envelope headers. Once set to true, the parser will not consume any more data. */
bool m_IsInHeaders;
-
+
/** Buffer for the incoming data until it is parsed */
AString m_IncomingData;
-
+
/** Holds the last parsed key; used for line-wrapped values */
AString m_LastKey;
-
+
/** Holds the last parsed value; used for line-wrapped values */
AString m_LastValue;
/** Notifies the callback of the key / value stored in m_LastKey / m_LastValue, then erases them */
void NotifyLast(void);
-
+
/** Parses one line of header data. Returns true if successful */
bool ParseLine(const char * a_Data, size_t a_Size);
} ;
diff --git a/src/HTTPServer/HTTPConnection.cpp b/src/HTTPServer/HTTPConnection.cpp
index c6a45e6ed..0db154139 100644
--- a/src/HTTPServer/HTTPConnection.cpp
+++ b/src/HTTPServer/HTTPConnection.cpp
@@ -104,7 +104,7 @@ void cHTTPConnection::AwaitNextRequest(void)
// Nothing has been received yet, or a special response was given (SendStatusAndReason() or SendNeedAuth())
break;
}
-
+
case wcsRecvIdle:
{
// The client is waiting for a response, send an "Internal server error":
@@ -112,7 +112,7 @@ void cHTTPConnection::AwaitNextRequest(void)
m_State = wcsRecvHeaders;
break;
}
-
+
case wcsSendingResp:
{
// The response headers have been sent, we need to terminate the response body:
@@ -120,7 +120,7 @@ void cHTTPConnection::AwaitNextRequest(void)
m_State = wcsRecvHeaders;
break;
}
-
+
default:
{
ASSERT(!"Unhandled state recovery");
@@ -184,7 +184,7 @@ void cHTTPConnection::OnReceivedData(const char * a_Data, size_t a_Size)
// The request headers are not yet complete
return;
}
-
+
// The request has finished parsing its headers successfully, notify of it:
m_State = wcsRecvBody;
m_HTTPServer.NewRequest(*this, *m_CurrentRequest);
@@ -194,7 +194,7 @@ void cHTTPConnection::OnReceivedData(const char * a_Data, size_t a_Size)
// The body length was not specified in the request, assume zero
m_CurrentRequestBodyRemaining = 0;
}
-
+
// Process the rest of the incoming data into the request body:
if (a_Size > BytesConsumed)
{
diff --git a/src/HTTPServer/HTTPConnection.h b/src/HTTPServer/HTTPConnection.h
index e1ebeb9ee..414075411 100644
--- a/src/HTTPServer/HTTPConnection.h
+++ b/src/HTTPServer/HTTPConnection.h
@@ -28,7 +28,7 @@ class cHTTPConnection :
public cTCPLink::cCallbacks
{
public:
-
+
enum eState
{
wcsRecvHeaders, ///< Receiving request headers (m_CurrentRequest is created if nullptr)
@@ -37,48 +37,48 @@ public:
wcsSendingResp, ///< Sending response body (m_CurrentRequest == nullptr)
wcsInvalid, ///< The request was malformed, the connection is closing
} ;
-
+
cHTTPConnection(cHTTPServer & a_HTTPServer);
virtual ~cHTTPConnection();
-
+
/** Sends HTTP status code together with a_Reason (used for HTTP errors).
Sends the a_Reason as the body as well, so that browsers display it. */
void SendStatusAndReason(int a_StatusCode, const AString & a_Reason);
-
+
/** Sends the "401 unauthorized" reply together with instructions on authorizing, using the specified realm */
void SendNeedAuth(const AString & a_Realm);
-
+
/** Sends the headers contained in a_Response */
void Send(const cHTTPResponse & a_Response);
-
+
/** Sends the data as the response (may be called multiple times) */
void Send(const void * a_Data, size_t a_Size);
/** Sends the data as the response (may be called multiple times) */
void Send(const AString & a_Data) { Send(a_Data.data(), a_Data.size()); }
-
+
/** Indicates that the current response is finished, gets ready for receiving another request (HTTP 1.1 keepalive) */
void FinishResponse(void);
-
+
/** Resets the internal connection state for a new request.
Depending on the state, this will send an "InternalServerError" status or a "ResponseEnd" */
void AwaitNextRequest(void);
-
+
/** Terminates the connection; finishes any request being currently processed */
void Terminate(void);
-
+
protected:
typedef std::map<AString, AString> cNameValueMap;
-
+
/** The parent webserver that is to be notified of events on this connection */
cHTTPServer & m_HTTPServer;
-
+
/** All the incoming data until the entire request header is parsed */
AString m_IncomingHeaderData;
-
+
/** Status in which the request currently is */
eState m_State;
-
+
/** The request being currently received
Valid only between having parsed the headers and finishing receiving the body. */
cHTTPRequest * m_CurrentRequest;
@@ -89,18 +89,18 @@ protected:
/** The network link attached to this connection. */
cTCPLinkPtr m_Link;
-
-
+
+
// cTCPLink::cCallbacks overrides:
/** The link instance has been created, remember it. */
virtual void OnLinkCreated(cTCPLinkPtr a_Link) override;
/** Data is received from the client. */
virtual void OnReceivedData(const char * a_Data, size_t a_Size) override;
-
+
/** The socket has been closed for any reason. */
virtual void OnRemoteClosed(void) override;
-
+
/** An error has occurred on the socket. */
virtual void OnError(int a_ErrorCode, const AString & a_ErrorMsg) override;
diff --git a/src/HTTPServer/HTTPFormParser.cpp b/src/HTTPServer/HTTPFormParser.cpp
index 77f98e43b..497f84033 100644
--- a/src/HTTPServer/HTTPFormParser.cpp
+++ b/src/HTTPServer/HTTPFormParser.cpp
@@ -22,7 +22,7 @@ cHTTPFormParser::cHTTPFormParser(cHTTPRequest & a_Request, cCallbacks & a_Callba
if (a_Request.GetMethod() == "GET")
{
m_Kind = fpkURL;
-
+
// Directly parse the URL in the request:
const AString & URL = a_Request.GetURL();
size_t idxQM = URL.find('?');
@@ -74,7 +74,7 @@ void cHTTPFormParser::Parse(const char * a_Data, size_t a_Size)
{
return;
}
-
+
switch (m_Kind)
{
case fpkURL:
@@ -223,7 +223,7 @@ void cHTTPFormParser::OnPartHeader(const AString & a_Key, const AString & a_Valu
m_IsValid = false;
return;
}
-
+
// Parse the field name and optional filename from this header:
cNameValueParser Parser(a_Value.data() + ParamsStart, a_Value.size() - ParamsStart);
Parser.Finish();
diff --git a/src/HTTPServer/HTTPFormParser.h b/src/HTTPServer/HTTPFormParser.h
index e72d4ef10..f6cbe047f 100644
--- a/src/HTTPServer/HTTPFormParser.h
+++ b/src/HTTPServer/HTTPFormParser.h
@@ -38,36 +38,36 @@ public:
public:
// Force a virtual destructor in descendants:
virtual ~cCallbacks() {}
-
+
/** Called when a new file part is encountered in the form data */
virtual void OnFileStart(cHTTPFormParser & a_Parser, const AString & a_FileName) = 0;
-
+
/** Called when more file data has come for the current file in the form data */
virtual void OnFileData(cHTTPFormParser & a_Parser, const char * a_Data, size_t a_Size) = 0;
-
+
/** Called when the current file part has ended in the form data */
virtual void OnFileEnd(cHTTPFormParser & a_Parser) = 0;
} ;
-
-
+
+
/** Creates a parser that is tied to a request and notifies of various events using a callback mechanism */
cHTTPFormParser(cHTTPRequest & a_Request, cCallbacks & a_Callbacks);
-
+
/** Creates a parser with the specified content type that reads data from a string */
cHTTPFormParser(eKind a_Kind, const char * a_Data, size_t a_Size, cCallbacks & a_Callbacks);
-
+
/** Adds more data into the parser, as the request body is received */
void Parse(const char * a_Data, size_t a_Size);
-
+
/** Notifies that there's no more data incoming and the parser should finish its parsing.
Returns true if parsing successful. */
bool Finish(void);
-
+
/** Returns true if the headers suggest the request has form data parseable by this class */
static bool HasFormData(const cHTTPRequest & a_Request);
-
+
protected:
-
+
/** The callbacks to call for incoming file data */
cCallbacks & m_Callbacks;
@@ -76,32 +76,32 @@ protected:
/** Buffer for the incoming data until it's parsed */
AString m_IncomingData;
-
+
/** True if the information received so far is a valid form; set to false on first problem. Further parsing is skipped when false. */
bool m_IsValid;
-
+
/** The parser for the multipart data, if used */
std::unique_ptr<cMultipartParser> m_MultipartParser;
-
+
/** Name of the currently parsed part in multipart data */
AString m_CurrentPartName;
-
+
/** True if the currently parsed part in multipart data is a file */
bool m_IsCurrentPartFile;
-
+
/** Filename of the current parsed part in multipart data (for file uploads) */
AString m_CurrentPartFileName;
-
+
/** Set to true after m_Callbacks.OnFileStart() has been called, reset to false on PartEnd */
bool m_FileHasBeenAnnounced;
-
-
+
+
/** Sets up the object for parsing a fpkMultipart request */
void BeginMultipart(const cHTTPRequest & a_Request);
-
+
/** Parses m_IncomingData as form-urlencoded data (fpkURL or fpkFormUrlEncoded kinds) */
void ParseFormUrlEncoded(void);
-
+
// cMultipartParser::cCallbacks overrides:
virtual void OnPartStart (void) override;
virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) override;
diff --git a/src/HTTPServer/HTTPMessage.cpp b/src/HTTPServer/HTTPMessage.cpp
index 400625690..360145a9a 100644
--- a/src/HTTPServer/HTTPMessage.cpp
+++ b/src/HTTPServer/HTTPMessage.cpp
@@ -47,7 +47,7 @@ void cHTTPMessage::AddHeader(const AString & a_Key, const AString & a_Value)
itr->second.append(", ");
itr->second.append(a_Value);
}
-
+
// Special processing for well-known headers:
if (Key == "content-type")
{
@@ -89,7 +89,7 @@ size_t cHTTPRequest::ParseHeaders(const char * a_Data, size_t a_Size)
{
return AString::npos;
}
-
+
if (m_Method.empty())
{
// The first line hasn't been processed yet
@@ -108,7 +108,7 @@ size_t cHTTPRequest::ParseHeaders(const char * a_Data, size_t a_Size)
}
return res2 + res;
}
-
+
if (m_EnvelopeParser.IsInHeaders())
{
size_t res = m_EnvelopeParser.Parse(a_Data, a_Size);
@@ -166,7 +166,7 @@ size_t cHTTPRequest::ParseRequestLine(const char * a_Data, size_t a_Size)
m_IsValid = false;
return AString::npos;
}
-
+
int NumSpaces = 0;
size_t MethodEnd = 0;
size_t URLEnd = 0;
@@ -218,7 +218,7 @@ size_t cHTTPRequest::ParseRequestLine(const char * a_Data, size_t a_Size)
}
} // switch (m_IncomingHeaderData[i])
} // for i - m_IncomingHeaderData[]
-
+
// CRLF hasn't been encountered yet, consider all data consumed
return a_Size;
}
diff --git a/src/HTTPServer/HTTPMessage.h b/src/HTTPServer/HTTPMessage.h
index ff657a272..72ecb67d1 100644
--- a/src/HTTPServer/HTTPMessage.h
+++ b/src/HTTPServer/HTTPMessage.h
@@ -29,26 +29,26 @@ public:
mkRequest,
mkResponse,
} ;
-
+
cHTTPMessage(eKind a_Kind);
// Force a virtual destructor in all descendants
virtual ~cHTTPMessage() {}
-
+
/** Adds a header into the internal map of headers. Recognizes special headers: Content-Type and Content-Length */
void AddHeader(const AString & a_Key, const AString & a_Value);
-
+
void SetContentType (const AString & a_ContentType) { m_ContentType = a_ContentType; }
void SetContentLength(size_t a_ContentLength) { m_ContentLength = a_ContentLength; }
-
+
const AString & GetContentType (void) const { return m_ContentType; }
size_t GetContentLength(void) const { return m_ContentLength; }
protected:
typedef std::map<AString, AString> cNameValueMap;
-
+
eKind m_Kind;
-
+
cNameValueMap m_Headers;
/** Type of the content; parsed by AddHeader(), set directly by SetContentLength() */
@@ -69,86 +69,86 @@ class cHTTPRequest :
protected cEnvelopeParser::cCallbacks
{
typedef cHTTPMessage super;
-
+
public:
cHTTPRequest(void);
-
+
/** Parses the request line and then headers from the received data.
Returns the number of bytes consumed or AString::npos number for error
*/
size_t ParseHeaders(const char * a_Data, size_t a_Size);
-
+
/** Returns true if the request did contain a Content-Length header */
bool HasReceivedContentLength(void) const { return (m_ContentLength != AString::npos); }
-
+
/** Returns the method used in the request */
const AString & GetMethod(void) const { return m_Method; }
-
+
/** Returns the URL used in the request */
const AString & GetURL(void) const { return m_URL; }
-
+
/** Returns the URL used in the request, without any parameters */
AString GetBareURL(void) const;
-
+
/** Sets the UserData pointer that is stored within this request.
The request doesn't touch this data (doesn't delete it)! */
void SetUserData(void * a_UserData) { m_UserData = a_UserData; }
-
+
/** Retrieves the UserData pointer that has been stored within this request. */
void * GetUserData(void) const { return m_UserData; }
-
+
/** Returns true if more data is expected for the request headers */
bool IsInHeaders(void) const { return m_EnvelopeParser.IsInHeaders(); }
-
+
/** Returns true if the request did present auth data that was understood by the parser */
bool HasAuth(void) const { return m_HasAuth; }
-
+
/** Returns the username that the request presented. Only valid if HasAuth() is true */
const AString & GetAuthUsername(void) const { return m_AuthUsername; }
-
+
/** Returns the password that the request presented. Only valid if HasAuth() is true */
const AString & GetAuthPassword(void) const { return m_AuthPassword; }
-
+
bool DoesAllowKeepAlive(void) const { return m_AllowKeepAlive; }
-
+
protected:
/** Parser for the envelope data */
cEnvelopeParser m_EnvelopeParser;
-
+
/** True if the data received so far is parsed successfully. When false, all further parsing is skipped */
bool m_IsValid;
-
+
/** Bufferred incoming data, while parsing for the request line */
AString m_IncomingHeaderData;
-
+
/** Method of the request (GET / PUT / POST / ...) */
AString m_Method;
-
+
/** Full URL of the request */
AString m_URL;
-
+
/** Data that the HTTPServer callbacks are allowed to store. */
void * m_UserData;
-
+
/** Set to true if the request contains auth data that was understood by the parser */
bool m_HasAuth;
-
+
/** The username used for auth */
AString m_AuthUsername;
-
+
/** The password used for auth */
AString m_AuthPassword;
-
+
/** Set to true if the request indicated that it supports keepalives.
If false, the server will close the connection once the request is finished */
bool m_AllowKeepAlive;
-
-
+
+
/** Parses the incoming data for the first line (RequestLine)
Returns the number of bytes consumed, or AString::npos for an error
*/
size_t ParseRequestLine(const char * a_Data, size_t a_Size);
-
+
// cEnvelopeParser::cCallbacks overrides:
virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override;
} ;
@@ -164,7 +164,7 @@ class cHTTPResponse :
public:
cHTTPResponse(void);
-
+
/** Appends the response to the specified datastream - response line and headers.
The body will be sent later directly through cConnection::Send()
*/
diff --git a/src/HTTPServer/HTTPServer.cpp b/src/HTTPServer/HTTPServer.cpp
index bbff5d57a..814a87fe4 100644
--- a/src/HTTPServer/HTTPServer.cpp
+++ b/src/HTTPServer/HTTPServer.cpp
@@ -31,26 +31,26 @@ class cDebugCallbacks :
virtual void OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override
{
UNUSED(a_Connection);
-
+
if (cHTTPFormParser::HasFormData(a_Request))
{
a_Request.SetUserData(new cHTTPFormParser(a_Request, *this));
}
}
-
-
+
+
virtual void OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) override
{
UNUSED(a_Connection);
-
+
cHTTPFormParser * FormParser = reinterpret_cast<cHTTPFormParser *>(a_Request.GetUserData());
if (FormParser != nullptr)
{
FormParser->Parse(a_Data, a_Size);
}
}
-
-
+
+
virtual void OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) override
{
cHTTPFormParser * FormParser = reinterpret_cast<cHTTPFormParser *>(a_Request.GetUserData());
@@ -69,7 +69,7 @@ class cDebugCallbacks :
a_Connection.Send("</table></body></html>");
return;
}
-
+
// Parsing failed:
cHTTPResponse Resp;
Resp.SetContentType("text/plain");
@@ -77,7 +77,7 @@ class cDebugCallbacks :
a_Connection.Send("Form parsing failed");
return;
}
-
+
// Test the auth failure and success:
if (a_Request.GetURL() == "/auth")
{
@@ -87,31 +87,31 @@ class cDebugCallbacks :
return;
}
}
-
+
cHTTPResponse Resp;
Resp.SetContentType("text/plain");
a_Connection.Send(Resp);
a_Connection.Send("Hello, world");
}
-
-
+
+
virtual void OnFileStart(cHTTPFormParser & a_Parser, const AString & a_FileName) override
{
// TODO
}
-
-
+
+
virtual void OnFileData(cHTTPFormParser & a_Parser, const char * a_Data, size_t a_Size) override
{
// TODO
}
-
+
virtual void OnFileEnd(cHTTPFormParser & a_Parser) override
{
// TODO
}
-
+
};
static cDebugCallbacks g_DebugCallbacks;
@@ -239,7 +239,7 @@ bool cHTTPServer::Start(cCallbacks & a_Callbacks, const AStringVector & a_Ports)
m_ServerHandles.push_back(Handle);
}
} // for port - a_Ports[]
-
+
// Report success if at least one port opened successfully:
return !m_ServerHandles.empty();
}
diff --git a/src/HTTPServer/HTTPServer.h b/src/HTTPServer/HTTPServer.h
index d626fb475..2a094b413 100644
--- a/src/HTTPServer/HTTPServer.h
+++ b/src/HTTPServer/HTTPServer.h
@@ -39,48 +39,48 @@ public:
{
public:
virtual ~cCallbacks() {}
-
+
/** Called when a new request arrives over a connection and all its headers have been parsed.
The request body needn't have arrived yet. */
virtual void OnRequestBegun(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) = 0;
-
+
/** Called when another part of request body has arrived.
May be called multiple times for a single request. */
virtual void OnRequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size) = 0;
-
+
/** Called when the request body has been fully received in previous calls to OnRequestBody() */
virtual void OnRequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request) = 0;
} ;
-
+
cHTTPServer(void);
virtual ~cHTTPServer();
-
+
/** Initializes the server - reads the cert files etc. */
bool Initialize(void);
-
+
/** Starts the server and assigns the callbacks to use for incoming requests */
bool Start(cCallbacks & a_Callbacks, const AStringVector & a_Ports);
-
+
/** Stops the server, drops all current connections */
void Stop(void);
-
+
protected:
friend class cHTTPConnection;
friend class cSslHTTPConnection;
friend class cHTTPServerListenCallbacks;
-
+
/** The cNetwork API handle for the listening socket. */
cServerHandlePtrs m_ServerHandles;
-
+
/** The callbacks to call for various events */
cCallbacks * m_Callbacks;
-
+
/** The server certificate to use for the SSL connections */
cX509CertPtr m_Cert;
-
+
/** The private key for m_Cert. */
cCryptoKeyPtr m_CertPrivKey;
-
+
/** Called by cHTTPServerListenCallbacks when there's a new incoming connection.
Returns the connection instance to be used as the cTCPLink callbacks. */
@@ -88,11 +88,11 @@ protected:
/** Called by cHTTPConnection when it finishes parsing the request header */
void NewRequest(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
-
+
/** Called by cHTTPConenction when it receives more data for the request body.
May be called multiple times for a single request. */
void RequestBody(cHTTPConnection & a_Connection, cHTTPRequest & a_Request, const char * a_Data, size_t a_Size);
-
+
/** Called by cHTTPConnection when it detects that the request has finished (all of its body has been received) */
void RequestFinished(cHTTPConnection & a_Connection, cHTTPRequest & a_Request);
} ;
diff --git a/src/HTTPServer/MultipartParser.cpp b/src/HTTPServer/MultipartParser.cpp
index 09732c5f7..09f4fd02a 100644
--- a/src/HTTPServer/MultipartParser.cpp
+++ b/src/HTTPServer/MultipartParser.cpp
@@ -56,25 +56,25 @@ ThisIsIgnoredEpilogue";
// DEBUG: Check if the onscreen output corresponds with the data above
printf("Multipart parsing test finished\n");
}
-
+
virtual void OnPartStart(void) override
{
printf("Starting a new part\n");
}
-
-
+
+
virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) override
{
printf(" Hdr: \"%s\"=\"%s\"\n", a_Key.c_str(), a_Value.c_str());
}
-
-
+
+
virtual void OnPartData(const char * a_Data, int a_Size) override
{
printf(" Data: %d bytes, \"%.*s\"\n", a_Size, a_Size, a_Data);
}
-
-
+
+
virtual void OnPartEnd(void) override
{
printf("Part end\n");
@@ -110,7 +110,7 @@ cMultipartParser::cMultipartParser(const AString & a_ContentType, cCallbacks & a
m_IsValid = false;
return;
}
-
+
// Find the multipart boundary:
ContentType.erase(0, idxSC + 1);
cNameValueParser CTParser(ContentType.c_str(), ContentType.size());
@@ -126,13 +126,13 @@ cMultipartParser::cMultipartParser(const AString & a_ContentType, cCallbacks & a
{
return;
}
-
+
// Set the envelope parser for parsing the body, so that our Parse() function parses the ignored prefix data as a body
m_EnvelopeParser.SetIsInHeaders(false);
// Append an initial CRLF to the incoming data, so that a body starting with the boundary line will get caught
m_IncomingData.assign("\r\n");
-
+
/*
m_Boundary = AString("\r\n--") + m_Boundary
m_BoundaryEnd = m_Boundary + "--\r\n";
@@ -151,7 +151,7 @@ void cMultipartParser::Parse(const char * a_Data, size_t a_Size)
{
return;
}
-
+
// Append to buffer, then parse it:
m_IncomingData.append(a_Data, a_Size);
for (;;)
@@ -213,7 +213,7 @@ void cMultipartParser::Parse(const char * a_Data, size_t a_Size)
m_IncomingData.erase(0, LineEnd);
continue;
}
-
+
if (strncmp(m_IncomingData.c_str() + idxBoundary, m_Boundary.c_str(), m_Boundary.size()) == 0)
{
// Boundary or BoundaryEnd found:
@@ -228,12 +228,12 @@ void cMultipartParser::Parse(const char * a_Data, size_t a_Size)
}
m_Callbacks.OnPartStart();
m_IncomingData.erase(0, LineEnd + 2);
-
+
// Keep parsing for the headers that may have come with this data:
m_EnvelopeParser.Reset();
continue;
}
-
+
// It's a line, but not a boundary. It can be fully sent to the data receiver, since a boundary cannot cross lines
m_Callbacks.OnPartData(m_IncomingData.c_str(), LineEnd);
m_IncomingData.erase(0, LineEnd);
diff --git a/src/HTTPServer/MultipartParser.h b/src/HTTPServer/MultipartParser.h
index ad76ad650..4f20b2bed 100644
--- a/src/HTTPServer/MultipartParser.h
+++ b/src/HTTPServer/MultipartParser.h
@@ -24,52 +24,52 @@ public:
public:
// Force a virtual destructor in descendants:
virtual ~cCallbacks() {}
-
+
/** Called when a new part starts */
virtual void OnPartStart(void) = 0;
-
+
/** Called when a complete header line is received for a part */
virtual void OnPartHeader(const AString & a_Key, const AString & a_Value) = 0;
-
+
/** Called when body for a part is received */
virtual void OnPartData(const char * a_Data, size_t a_Size) = 0;
-
+
/** Called when the current part ends */
virtual void OnPartEnd(void) = 0;
} ;
-
+
/** Creates the parser, expects to find the boundary in a_ContentType */
cMultipartParser(const AString & a_ContentType, cCallbacks & a_Callbacks);
-
+
/** Parses more incoming data */
void Parse(const char * a_Data, size_t a_Size);
-
+
protected:
/** The callbacks to call for various parsing events */
cCallbacks & m_Callbacks;
-
+
/** True if the data parsed so far is valid; if false, further parsing is skipped */
bool m_IsValid;
-
+
/** Parser for each part's envelope */
cEnvelopeParser m_EnvelopeParser;
-
+
/** Buffer for the incoming data until it is parsed */
AString m_IncomingData;
-
+
/** The boundary, excluding both the initial "--" and the terminating CRLF */
AString m_Boundary;
-
+
/** Set to true if some data for the current part has already been signalized to m_Callbacks. Used for proper CRLF inserting. */
bool m_HasHadData;
-
-
+
+
/** Parse one line of incoming data. The CRLF has already been stripped from a_Data / a_Size */
void ParseLine(const char * a_Data, size_t a_Size);
-
+
/** Parse one line of incoming data in the headers section of a part. The CRLF has already been stripped from a_Data / a_Size */
void ParseHeaderLine(const char * a_Data, size_t a_Size);
-
+
// cEnvelopeParser overrides:
virtual void OnHeaderLine(const AString & a_Key, const AString & a_Value) override;
} ;
diff --git a/src/HTTPServer/NameValueParser.cpp b/src/HTTPServer/NameValueParser.cpp
index b345fef88..f759c4d21 100644
--- a/src/HTTPServer/NameValueParser.cpp
+++ b/src/HTTPServer/NameValueParser.cpp
@@ -29,18 +29,18 @@ public:
Parser2.Parse(Data + i, 1);
}
Parser2.Finish();
-
+
// Parse as a single chunk of data:
cNameValueParser Parser(Data, sizeof(Data) - 1);
-
+
// Use the debugger to inspect the Parser variable
-
+
// Check that the two parsers have the same content:
for (cNameValueParser::const_iterator itr = Parser.begin(), end = Parser.end(); itr != end; ++itr)
{
ASSERT(Parser2[itr->first] == itr->second);
} // for itr - Parser[]
-
+
// Try parsing in 2-char chunks:
cNameValueParser Parser3;
for (int i = 0; i < sizeof(Data) - 2; i += 2)
@@ -52,13 +52,13 @@ public:
Parser3.Parse(Data + sizeof(Data) - 2, 1);
}
Parser3.Finish();
-
+
// Check that the third parser has the same content:
for (cNameValueParser::const_iterator itr = Parser.begin(), end = Parser.end(); itr != end; ++itr)
{
ASSERT(Parser3[itr->first] == itr->second);
} // for itr - Parser[]
-
+
printf("cNameValueParserTest done");
}
} g_Test;
@@ -96,7 +96,7 @@ cNameValueParser::cNameValueParser(const char * a_Data, size_t a_Size, bool a_Al
void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
{
ASSERT(m_State != psFinished); // Calling Parse() after Finish() is wrong!
-
+
size_t Last = 0;
for (size_t i = 0; i < a_Size;)
{
@@ -107,7 +107,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
{
return;
}
-
+
case psKeySpace:
{
// Skip whitespace until a non-whitespace is found, then start the key:
@@ -122,7 +122,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
}
break;
}
-
+
case psKey:
{
// Read the key until whitespace or an equal sign:
@@ -174,7 +174,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
}
break;
}
-
+
case psEqualSpace:
{
// The space before the expected equal sign; the current key is already assigned
@@ -211,7 +211,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
} // while (i < a_Size)
break;
} // case psEqualSpace
-
+
case psEqual:
{
// just parsed the equal-sign
@@ -256,7 +256,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
} // while (i < a_Size)
break;
} // case psEqual
-
+
case psValueInDQuotes:
{
while (i < a_Size)
@@ -280,7 +280,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
}
break;
} // case psValueInDQuotes
-
+
case psValueInSQuotes:
{
while (i < a_Size)
@@ -304,7 +304,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
}
break;
} // case psValueInSQuotes
-
+
case psValueRaw:
{
while (i < a_Size)
@@ -328,7 +328,7 @@ void cNameValueParser::Parse(const char * a_Data, size_t a_Size)
}
break;
} // case psValueRaw
-
+
case psAfterValue:
{
// Between the closing DQuote or SQuote and the terminating semicolon
diff --git a/src/HTTPServer/NameValueParser.h b/src/HTTPServer/NameValueParser.h
index c0643b139..e205079db 100644
--- a/src/HTTPServer/NameValueParser.h
+++ b/src/HTTPServer/NameValueParser.h
@@ -19,22 +19,22 @@ class cNameValueParser :
public:
/** Creates an empty parser */
cNameValueParser(bool a_AllowsKeyOnly = true);
-
+
/** Creates an empty parser, then parses the data given. Doesn't call Finish(), so more data can be parsed later */
cNameValueParser(const char * a_Data, size_t a_Size, bool a_AllowsKeyOnly = true);
-
+
/** Parses the data given */
void Parse(const char * a_Data, size_t a_Size);
-
+
/** Notifies the parser that no more data will be coming. Returns true if the parser state is valid */
bool Finish(void);
-
+
/** Returns true if the data parsed so far was valid */
bool IsValid(void) const { return (m_State != psInvalid); }
-
+
/** Returns true if the parser expects no more data */
bool IsFinished(void) const { return ((m_State == psInvalid) || (m_State == psFinished)); }
-
+
protected:
enum eState
{
@@ -49,20 +49,20 @@ protected:
psInvalid, ///< The parser has encountered an invalid input; further parsing is skipped
psFinished, ///< The parser has already been instructed to finish and doesn't expect any more data
} ;
-
+
/** The current state of the parser */
eState m_State;
-
+
/** If true, the parser will accept keys without an equal sign and the value */
bool m_AllowsKeyOnly;
-
+
/** Buffer for the current Key */
AString m_CurrentKey;
-
+
/** Buffer for the current Value; */
AString m_CurrentValue;
-
-
+
+
} ;
diff --git a/src/HTTPServer/SslHTTPConnection.cpp b/src/HTTPServer/SslHTTPConnection.cpp
index 1e862466c..1cbe02312 100644
--- a/src/HTTPServer/SslHTTPConnection.cpp
+++ b/src/HTTPServer/SslHTTPConnection.cpp
@@ -49,7 +49,7 @@ void cSslHTTPConnection::OnReceivedData(const char * a_Data, size_t a_Size)
Data += BytesWritten;
Size -= BytesWritten;
}
-
+
// Try to read as many bytes from SSL's decryption as possible:
char Buffer[32000];
int NumRead = m_Ssl.ReadPlain(Buffer, sizeof(Buffer));
@@ -64,7 +64,7 @@ void cSslHTTPConnection::OnReceivedData(const char * a_Data, size_t a_Size)
// SSL requires us to send data to peer first, do so by "sending" empty data:
SendData(nullptr, 0);
}
-
+
// If both failed, bail out:
if ((BytesWritten == 0) && (NumRead <= 0))
{
@@ -93,7 +93,7 @@ void cSslHTTPConnection::SendData(const void * a_Data, size_t a_Size)
pos += static_cast<size_t>(NumWritten);
}
}
-
+
// Read as many bytes from SSL's "outgoing" buffer as possible:
char Buffer[32000];
size_t NumBytes = m_Ssl.ReadOutgoing(Buffer, sizeof(Buffer));
@@ -101,7 +101,7 @@ void cSslHTTPConnection::SendData(const void * a_Data, size_t a_Size)
{
m_Link->Send(Buffer, NumBytes);
}
-
+
// If both failed, bail out:
if ((NumWritten <= 0) && (NumBytes == 0))
{
diff --git a/src/HTTPServer/SslHTTPConnection.h b/src/HTTPServer/SslHTTPConnection.h
index c461a3a24..b35bd8ba0 100644
--- a/src/HTTPServer/SslHTTPConnection.h
+++ b/src/HTTPServer/SslHTTPConnection.h
@@ -20,23 +20,23 @@ class cSslHTTPConnection :
public cHTTPConnection
{
typedef cHTTPConnection super;
-
+
public:
/** Creates a new connection on the specified server.
Sends the specified cert as the server certificate, uses the private key for decryption. */
cSslHTTPConnection(cHTTPServer & a_HTTPServer, const cX509CertPtr & a_Cert, const cCryptoKeyPtr & a_PrivateKey);
~cSslHTTPConnection();
-
+
protected:
cBufferedSslContext m_Ssl;
-
+
/** The certificate to send to the client */
cX509CertPtr m_Cert;
-
+
/** The private key used for the certificate */
cCryptoKeyPtr m_PrivateKey;
-
+
// cHTTPConnection overrides:
virtual void OnReceivedData(const char * a_Data, size_t a_Size) override; // Data is received from the client
virtual void SendData(const void * a_Data, size_t a_Size) override; // Data is to be sent to client