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