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