Cuberite
A lightweight, fast and extensible game server for Minecraft
HTTPServerConnection.cpp
Go to the documentation of this file.
1 
2 // HTTPConnection.cpp
3 
4 // Implements the cHTTPServerConnection class representing a single persistent connection in the HTTP server.
5 
6 #include "Globals.h"
7 #include "HTTPServerConnection.h"
8 #include "HTTPMessage.h"
9 #include "HTTPServer.h"
10 
11 
12 
13 
14 
16  m_HTTPServer(a_HTTPServer),
17  m_Parser(*this),
18  m_CurrentRequest(nullptr)
19 {
20  // LOGD("HTTP: New connection at %p", this);
21 }
22 
23 
24 
25 
26 
28 {
29  // LOGD("HTTP: Connection deleting: %p", this);
30  m_CurrentRequest.reset();
31 }
32 
33 
34 
35 
36 
37 void cHTTPServerConnection::SendStatusAndReason(int a_StatusCode, const AString & a_Response)
38 {
39  SendData(Printf("HTTP/1.1 %d %s\r\n", a_StatusCode, a_Response.c_str()));
40  SendData(Printf("Content-Length: %u\r\n\r\n", static_cast<unsigned>(a_Response.size())));
41  SendData(a_Response.data(), a_Response.size());
42  m_CurrentRequest.reset();
43  m_Parser.Reset();
44 }
45 
46 
47 
48 
49 
51 {
52  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()));
53  m_CurrentRequest.reset();
54  m_Parser.Reset();
55 }
56 
57 
58 
59 
60 
62 {
63  ASSERT(m_CurrentRequest != nullptr);
64  AString toSend;
65  a_Response.AppendToData(toSend);
66  SendData(toSend);
67 }
68 
69 
70 
71 
72 
73 void cHTTPServerConnection::Send(const void * a_Data, size_t a_Size)
74 {
75  ASSERT(m_CurrentRequest != nullptr);
76  // We're sending in Chunked transfer encoding
77  SendData(fmt::format("{0:x}\r\n", a_Size));
78  SendData(a_Data, a_Size);
79  SendData("\r\n");
80 }
81 
82 
83 
84 
85 
87 {
88  ASSERT(m_CurrentRequest != nullptr);
89  SendData("0\r\n\r\n");
90  m_CurrentRequest.reset();
91  m_Parser.Reset();
92 }
93 
94 
95 
96 
97 
99 {
100  if (m_CurrentRequest != nullptr)
101  {
103  }
104  m_Link.reset();
105 }
106 
107 
108 
109 
110 
112 {
113  ASSERT(m_Link == nullptr);
114  m_Link = a_Link;
115 }
116 
117 
118 
119 
120 
121 void cHTTPServerConnection::OnReceivedData(const char * a_Data, size_t a_Size)
122 {
123  ASSERT(m_Link != nullptr);
124 
125  m_Parser.Parse(a_Data, a_Size);
126 }
127 
128 
129 
130 
131 
133 {
134  if (m_CurrentRequest != nullptr)
135  {
137  }
138  m_Link.reset();
139 }
140 
141 
142 
143 
144 
145 void cHTTPServerConnection::OnError(int a_ErrorCode, const AString & a_ErrorMsg)
146 {
147  OnRemoteClosed();
148 }
149 
150 
151 
152 
153 
154 void cHTTPServerConnection::OnError(const AString & a_ErrorDescription)
155 {
156  OnRemoteClosed();
157 }
158 
159 
160 
161 
162 
164 {
165  // Create a new request object for this request:
166  auto split = StringSplit(a_FirstLine, " ");
167  if (split.size() < 2)
168  {
169  // Invalid request line. We need at least the Method and URL
170  OnRemoteClosed();
171  return;
172  }
173  m_CurrentRequest.reset(new cHTTPIncomingRequest(split[0], split[1]));
174 }
175 
176 
177 
178 
179 
180 void cHTTPServerConnection::OnHeaderLine(const AString & a_Key, const AString & a_Value)
181 {
182  if (m_CurrentRequest == nullptr)
183  {
184  return;
185  }
186  m_CurrentRequest->AddHeader(a_Key, a_Value);
187 }
188 
189 
190 
191 
192 
194 {
195  if (m_CurrentRequest == nullptr)
196  {
197  return;
198  }
200 }
201 
202 
203 
204 
205 
206 void cHTTPServerConnection::OnBodyData(const void * a_Data, size_t a_Size)
207 {
208  if (m_CurrentRequest == nullptr)
209  {
210  return;
211  }
212  m_HTTPServer.RequestBody(*this, *m_CurrentRequest, a_Data, a_Size);
213 }
214 
215 
216 
217 
218 
220 {
221  // Process the request and reset:
223  m_CurrentRequest.reset();
224  m_Parser.Reset();
225 }
226 
227 
228 
229 
230 
231 void cHTTPServerConnection::SendData(const void * a_Data, size_t a_Size)
232 {
233  m_Link->Send(a_Data, a_Size);
234 }
235 
236 
237 
238 
cHTTPMessageParser m_Parser
The parser responsible for reading the requests.
void RequestBody(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request, const void *a_Data, size_t a_Size)
Called by cHTTPConenction when it receives more data for the request body.
Definition: HTTPServer.cpp:217
void AppendToData(AString &a_DataStream) const
Appends the response to the specified datastream - response line and headers.
Definition: HTTPMessage.cpp:81
void NewRequest(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request)
Called by cHTTPServerConnection when it finishes parsing the request header.
Definition: HTTPServer.cpp:208
Provides storage for an incoming HTTP request.
Definition: HTTPMessage.h:85
cHTTPServerConnection(cHTTPServer &a_HTTPServer)
Creates a new instance, connected to the specified HTTP server instance.
virtual void OnHeaderLine(const AString &a_Key, const AString &a_Value) override
Called when a single header line is parsed.
Stores outgoing response headers and serializes them to an HTTP data stream.
Definition: HTTPMessage.h:67
void Terminate(void)
Terminates the connection; finishes any request being currently processed.
void Reset(void)
Resets the parser to the initial state, so that a new request can be parsed.
virtual void OnBodyFinished(void) override
Called when the entire body has been reported by OnBodyData().
virtual void OnBodyData(const void *a_Data, size_t a_Size) override
Called for each chunk of the incoming body data.
virtual void OnLinkCreated(cTCPLinkPtr a_Link) override
The link instance has been created, remember it.
cHTTPServer & m_HTTPServer
The HTTP server instance that we&#39;re attached to.
Definition: HTTPServer.cpp:43
virtual ~cHTTPServerConnection() override
virtual void OnError(int a_ErrorCode, const AString &a_ErrorMsg) override
An error has occurred on the socket.
virtual void SendData(const void *a_Data, size_t a_Size)
Called to send raw data over the link.
virtual void OnHeadersFinished(void) override
Called when all the headers have been parsed.
void SendStatusAndReason(int a_StatusCode, const AString &a_Reason)
Sends HTTP status code together with a_Reason (used for HTTP errors).
cTCPLinkPtr m_Link
The network link attached to this connection.
cHTTPServer & m_HTTPServer
The parent webserver that is to be notified of events on this connection.
std::shared_ptr< cTCPLink > cTCPLinkPtr
Definition: Network.h:17
AString & Printf(AString &str, const char *format, fmt::ArgList args)
Output the formatted text into the string.
Definition: StringUtils.cpp:55
void SendNeedAuth(const AString &a_Realm)
Sends the "401 unauthorized" reply together with instructions on authorizing, using the specified rea...
virtual void OnRemoteClosed(void) override
The socket has been closed for any reason.
void FinishResponse(void)
Indicates that the current response is finished, gets ready for receiving another request (HTTP 1...
#define ASSERT(x)
Definition: Globals.h:335
std::unique_ptr< cHTTPIncomingRequest > m_CurrentRequest
The request being currently received Valid only between having parsed the headers and finishing recei...
virtual void OnReceivedData(const char *a_Data, size_t a_Size) override
Data is received from the client.
std::string AString
Definition: StringUtils.h:13
virtual void OnFirstLine(const AString &a_FirstLine) override
Called when the first line of the request or response is fully parsed.
void Send(const cHTTPOutgoingResponse &a_Response)
Sends the headers contained in a_Response.
AStringVector StringSplit(const AString &str, const AString &delim)
Split the string at any of the listed delimiters.
Definition: StringUtils.cpp:76
void RequestFinished(cHTTPServerConnection &a_Connection, cHTTPIncomingRequest &a_Request)
Called by cHTTPServerConnection when it detects that the request has finished (all of its body has be...
Definition: HTTPServer.cpp:226
size_t Parse(const char *a_Data, size_t a_Size)
Parses the incoming data and calls the appropriate callbacks.