diff options
Diffstat (limited to 'src/HTTP/HTTPServerConnection.cpp')
-rw-r--r-- | src/HTTP/HTTPServerConnection.cpp | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/src/HTTP/HTTPServerConnection.cpp b/src/HTTP/HTTPServerConnection.cpp new file mode 100644 index 000000000..9edec2886 --- /dev/null +++ b/src/HTTP/HTTPServerConnection.cpp @@ -0,0 +1,240 @@ + +// HTTPConnection.cpp + +// Implements the cHTTPServerConnection class representing a single persistent connection in the HTTP server. + +#include "Globals.h" +#include "HTTPServerConnection.h" +#include "HTTPMessage.h" +#include "HTTPMessageParser.h" +#include "HTTPServer.h" + + + + + +cHTTPServerConnection::cHTTPServerConnection(cHTTPServer & a_HTTPServer) : + m_HTTPServer(a_HTTPServer), + m_Parser(*this), + m_CurrentRequest(nullptr) +{ + // LOGD("HTTP: New connection at %p", this); +} + + + + + +cHTTPServerConnection::~cHTTPServerConnection() +{ + // LOGD("HTTP: Connection deleting: %p", this); + m_CurrentRequest.reset(); +} + + + + + +void cHTTPServerConnection::SendStatusAndReason(int a_StatusCode, const AString & a_Response) +{ + SendData(Printf("HTTP/1.1 %d %s\r\n", a_StatusCode, a_Response.c_str())); + SendData(Printf("Content-Length: %u\r\n\r\n", static_cast<unsigned>(a_Response.size()))); + SendData(a_Response.data(), a_Response.size()); + m_CurrentRequest.reset(); + m_Parser.Reset(); +} + + + + + +void cHTTPServerConnection::SendNeedAuth(const AString & a_Realm) +{ + SendData(Printf("HTTP/1.1 401 Unauthorized\r\nWWW-Authenticate: Basic realm=\"%s\"\r\nContent-Length: 0\r\n\r\n", a_Realm.c_str())); + m_CurrentRequest.reset(); + m_Parser.Reset(); +} + + + + + +void cHTTPServerConnection::Send(const cHTTPOutgoingResponse & a_Response) +{ + ASSERT(m_CurrentRequest != nullptr); + AString toSend; + a_Response.AppendToData(toSend); + SendData(toSend); +} + + + + + +void cHTTPServerConnection::Send(const void * a_Data, size_t a_Size) +{ + ASSERT(m_CurrentRequest != nullptr); + // We're sending in Chunked transfer encoding + SendData(Printf(SIZE_T_FMT_HEX "\r\n", a_Size)); + SendData(a_Data, a_Size); + SendData("\r\n"); +} + + + + + +void cHTTPServerConnection::FinishResponse(void) +{ + ASSERT(m_CurrentRequest != nullptr); + SendData("0\r\n\r\n"); + m_CurrentRequest.reset(); + m_Parser.Reset(); +} + + + + + +void cHTTPServerConnection::Terminate(void) +{ + if (m_CurrentRequest != nullptr) + { + m_HTTPServer.RequestFinished(*this, *m_CurrentRequest); + } + m_Link.reset(); +} + + + + + +void cHTTPServerConnection::OnLinkCreated(cTCPLinkPtr a_Link) +{ + ASSERT(m_Link == nullptr); + m_Link = a_Link; +} + + + + + +void cHTTPServerConnection::OnReceivedData(const char * a_Data, size_t a_Size) +{ + ASSERT(m_Link != nullptr); + + m_Parser.Parse(a_Data, a_Size); +} + + + + + +void cHTTPServerConnection::OnRemoteClosed(void) +{ + if (m_CurrentRequest != nullptr) + { + m_HTTPServer.RequestFinished(*this, *m_CurrentRequest); + } + m_Link.reset(); +} + + + + + + +void cHTTPServerConnection::OnError(int a_ErrorCode, const AString & a_ErrorMsg) +{ + OnRemoteClosed(); +} + + + + + +void cHTTPServerConnection::OnError(const AString & a_ErrorDescription) +{ + OnRemoteClosed(); +} + + + + + +void cHTTPServerConnection::OnFirstLine(const AString & a_FirstLine) +{ + // Create a new request object for this request: + auto split = StringSplit(a_FirstLine, " "); + if (split.size() < 2) + { + // Invalid request line. We need at least the Method and URL + OnRemoteClosed(); + return; + } + m_CurrentRequest.reset(new cHTTPIncomingRequest(split[0], split[1])); +} + + + + + +void cHTTPServerConnection::OnHeaderLine(const AString & a_Key, const AString & a_Value) +{ + if (m_CurrentRequest == nullptr) + { + return; + } + m_CurrentRequest->AddHeader(a_Key, a_Value); +} + + + + + +void cHTTPServerConnection::OnHeadersFinished(void) +{ + if (m_CurrentRequest == nullptr) + { + return; + } + m_HTTPServer.NewRequest(*this, *m_CurrentRequest); +} + + + + + +void cHTTPServerConnection::OnBodyData(const void * a_Data, size_t a_Size) +{ + if (m_CurrentRequest == nullptr) + { + return; + } + m_HTTPServer.RequestBody(*this, *m_CurrentRequest, a_Data, a_Size); +} + + + + + +void cHTTPServerConnection::OnBodyFinished(void) +{ + // Process the request and reset: + m_HTTPServer.RequestFinished(*this, *m_CurrentRequest); + m_CurrentRequest.reset(); + m_Parser.Reset(); +} + + + + + +void cHTTPServerConnection::SendData(const void * a_Data, size_t a_Size) +{ + m_Link->Send(a_Data, a_Size); +} + + + + |