From 11e0c73ffd23a506c68ae351641a7ca74085ca81 Mon Sep 17 00:00:00 2001 From: madmaxoft Date: Tue, 24 Sep 2013 20:52:37 +0200 Subject: Implemented basic HTTP message header parsing. --- source/WebServer.h | 122 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100644 source/WebServer.h (limited to 'source/WebServer.h') diff --git a/source/WebServer.h b/source/WebServer.h new file mode 100644 index 000000000..1a10e4461 --- /dev/null +++ b/source/WebServer.h @@ -0,0 +1,122 @@ + +// WebServer.h + +// Declares the cWebServer class representing a HTTP webserver that uses cListenThread and cSocketThreads for processing + + + + + +#pragma once + +#include "OSSupport/ListenThread.h" +#include "OSSupport/SocketThreads.h" +#include "../iniFile/iniFile.h" + + + + + +// fwd: +class cWebServer; + + + + + +class cWebRequest : + public cSocketThreads::cCallback +{ +public: + enum + { + HTTP_OK = 200, + HTTP_BAD_REQUEST = 400, + } ; + + cWebRequest(cWebServer & a_WebServer); + + /// Sends HTTP status code together with a_Reason + void SendStatusAndReason(int a_StatusCode, const AString & a_Reason); + +protected: + typedef std::map cNameValueMap; + + cWebServer & m_WebServer; + + AString m_Method; ///< Method of the request (GET / PUT / POST / ...) + AString m_URL; ///< Full URL of the request + cNameValueMap m_Headers; ///< All the headers the request has come with + + AString m_IncomingHeaderData; ///< All the incoming data until the entire header is parsed + + /// Set to true when the header haven't been received yet. If false, receiving the optional body. + bool m_IsReceivingHeaders; + + /// Data that is queued for sending, once the socket becomes writable + AString m_OutgoingData; + + + /// Parses the header in m_IncomingData until the specified end mark + void ParseHeader(size_t a_IdxEnd); + + /** Parses the RequestLine out of m_IncomingHeaderData, up to index a_IdxEnd + Returns the index to the next line, or npos if invalid request + */ + size_t ParseRequestLine(size_t a_IdxEnd); + + /** Parses one header field out of m_IncomingHeaderData, starting at the specified offset, up to offset a_IdxEnd. + Returns the index to the next line, or npos if invalid request. + a_Key is set to the key that was parsed (used for multi-line headers) + */ + size_t ParseHeaderField(size_t a_IdxStart, size_t a_IdxEnd, AString & a_Key); + + /** Parses one header field that is known to be a continuation of previous header. + Returns the index to the next line, or npos if invalid request. + */ + size_t ParseHeaderFieldContinuation(size_t a_IdxStart, size_t a_IdxEnd, AString & a_Key); + + /// Adds a header into m_Headers; appends if key already exists + void AddHeader(const AString & a_Key, const AString & a_Value); + + // cSocketThreads::cCallback overrides: + virtual void DataReceived (const char * a_Data, int a_Size) override; // Data is received from the client + virtual void GetOutgoingData(AString & a_Data) override; // Data can be sent to client + virtual void SocketClosed (void) override; // The socket has been closed for any reason +} ; + +typedef std::vector cWebRequests; + + + + +class cWebServer : + public cListenThread::cCallback +{ +public: + cWebServer(void); + + bool Initialize(cIniFile & a_IniFile); + +protected: + friend class cWebRequest; + + cListenThread m_ListenThreadIPv4; + cListenThread m_ListenThreadIPv6; + + cSocketThreads m_SocketThreads; + + cCriticalSection m_CSRequests; + cWebRequests m_Requests; ///< All the requests that are currently being serviced + + // cListenThread::cCallback overrides: + virtual void OnConnectionAccepted(cSocket & a_Socket) override; + + /// Called by cWebRequest when it finishes parsing its header + void RequestReady(cWebRequest * a_Request); +} ; + + + + + -- cgit v1.2.3