2013-09-27 13:34:46 -04:00
|
|
|
|
|
|
|
// HTTPConnection.cpp
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
// Implements the cHTTPServerConnection class representing a single persistent connection in the HTTP server.
|
2013-09-27 13:34:46 -04:00
|
|
|
|
|
|
|
#include "Globals.h"
|
2015-12-25 13:42:50 -05:00
|
|
|
#include "HTTPServerConnection.h"
|
2016-02-20 05:50:52 -05:00
|
|
|
#include "HTTPMessage.h"
|
2013-09-27 13:34:46 -04:00
|
|
|
#include "HTTPServer.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
cHTTPServerConnection::cHTTPServerConnection(cHTTPServer & a_HTTPServer) :
|
2013-09-27 13:34:46 -04:00
|
|
|
m_HTTPServer(a_HTTPServer),
|
2016-02-20 05:50:52 -05:00
|
|
|
m_Parser(*this),
|
|
|
|
m_CurrentRequest(nullptr)
|
2013-09-27 13:34:46 -04:00
|
|
|
{
|
2013-10-06 10:40:28 -04:00
|
|
|
// LOGD("HTTP: New connection at %p", this);
|
2013-09-27 13:34:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-10-06 10:40:28 -04:00
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
cHTTPServerConnection::~cHTTPServerConnection()
|
2013-10-06 10:40:28 -04:00
|
|
|
{
|
2014-05-01 05:34:15 -04:00
|
|
|
// LOGD("HTTP: Connection deleting: %p", this);
|
2016-02-20 05:50:52 -05:00
|
|
|
m_CurrentRequest.reset();
|
2013-10-06 10:40:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::SendStatusAndReason(int a_StatusCode, const AString & a_Response)
|
2013-09-27 13:34:46 -04:00
|
|
|
{
|
2015-04-19 11:32:44 -04:00
|
|
|
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());
|
2016-02-20 05:50:52 -05:00
|
|
|
m_CurrentRequest.reset();
|
|
|
|
m_Parser.Reset();
|
2013-10-04 14:28:30 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::SendNeedAuth(const AString & a_Realm)
|
2013-10-04 14:28:30 -04:00
|
|
|
{
|
2015-01-24 04:11:34 -05:00
|
|
|
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()));
|
2016-02-20 05:50:52 -05:00
|
|
|
m_CurrentRequest.reset();
|
|
|
|
m_Parser.Reset();
|
2013-09-27 13:34:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-02-20 06:33:27 -05:00
|
|
|
void cHTTPServerConnection::Send(const cHTTPOutgoingResponse & a_Response)
|
2013-09-27 13:34:46 -04:00
|
|
|
{
|
2016-02-20 05:50:52 -05:00
|
|
|
ASSERT(m_CurrentRequest != nullptr);
|
2015-01-24 04:11:34 -05:00
|
|
|
AString toSend;
|
|
|
|
a_Response.AppendToData(toSend);
|
|
|
|
SendData(toSend);
|
2013-09-27 13:34:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::Send(const void * a_Data, size_t a_Size)
|
2013-09-27 13:34:46 -04:00
|
|
|
{
|
2016-02-20 05:50:52 -05:00
|
|
|
ASSERT(m_CurrentRequest != nullptr);
|
2015-01-24 04:11:34 -05:00
|
|
|
// We're sending in Chunked transfer encoding
|
2018-01-03 12:41:16 -05:00
|
|
|
SendData(fmt::format("{0:x}\r\n", a_Size));
|
2015-01-24 04:11:34 -05:00
|
|
|
SendData(a_Data, a_Size);
|
|
|
|
SendData("\r\n");
|
2013-09-27 13:34:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::FinishResponse(void)
|
2013-09-27 13:34:46 -04:00
|
|
|
{
|
2016-02-20 05:50:52 -05:00
|
|
|
ASSERT(m_CurrentRequest != nullptr);
|
2015-01-24 04:11:34 -05:00
|
|
|
SendData("0\r\n\r\n");
|
2016-02-20 05:50:52 -05:00
|
|
|
m_CurrentRequest.reset();
|
|
|
|
m_Parser.Reset();
|
2013-09-27 15:28:41 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::Terminate(void)
|
2013-10-06 10:40:28 -04:00
|
|
|
{
|
2014-10-20 16:55:07 -04:00
|
|
|
if (m_CurrentRequest != nullptr)
|
2013-10-06 10:40:28 -04:00
|
|
|
{
|
|
|
|
m_HTTPServer.RequestFinished(*this, *m_CurrentRequest);
|
|
|
|
}
|
2015-01-24 04:11:34 -05:00
|
|
|
m_Link.reset();
|
2013-10-06 10:40:28 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::OnLinkCreated(cTCPLinkPtr a_Link)
|
2013-09-27 13:34:46 -04:00
|
|
|
{
|
2015-01-24 04:11:34 -05:00
|
|
|
ASSERT(m_Link == nullptr);
|
|
|
|
m_Link = a_Link;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::OnReceivedData(const char * a_Data, size_t a_Size)
|
2015-01-24 04:11:34 -05:00
|
|
|
{
|
|
|
|
ASSERT(m_Link != nullptr);
|
|
|
|
|
2016-02-20 05:50:52 -05:00
|
|
|
m_Parser.Parse(a_Data, a_Size);
|
2013-09-27 13:34:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::OnRemoteClosed(void)
|
2013-09-27 13:34:46 -04:00
|
|
|
{
|
2015-01-24 04:11:34 -05:00
|
|
|
if (m_CurrentRequest != nullptr)
|
|
|
|
{
|
|
|
|
m_HTTPServer.RequestFinished(*this, *m_CurrentRequest);
|
|
|
|
}
|
|
|
|
m_Link.reset();
|
2013-09-27 13:34:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::OnError(int a_ErrorCode, const AString & a_ErrorMsg)
|
2013-09-27 13:34:46 -04:00
|
|
|
{
|
2015-01-24 04:11:34 -05:00
|
|
|
OnRemoteClosed();
|
2013-09-27 13:34:46 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-02-20 05:50:52 -05:00
|
|
|
|
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2015-12-25 13:42:50 -05:00
|
|
|
void cHTTPServerConnection::SendData(const void * a_Data, size_t a_Size)
|
2015-01-24 04:11:34 -05:00
|
|
|
{
|
|
|
|
m_Link->Send(a_Data, a_Size);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2013-09-27 13:34:46 -04:00
|
|
|
|