1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
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<AString, AString> 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<cWebRequest *> 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);
} ;
|