• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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