diff options
Diffstat (limited to 'source/WebServer.cpp')
-rw-r--r-- | source/WebServer.cpp | 341 |
1 files changed, 0 insertions, 341 deletions
diff --git a/source/WebServer.cpp b/source/WebServer.cpp deleted file mode 100644 index 8f3fa26ae..000000000 --- a/source/WebServer.cpp +++ /dev/null @@ -1,341 +0,0 @@ - -// WebServer.cpp - -// Implements the cWebServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for processing - -#include "Globals.h" -#include "WebServer.h" - - - - - -// Disable MSVC warnings: -#if defined(_MSC_VER) - #pragma warning(push) - #pragma warning(disable:4355) // 'this' : used in base member initializer list -#endif - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cWebRequest: - -cWebRequest::cWebRequest(cWebServer & a_WebServer) : - m_WebServer(a_WebServer), - m_IsReceivingHeaders(true) -{ -} - - - - -void cWebRequest::SendStatusAndReason(int a_StatusCode, const AString & a_Response) -{ - AppendPrintf(m_OutgoingData, "%d %s\r\n\r\n", a_StatusCode, a_Response.c_str()); -} - - - - - -void cWebRequest::ParseHeader(size_t a_IdxEnd) -{ - size_t Next = ParseRequestLine(a_IdxEnd); - if (Next == AString::npos) - { - SendStatusAndReason(HTTP_BAD_REQUEST, "Bad request"); - return; - } - - AString Key; - while (Next < a_IdxEnd) - { - Next = ParseHeaderField(Next, a_IdxEnd, Key); - if (Next == AString::npos) - { - SendStatusAndReason(HTTP_BAD_REQUEST, "Bad request"); - return; - } - } - - m_WebServer.RequestReady(this); -} - - - - -size_t cWebRequest::ParseRequestLine(size_t a_IdxEnd) -{ - // Ignore the initial CRLFs (HTTP spec's "should") - size_t LineStart = 0; - while ( - (LineStart < a_IdxEnd) && - ( - (m_IncomingHeaderData[LineStart] == '\r') || - (m_IncomingHeaderData[LineStart] == '\n') - ) - ) - { - LineStart++; - } - if (LineStart >= a_IdxEnd) - { - return AString::npos; - } - - // Get the Request-Line - size_t LineEnd = m_IncomingHeaderData.find("\r\n", LineStart); - if (LineEnd == AString::npos) - { - return AString::npos; - } - AString RequestLine = m_IncomingHeaderData.substr(LineStart, LineEnd - LineStart); - - // Find the method: - size_t Space = RequestLine.find(" ", LineStart); - if (Space == AString::npos) - { - return AString::npos; - } - m_Method = RequestLine.substr(0, Space); - - // Find the URL: - size_t Space2 = RequestLine.find(" ", Space + 1); - if (Space2 == AString::npos) - { - return AString::npos; - } - m_URL = RequestLine.substr(Space, Space2 - Space); - - // Check that there's HTTP/version at the end - if (strncmp(RequestLine.c_str() + Space2 + 1, "HTTP/1.", 7) != 0) - { - return AString::npos; - } - - return LineEnd + 2; -} - - - - - -size_t cWebRequest::ParseHeaderField(size_t a_IdxStart, size_t a_IdxEnd, AString & a_Key) -{ - if (a_IdxStart >= a_IdxEnd) - { - return a_IdxEnd; - } - if (m_IncomingHeaderData[a_IdxStart] <= ' ') - { - return ParseHeaderFieldContinuation(a_IdxStart + 1, a_IdxEnd, a_Key); - } - size_t ValueIdx = 0; - AString Key; - for (size_t i = a_IdxStart; i < a_IdxEnd; i++) - { - switch (m_IncomingHeaderData[i]) - { - case '\n': - { - if ((ValueIdx == 0) || (i < ValueIdx - 2) || (i < a_IdxStart + 1) || (m_IncomingHeaderData[i - 1] != '\r')) - { - // Invalid header field - no colon or no CR before LF - return AString::npos; - } - AString Value = m_IncomingHeaderData.substr(ValueIdx + 1, i - ValueIdx - 2); - AddHeader(Key, Value); - a_Key = Key; - return i + 1; - } - case ':': - { - if (ValueIdx == 0) - { - Key = m_IncomingHeaderData.substr(a_IdxStart, i - a_IdxStart); - ValueIdx = i; - } - break; - } - case ' ': - case '\t': - { - if (ValueIdx == i - 1) - { - // Value has started in this char, but it is whitespace, so move the start one char further - ValueIdx = i; - } - } - } // switch (char) - } // for i - m_IncomingHeaderData[] - // No header found, return the end-of-data index: - return a_IdxEnd; -} - - - - - -size_t cWebRequest::ParseHeaderFieldContinuation(size_t a_IdxStart, size_t a_IdxEnd, AString & a_Key) -{ - size_t Start = a_IdxStart; - for (size_t i = a_IdxStart; i < a_IdxEnd; i++) - { - if ((m_IncomingHeaderData[i] > ' ') && (Start == a_IdxStart)) - { - Start = i; - } - else if (m_IncomingHeaderData[i] == '\n') - { - if ((i < a_IdxStart + 1) || (m_IncomingHeaderData[i - 1] != '\r')) - { - // There wasn't a CR before this LF - return AString::npos; - } - AString Value = m_IncomingHeaderData.substr(Start, i - Start - 1); - AddHeader(a_Key, Value); - return i + 1; - } - } - // LF not found, how? We found it at the header end (CRLFCRLF) - ASSERT(!"LF not found, wtf?"); - return AString::npos; -} - - - - - -void cWebRequest::AddHeader(const AString & a_Key, const AString & a_Value) -{ - cNameValueMap::iterator itr = m_Headers.find(a_Key); - if (itr == m_Headers.end()) - { - m_Headers[a_Key] = a_Value; - } - else - { - // The header-field key is specified multiple times, combine into comma-separated list (RFC 2616 @ 4.2) - itr->second.append(", "); - itr->second.append(a_Value); - } -} - - - - - -void cWebRequest::DataReceived(const char * a_Data, int a_Size) -{ - if (m_IsReceivingHeaders) - { - // Start searching 3 chars from the end of the already received data, if available: - size_t SearchStart = m_IncomingHeaderData.size(); - SearchStart = (SearchStart > 3) ? SearchStart - 3 : 0; - - m_IncomingHeaderData.append(a_Data, a_Size); - - // Parse the header, if it is complete: - size_t idxEnd = m_IncomingHeaderData.find("\r\n\r\n", SearchStart); - if (idxEnd != AString::npos) - { - ParseHeader(idxEnd + 2); - m_IsReceivingHeaders = false; - } - } - else - { - // TODO: Receive the body, and the next request (If HTTP/1.1 keepalive - } -} - - - - - -void cWebRequest::GetOutgoingData(AString & a_Data) -{ - std::swap(a_Data, m_OutgoingData); -} - - - - - -void cWebRequest::SocketClosed(void) -{ - // TODO: m_WebServer.RequestFinished(this); -} - - - - - -/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// cWebServer: - -cWebServer::cWebServer(void) : - m_ListenThreadIPv4(*this, cSocket::IPv4, "WebServer IPv4"), - m_ListenThreadIPv6(*this, cSocket::IPv6, "WebServer IPv6"), - m_SocketThreads() -{ -} - - - - - -bool cWebServer::Initialize(cIniFile & a_IniFile) -{ - if (!a_IniFile.GetValueSetB("WebAdmin", "Enabled", false)) - { - // The WebAdmin is disabled - return true; - } - bool HasAnyPort; - HasAnyPort = m_ListenThreadIPv4.Initialize(a_IniFile.GetValueSet("WebAdmin", "Port", "8081")); - HasAnyPort = m_ListenThreadIPv6.Initialize(a_IniFile.GetValueSet("WebAdmin", "PortsIPv6", "8082, 3300")) || HasAnyPort; - if (!HasAnyPort) - { - LOG("WebAdmin is disabled"); - return false; - } - if (!m_ListenThreadIPv4.Start()) - { - return false; - } - if (!m_ListenThreadIPv6.Start()) - { - m_ListenThreadIPv4.Stop(); - return false; - } - return true; -} - - - - - -void cWebServer::OnConnectionAccepted(cSocket & a_Socket) -{ - cWebRequest * Request = new cWebRequest(*this); - m_SocketThreads.AddClient(a_Socket, Request); - cCSLock Lock(m_CSRequests); - m_Requests.push_back(Request); -} - - - - - -void cWebServer::RequestReady(cWebRequest * a_Request) -{ - a_Request->SendStatusAndReason(cWebRequest::HTTP_OK, "Hello"); -} - - - - |