1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/server/http_server.h"
6
7 #include <utility>
8
9 #include "base/compiler_specific.h"
10 #include "base/functional/bind.h"
11 #include "base/location.h"
12 #include "base/logging.h"
13 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h"
15 #include "base/sys_byteorder.h"
16 #include "base/task/single_thread_task_runner.h"
17 #include "build/build_config.h"
18 #include "net/base/net_errors.h"
19 #include "net/server/http_connection.h"
20 #include "net/server/http_server_request_info.h"
21 #include "net/server/http_server_response_info.h"
22 #include "net/server/web_socket.h"
23 #include "net/socket/server_socket.h"
24 #include "net/socket/stream_socket.h"
25 #include "net/socket/tcp_server_socket.h"
26
27 namespace net {
28
29 namespace {
30
31 constexpr NetworkTrafficAnnotationTag
32 kHttpServerErrorResponseTrafficAnnotation =
33 DefineNetworkTrafficAnnotation("http_server_error_response",
34 R"(
35 semantics {
36 sender: "HTTP Server"
37 description: "Error response from the built-in HTTP server."
38 trigger: "Sending a request to the HTTP server that it can't handle."
39 data: "A 500 error code."
40 destination: OTHER
41 destination_other: "Any destination the consumer selects."
42 }
43 policy {
44 cookies_allowed: NO
45 setting:
46 "This request cannot be disabled in settings. However it will never "
47 "be made unless user activates an HTTP server."
48 policy_exception_justification:
49 "Not implemented, not used if HTTP Server is not activated."
50 })");
51
52 } // namespace
53
HttpServer(std::unique_ptr<ServerSocket> server_socket,HttpServer::Delegate * delegate)54 HttpServer::HttpServer(std::unique_ptr<ServerSocket> server_socket,
55 HttpServer::Delegate* delegate)
56 : server_socket_(std::move(server_socket)), delegate_(delegate) {
57 DCHECK(server_socket_);
58 // Start accepting connections in next run loop in case when delegate is not
59 // ready to get callbacks.
60 base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
61 FROM_HERE, base::BindOnce(&HttpServer::DoAcceptLoop,
62 weak_ptr_factory_.GetWeakPtr()));
63 }
64
65 HttpServer::~HttpServer() = default;
66
67 void HttpServer::AcceptWebSocket(
68 int connection_id,
69 const HttpServerRequestInfo& request,
70 NetworkTrafficAnnotationTag traffic_annotation) {
71 HttpConnection* connection = FindConnection(connection_id);
72 if (connection == nullptr)
73 return;
74 DCHECK(connection->web_socket());
75 connection->web_socket()->Accept(request, traffic_annotation);
76 }
77
78 void HttpServer::SendOverWebSocket(
79 int connection_id,
80 base::StringPiece data,
81 NetworkTrafficAnnotationTag traffic_annotation) {
82 HttpConnection* connection = FindConnection(connection_id);
83 if (connection == nullptr)
84 return;
85 DCHECK(connection->web_socket());
86 connection->web_socket()->Send(
87 data, WebSocketFrameHeader::OpCodeEnum::kOpCodeText, traffic_annotation);
88 }
89
90 void HttpServer::SendRaw(int connection_id,
91 const std::string& data,
92 NetworkTrafficAnnotationTag traffic_annotation) {
93 HttpConnection* connection = FindConnection(connection_id);
94 if (connection == nullptr)
95 return;
96
97 bool writing_in_progress = !connection->write_buf()->IsEmpty();
98 if (connection->write_buf()->Append(data) && !writing_in_progress)
99 DoWriteLoop(connection, traffic_annotation);
100 }
101
102 void HttpServer::SendResponse(int connection_id,
103 const HttpServerResponseInfo& response,
104 NetworkTrafficAnnotationTag traffic_annotation) {
105 SendRaw(connection_id, response.Serialize(), traffic_annotation);
106 }
107
108 void HttpServer::Send(int connection_id,
109 HttpStatusCode status_code,
110 const std::string& data,
111 const std::string& content_type,
112 NetworkTrafficAnnotationTag traffic_annotation) {
113 HttpServerResponseInfo response(status_code);
114 response.SetContentHeaders(data.size(), content_type);
115 SendResponse(connection_id, response, traffic_annotation);
116 SendRaw(connection_id, data, traffic_annotation);
117 }
118
119 void HttpServer::Send200(int connection_id,
120 const std::string& data,
121 const std::string& content_type,
122 NetworkTrafficAnnotationTag traffic_annotation) {
123 Send(connection_id, HTTP_OK, data, content_type, traffic_annotation);
124 }
125
126 void HttpServer::Send404(int connection_id,
127 NetworkTrafficAnnotationTag traffic_annotation) {
128 SendResponse(connection_id, HttpServerResponseInfo::CreateFor404(),
129 traffic_annotation);
130 }
131
132 void HttpServer::Send500(int connection_id,
133 const std::string& message,
134 NetworkTrafficAnnotationTag traffic_annotation) {
135 SendResponse(connection_id, HttpServerResponseInfo::CreateFor500(message),
136 traffic_annotation);
137 }
138
139 void HttpServer::Close(int connection_id) {
140 auto it = id_to_connection_.find(connection_id);
141 if (it == id_to_connection_.end())
142 return;
143
144 std::unique_ptr<HttpConnection> connection = std::move(it->second);
145 id_to_connection_.erase(it);
146 delegate_->OnClose(connection_id);
147
148 // The call stack might have callbacks which still have the pointer of
149 // connection. Instead of referencing connection with ID all the time,
150 // destroys the connection in next run loop to make sure any pending
151 // callbacks in the call stack return.
152 base::SingleThreadTaskRunner::GetCurrentDefault()->DeleteSoon(
153 FROM_HERE, connection.release());
154 }
155
156 int HttpServer::GetLocalAddress(IPEndPoint* address) {
157 return server_socket_->GetLocalAddress(address);
158 }
159
160 void HttpServer::SetReceiveBufferSize(int connection_id, int32_t size) {
161 HttpConnection* connection = FindConnection(connection_id);
162 if (connection)
163 connection->read_buf()->set_max_buffer_size(size);
164 }
165
166 void HttpServer::SetSendBufferSize(int connection_id, int32_t size) {
167 HttpConnection* connection = FindConnection(connection_id);
168 if (connection)
169 connection->write_buf()->set_max_buffer_size(size);
170 }
171
172 void HttpServer::DoAcceptLoop() {
173 int rv;
174 do {
175 rv = server_socket_->Accept(&accepted_socket_,
176 base::BindOnce(&HttpServer::OnAcceptCompleted,
177 weak_ptr_factory_.GetWeakPtr()));
178 if (rv == ERR_IO_PENDING)
179 return;
180 rv = HandleAcceptResult(rv);
181 } while (rv == OK);
182 }
183
184 void HttpServer::OnAcceptCompleted(int rv) {
185 if (HandleAcceptResult(rv) == OK)
186 DoAcceptLoop();
187 }
188
189 int HttpServer::HandleAcceptResult(int rv) {
190 if (rv < 0) {
191 LOG(ERROR) << "Accept error: rv=" << rv;
192 return rv;
193 }
194
195 std::unique_ptr<HttpConnection> connection_ptr =
196 std::make_unique<HttpConnection>(++last_id_, std::move(accepted_socket_));
197 HttpConnection* connection = connection_ptr.get();
198 id_to_connection_[connection->id()] = std::move(connection_ptr);
199 delegate_->OnConnect(connection->id());
200 if (!HasClosedConnection(connection))
201 DoReadLoop(connection);
202 return OK;
203 }
204
205 void HttpServer::DoReadLoop(HttpConnection* connection) {
206 int rv;
207 do {
208 HttpConnection::ReadIOBuffer* read_buf = connection->read_buf();
209 // Increases read buffer size if necessary.
210 if (read_buf->RemainingCapacity() == 0 && !read_buf->IncreaseCapacity()) {
211 Close(connection->id());
212 return;
213 }
214
215 rv = connection->socket()->Read(
216 read_buf, read_buf->RemainingCapacity(),
217 base::BindOnce(&HttpServer::OnReadCompleted,
218 weak_ptr_factory_.GetWeakPtr(), connection->id()));
219 if (rv == ERR_IO_PENDING)
220 return;
221 rv = HandleReadResult(connection, rv);
222 } while (rv == OK);
223 }
224
225 void HttpServer::OnReadCompleted(int connection_id, int rv) {
226 HttpConnection* connection = FindConnection(connection_id);
227 if (!connection) // It might be closed right before by write error.
228 return;
229
230 if (HandleReadResult(connection, rv) == OK)
231 DoReadLoop(connection);
232 }
233
234 int HttpServer::HandleReadResult(HttpConnection* connection, int rv) {
235 if (rv <= 0) {
236 Close(connection->id());
237 return rv == 0 ? ERR_CONNECTION_CLOSED : rv;
238 }
239
240 HttpConnection::ReadIOBuffer* read_buf = connection->read_buf();
241 read_buf->DidRead(rv);
242
243 // Handles http requests or websocket messages.
244 while (read_buf->GetSize() > 0) {
245 if (connection->web_socket()) {
246 std::string message;
247 WebSocket::ParseResult result = connection->web_socket()->Read(&message);
248 if (result == WebSocket::FRAME_INCOMPLETE)
249 break;
250
251 if (result == WebSocket::FRAME_CLOSE ||
252 result == WebSocket::FRAME_ERROR) {
253 Close(connection->id());
254 return ERR_CONNECTION_CLOSED;
255 }
256 if (result == WebSocket::FRAME_OK_FINAL)
257 delegate_->OnWebSocketMessage(connection->id(), std::move(message));
258 if (HasClosedConnection(connection))
259 return ERR_CONNECTION_CLOSED;
260 continue;
261 }
262
263 HttpServerRequestInfo request;
264 size_t pos = 0;
265 if (!ParseHeaders(read_buf->StartOfBuffer(), read_buf->GetSize(),
266 &request, &pos)) {
267 // An error has occured. Close the connection.
268 Close(connection->id());
269 return ERR_CONNECTION_CLOSED;
270 } else if (!pos) {
271 // If pos is 0, all the data in read_buf has been consumed, but the
272 // headers have not been fully parsed yet. Continue parsing when more data
273 // rolls in.
274 break;
275 }
276
277 // Sets peer address if exists.
278 connection->socket()->GetPeerAddress(&request.peer);
279
280 if (request.HasHeaderValue("connection", "upgrade") &&
281 request.HasHeaderValue("upgrade", "websocket")) {
282 connection->SetWebSocket(std::make_unique<WebSocket>(this, connection));
283 read_buf->DidConsume(pos);
284 delegate_->OnWebSocketRequest(connection->id(), request);
285 if (HasClosedConnection(connection))
286 return ERR_CONNECTION_CLOSED;
287 continue;
288 }
289
290 const char kContentLength[] = "content-length";
291 if (request.headers.count(kContentLength) > 0) {
292 size_t content_length = 0;
293 const size_t kMaxBodySize = 100 << 20;
294 if (!base::StringToSizeT(request.GetHeaderValue(kContentLength),
295 &content_length) ||
296 content_length > kMaxBodySize) {
297 SendResponse(connection->id(),
298 HttpServerResponseInfo::CreateFor500(
299 "request content-length too big or unknown."),
300 kHttpServerErrorResponseTrafficAnnotation);
301 Close(connection->id());
302 return ERR_CONNECTION_CLOSED;
303 }
304
305 if (read_buf->GetSize() - pos < content_length)
306 break; // Not enough data was received yet.
307 request.data.assign(read_buf->StartOfBuffer() + pos, content_length);
308 pos += content_length;
309 }
310
311 read_buf->DidConsume(pos);
312 delegate_->OnHttpRequest(connection->id(), request);
313 if (HasClosedConnection(connection))
314 return ERR_CONNECTION_CLOSED;
315 }
316
317 return OK;
318 }
319
320 void HttpServer::DoWriteLoop(HttpConnection* connection,
321 NetworkTrafficAnnotationTag traffic_annotation) {
322 int rv = OK;
323 HttpConnection::QueuedWriteIOBuffer* write_buf = connection->write_buf();
324 while (rv == OK && write_buf->GetSizeToWrite() > 0) {
325 rv = connection->socket()->Write(
326 write_buf, write_buf->GetSizeToWrite(),
327 base::BindOnce(&HttpServer::OnWriteCompleted,
328 weak_ptr_factory_.GetWeakPtr(), connection->id(),
329 traffic_annotation),
330 traffic_annotation);
331 if (rv == ERR_IO_PENDING || rv == OK)
332 return;
333 rv = HandleWriteResult(connection, rv);
334 }
335 }
336
337 void HttpServer::OnWriteCompleted(
338 int connection_id,
339 NetworkTrafficAnnotationTag traffic_annotation,
340 int rv) {
341 HttpConnection* connection = FindConnection(connection_id);
342 if (!connection) // It might be closed right before by read error.
343 return;
344
345 if (HandleWriteResult(connection, rv) == OK)
346 DoWriteLoop(connection, traffic_annotation);
347 }
348
349 int HttpServer::HandleWriteResult(HttpConnection* connection, int rv) {
350 if (rv < 0) {
351 Close(connection->id());
352 return rv;
353 }
354
355 connection->write_buf()->DidConsume(rv);
356 return OK;
357 }
358
359 namespace {
360
361 //
362 // HTTP Request Parser
363 // This HTTP request parser uses a simple state machine to quickly parse
364 // through the headers. The parser is not 100% complete, as it is designed
365 // for use in this simple test driver.
366 //
367 // Known issues:
368 // - does not handle whitespace on first HTTP line correctly. Expects
369 // a single space between the method/url and url/protocol.
370
371 // Input character types.
372 enum header_parse_inputs {
373 INPUT_LWS,
374 INPUT_CR,
375 INPUT_LF,
376 INPUT_COLON,
377 INPUT_DEFAULT,
378 MAX_INPUTS,
379 };
380
381 // Parser states.
382 enum header_parse_states {
383 ST_METHOD, // Receiving the method
384 ST_URL, // Receiving the URL
385 ST_PROTO, // Receiving the protocol
386 ST_HEADER, // Starting a Request Header
387 ST_NAME, // Receiving a request header name
388 ST_SEPARATOR, // Receiving the separator between header name and value
389 ST_VALUE, // Receiving a request header value
390 ST_DONE, // Parsing is complete and successful
391 ST_ERR, // Parsing encountered invalid syntax.
392 MAX_STATES
393 };
394
395 // State transition table
396 const int parser_state[MAX_STATES][MAX_INPUTS] = {
397 /* METHOD */ {ST_URL, ST_ERR, ST_ERR, ST_ERR, ST_METHOD},
398 /* URL */ {ST_PROTO, ST_ERR, ST_ERR, ST_URL, ST_URL},
399 /* PROTOCOL */ {ST_ERR, ST_HEADER, ST_NAME, ST_ERR, ST_PROTO},
400 /* HEADER */ {ST_ERR, ST_ERR, ST_NAME, ST_ERR, ST_ERR},
401 /* NAME */ {ST_SEPARATOR, ST_DONE, ST_ERR, ST_VALUE, ST_NAME},
402 /* SEPARATOR */ {ST_SEPARATOR, ST_ERR, ST_ERR, ST_VALUE, ST_ERR},
403 /* VALUE */ {ST_VALUE, ST_HEADER, ST_NAME, ST_VALUE, ST_VALUE},
404 /* DONE */ {ST_DONE, ST_DONE, ST_DONE, ST_DONE, ST_DONE},
405 /* ERR */ {ST_ERR, ST_ERR, ST_ERR, ST_ERR, ST_ERR}};
406
407 // Convert an input character to the parser's input token.
408 int charToInput(char ch) {
409 switch (ch) {
410 case ' ':
411 case '\t':
412 return INPUT_LWS;
413 case '\r':
414 return INPUT_CR;
415 case '\n':
416 return INPUT_LF;
417 case ':':
418 return INPUT_COLON;
419 }
420 return INPUT_DEFAULT;
421 }
422
423 } // namespace
424
ParseHeaders(const char * data,size_t data_len,HttpServerRequestInfo * info,size_t * ppos)425 bool HttpServer::ParseHeaders(const char* data,
426 size_t data_len,
427 HttpServerRequestInfo* info,
428 size_t* ppos) {
429 size_t& pos = *ppos;
430 int state = ST_METHOD;
431 std::string buffer;
432 std::string header_name;
433 std::string header_value;
434 while (pos < data_len) {
435 char ch = data[pos++];
436 int input = charToInput(ch);
437 int next_state = parser_state[state][input];
438
439 bool transition = (next_state != state);
440 HttpServerRequestInfo::HeadersMap::iterator it;
441 if (transition) {
442 // Do any actions based on state transitions.
443 switch (state) {
444 case ST_METHOD:
445 info->method = buffer;
446 buffer.clear();
447 break;
448 case ST_URL:
449 info->path = buffer;
450 buffer.clear();
451 break;
452 case ST_PROTO:
453 if (buffer != "HTTP/1.1") {
454 LOG(ERROR) << "Cannot handle request with protocol: " << buffer;
455 next_state = ST_ERR;
456 }
457 buffer.clear();
458 break;
459 case ST_NAME:
460 header_name = base::ToLowerASCII(buffer);
461 buffer.clear();
462 break;
463 case ST_VALUE:
464 base::TrimWhitespaceASCII(buffer, base::TRIM_LEADING, &header_value);
465 it = info->headers.find(header_name);
466 // See the second paragraph ("A sender MUST NOT generate multiple
467 // header fields...") of tools.ietf.org/html/rfc7230#section-3.2.2.
468 if (it == info->headers.end()) {
469 info->headers[header_name] = header_value;
470 } else {
471 it->second.append(",");
472 it->second.append(header_value);
473 }
474 buffer.clear();
475 break;
476 case ST_SEPARATOR:
477 break;
478 }
479 state = next_state;
480 } else {
481 // Do any actions based on current state
482 switch (state) {
483 case ST_METHOD:
484 case ST_URL:
485 case ST_PROTO:
486 case ST_VALUE:
487 case ST_NAME:
488 buffer.append(&ch, 1);
489 break;
490 case ST_DONE:
491 // We got CR to get this far, also need the LF
492 return (input == INPUT_LF);
493 case ST_ERR:
494 return false;
495 }
496 }
497 }
498 // No more characters, but we haven't finished parsing yet. Signal this to
499 // the caller by setting |pos| to zero.
500 pos = 0;
501 return true;
502 }
503
FindConnection(int connection_id)504 HttpConnection* HttpServer::FindConnection(int connection_id) {
505 auto it = id_to_connection_.find(connection_id);
506 if (it == id_to_connection_.end())
507 return nullptr;
508 return it->second.get();
509 }
510
511 // This is called after any delegate callbacks are called to check if Close()
512 // has been called during callback processing. Using the pointer of connection,
513 // |connection| is safe here because Close() deletes the connection in next run
514 // loop.
HasClosedConnection(HttpConnection * connection)515 bool HttpServer::HasClosedConnection(HttpConnection* connection) {
516 return FindConnection(connection->id()) != connection;
517 }
518
519 } // namespace net
520