• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 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/test/embedded_test_server/http2_connection.h"
6 
7 #include <memory>
8 #include <string_view>
9 
10 #include "base/functional/bind.h"
11 #include "base/functional/callback_helpers.h"
12 #include "base/memory/raw_ptr.h"
13 #include "base/memory/raw_ref.h"
14 #include "base/strings/strcat.h"
15 #include "base/task/sequenced_task_runner.h"
16 #include "net/http/http_response_headers.h"
17 #include "net/http/http_status_code.h"
18 #include "net/socket/stream_socket.h"
19 #include "net/ssl/ssl_info.h"
20 #include "net/test/embedded_test_server/embedded_test_server.h"
21 #include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
22 
23 namespace net {
24 
25 namespace {
26 
27 using http2::adapter::Http2VisitorInterface;
28 
GenerateHeaders(HttpStatusCode status,base::StringPairs headers)29 std::vector<http2::adapter::Header> GenerateHeaders(HttpStatusCode status,
30                                                     base::StringPairs headers) {
31   std::vector<http2::adapter::Header> response_vector;
32   response_vector.emplace_back(
33       http2::adapter::HeaderRep(std::string(":status")),
34       http2::adapter::HeaderRep(base::NumberToString(status)));
35   for (const auto& header : headers) {
36     // Connection (and related) headers are considered malformed and will
37     // result in a client error
38     if (base::EqualsCaseInsensitiveASCII(header.first, "connection"))
39       continue;
40     response_vector.emplace_back(
41         http2::adapter::HeaderRep(base::ToLowerASCII(header.first)),
42         http2::adapter::HeaderRep(header.second));
43   }
44 
45   return response_vector;
46 }
47 
48 }  // namespace
49 
50 namespace test_server {
51 
52 // Corresponds to an HTTP/2 stream
53 class Http2Connection::ResponseDelegate : public HttpResponseDelegate {
54  public:
ResponseDelegate(Http2Connection * connection,StreamId stream_id)55   ResponseDelegate(Http2Connection* connection, StreamId stream_id)
56       : stream_id_(stream_id), connection_(connection) {}
57   ~ResponseDelegate() override = default;
58   ResponseDelegate(const ResponseDelegate&) = delete;
59   ResponseDelegate& operator=(const ResponseDelegate&) = delete;
60 
AddResponse(std::unique_ptr<HttpResponse> response)61   void AddResponse(std::unique_ptr<HttpResponse> response) override {
62     responses_.push_back(std::move(response));
63   }
64 
SendResponseHeaders(HttpStatusCode status,const std::string & status_reason,const base::StringPairs & headers)65   void SendResponseHeaders(HttpStatusCode status,
66                            const std::string& status_reason,
67                            const base::StringPairs& headers) override {
68     connection_->adapter()->SubmitResponse(stream_id_,
69                                            GenerateHeaders(status, headers),
70                                            /*end_stream=*/false);
71     connection_->SendIfNotProcessing();
72   }
73 
SendRawResponseHeaders(const std::string & headers)74   void SendRawResponseHeaders(const std::string& headers) override {
75     scoped_refptr<HttpResponseHeaders> parsed_headers =
76         HttpResponseHeaders::TryToCreate(headers);
77     if (parsed_headers->response_code() == 0) {
78       connection_->OnConnectionError(ConnectionError::kParseError);
79       LOG(ERROR) << "raw headers could not be parsed";
80     }
81     base::StringPairs header_pairs;
82     size_t iter = 0;
83     std::string key, value;
84     while (parsed_headers->EnumerateHeaderLines(&iter, &key, &value))
85       header_pairs.emplace_back(key, value);
86     SendResponseHeaders(
87         static_cast<HttpStatusCode>(parsed_headers->response_code()),
88         /*status_reason=*/"", header_pairs);
89   }
90 
SendContents(const std::string & contents,base::OnceClosure callback)91   void SendContents(const std::string& contents,
92                     base::OnceClosure callback) override {
93     chunks_.push(std::move(contents));
94     send_completion_callback_ = std::move(callback);
95     connection_->adapter()->ResumeStream(stream_id_);
96     connection_->SendIfNotProcessing();
97   }
98 
FinishResponse()99   void FinishResponse() override {
100     last_frame_ = true;
101     connection_->adapter()->ResumeStream(stream_id_);
102     connection_->SendIfNotProcessing();
103   }
104 
SendContentsAndFinish(const std::string & contents)105   void SendContentsAndFinish(const std::string& contents) override {
106     last_frame_ = true;
107     SendContents(contents, base::DoNothing());
108   }
109 
SendHeadersContentAndFinish(HttpStatusCode status,const std::string & status_reason,const base::StringPairs & headers,const std::string & contents)110   void SendHeadersContentAndFinish(HttpStatusCode status,
111                                    const std::string& status_reason,
112                                    const base::StringPairs& headers,
113                                    const std::string& contents) override {
114     chunks_.push(std::move(contents));
115     last_frame_ = true;
116     connection_->adapter()->SubmitResponse(stream_id_,
117                                            GenerateHeaders(status, headers),
118                                            /*end_stream=*/false);
119     connection_->SendIfNotProcessing();
120   }
GetWeakPtr()121   base::WeakPtr<ResponseDelegate> GetWeakPtr() {
122     return weak_factory_.GetWeakPtr();
123   }
124 
OnReadyToSendDataForStream(StreamId stream_id,size_t max_length)125   Http2VisitorInterface::DataFrameHeaderInfo OnReadyToSendDataForStream(
126       StreamId stream_id,
127       size_t max_length) {
128     if (chunks_.empty()) {
129       return {Http2VisitorInterface::kSendBlocked, false, false};
130     }
131 
132     bool finished = (chunks_.size() <= 1) &&
133                     (chunks_.front().size() <= max_length) && last_frame_;
134 
135     return {static_cast<int64_t>(std::min(chunks_.front().size(), max_length)),
136             finished, finished};
137   }
138 
SendDataFrame(StreamId stream_id,std::string_view frame_header,size_t payload_length)139   bool SendDataFrame(StreamId stream_id,
140                      std::string_view frame_header,
141                      size_t payload_length) {
142     std::string concatenated =
143         base::StrCat({frame_header, chunks_.front().substr(0, payload_length)});
144     const int64_t result = connection_->OnReadyToSend(concatenated);
145     // Write encountered error.
146     if (result < 0) {
147       connection_->OnConnectionError(ConnectionError::kSendError);
148       return false;
149     }
150 
151     // Write blocked.
152     if (result == 0) {
153       connection_->blocked_streams_.insert(stream_id);
154       return false;
155     }
156 
157     if (static_cast<const size_t>(result) < concatenated.size()) {
158       // Probably need to handle this better within this test class.
159       QUICHE_LOG(DFATAL)
160           << "DATA frame not fully flushed. Connection will be corrupt!";
161       connection_->OnConnectionError(ConnectionError::kSendError);
162       return false;
163     }
164 
165     chunks_.front().erase(0, payload_length);
166 
167     if (chunks_.front().empty()) {
168       chunks_.pop();
169     }
170 
171     if (chunks_.empty() && send_completion_callback_) {
172       std::move(send_completion_callback_).Run();
173     }
174 
175     return true;
176   }
177 
178  private:
179   std::vector<std::unique_ptr<HttpResponse>> responses_;
180   StreamId stream_id_;
181   const raw_ptr<Http2Connection> connection_;
182   std::queue<std::string> chunks_;
183   bool last_frame_ = false;
184   base::OnceClosure send_completion_callback_;
185   base::WeakPtrFactory<ResponseDelegate> weak_factory_{this};
186 };
187 
Http2Connection(std::unique_ptr<StreamSocket> socket,EmbeddedTestServerConnectionListener * connection_listener,EmbeddedTestServer * embedded_test_server)188 Http2Connection::Http2Connection(
189     std::unique_ptr<StreamSocket> socket,
190     EmbeddedTestServerConnectionListener* connection_listener,
191     EmbeddedTestServer* embedded_test_server)
192     : socket_(std::move(socket)),
193       connection_listener_(connection_listener),
194       embedded_test_server_(embedded_test_server),
195       read_buf_(base::MakeRefCounted<IOBufferWithSize>(4096)) {
196   http2::adapter::OgHttp2Adapter::Options options;
197   options.perspective = http2::adapter::Perspective::kServer;
198   adapter_ = http2::adapter::OgHttp2Adapter::Create(*this, options);
199 }
200 
201 Http2Connection::~Http2Connection() = default;
202 
OnSocketReady()203 void Http2Connection::OnSocketReady() {
204   ReadData();
205 }
206 
ReadData()207 void Http2Connection::ReadData() {
208   while (true) {
209     int rv = socket_->Read(
210         read_buf_.get(), read_buf_->size(),
211         base::BindOnce(&Http2Connection::OnDataRead, base::Unretained(this)));
212     if (rv == ERR_IO_PENDING)
213       return;
214     if (!HandleData(rv))
215       return;
216   }
217 }
218 
OnDataRead(int rv)219 void Http2Connection::OnDataRead(int rv) {
220   if (HandleData(rv))
221     ReadData();
222 }
223 
HandleData(int rv)224 bool Http2Connection::HandleData(int rv) {
225   if (rv <= 0) {
226     embedded_test_server_->RemoveConnection(this);
227     return false;
228   }
229 
230   if (connection_listener_)
231     connection_listener_->ReadFromSocket(*socket_, rv);
232 
233   std::string_view remaining_buffer(read_buf_->data(), rv);
234   while (!remaining_buffer.empty()) {
235     int result = adapter_->ProcessBytes(remaining_buffer);
236     if (result < 0)
237       return false;
238     remaining_buffer = remaining_buffer.substr(result);
239   }
240 
241   // Any frames and data sources will be queued up and sent all at once below
242   DCHECK(!processing_responses_);
243   processing_responses_ = true;
244   while (!ready_streams_.empty()) {
245     StreamId stream_id = ready_streams_.front();
246     ready_streams_.pop();
247     auto delegate = std::make_unique<ResponseDelegate>(this, stream_id);
248     ResponseDelegate* delegate_ptr = delegate.get();
249     response_map_[stream_id] = std::move(delegate);
250     embedded_test_server_->HandleRequest(delegate_ptr->GetWeakPtr(),
251                                          std::move(request_map_[stream_id]),
252                                          socket_.get());
253     request_map_.erase(stream_id);
254   }
255   adapter_->Send();
256   processing_responses_ = false;
257   return true;
258 }
259 
Socket()260 StreamSocket* Http2Connection::Socket() {
261   return socket_.get();
262 }
263 
TakeSocket()264 std::unique_ptr<StreamSocket> Http2Connection::TakeSocket() {
265   return std::move(socket_);
266 }
267 
GetWeakPtr()268 base::WeakPtr<HttpConnection> Http2Connection::GetWeakPtr() {
269   return weak_factory_.GetWeakPtr();
270 }
271 
OnReadyToSend(std::string_view serialized)272 int64_t Http2Connection::OnReadyToSend(std::string_view serialized) {
273   if (write_buf_)
274     return kSendBlocked;
275 
276   write_buf_ = base::MakeRefCounted<DrainableIOBuffer>(
277       base::MakeRefCounted<StringIOBuffer>(std::string(serialized)),
278       serialized.size());
279   SendInternal();
280   return serialized.size();
281 }
282 
OnCloseStream(StreamId stream_id,http2::adapter::Http2ErrorCode error_code)283 bool Http2Connection::OnCloseStream(StreamId stream_id,
284                                     http2::adapter::Http2ErrorCode error_code) {
285   response_map_.erase(stream_id);
286   return true;
287 }
288 
289 Http2VisitorInterface::DataFrameHeaderInfo
OnReadyToSendDataForStream(StreamId stream_id,size_t max_length)290 Http2Connection::OnReadyToSendDataForStream(StreamId stream_id,
291                                             size_t max_length) {
292   auto it = response_map_.find(stream_id);
293   if (it == response_map_.end()) {
294     return {kSendError, false, false};
295   }
296   return it->second->OnReadyToSendDataForStream(stream_id, max_length);
297 }
298 
SendDataFrame(StreamId stream_id,absl::string_view frame_header,size_t payload_bytes)299 bool Http2Connection::SendDataFrame(StreamId stream_id,
300                                     absl::string_view frame_header,
301                                     size_t payload_bytes) {
302   auto it = response_map_.find(stream_id);
303   if (it == response_map_.end()) {
304     return false;
305   }
306   return it->second->SendDataFrame(stream_id, frame_header, payload_bytes);
307 }
308 
SendInternal()309 void Http2Connection::SendInternal() {
310   DCHECK(socket_);
311   DCHECK(write_buf_);
312   while (write_buf_->BytesRemaining() > 0) {
313     int rv = socket_->Write(write_buf_.get(), write_buf_->BytesRemaining(),
314                             base::BindOnce(&Http2Connection::OnSendInternalDone,
315                                            base::Unretained(this)),
316                             TRAFFIC_ANNOTATION_FOR_TESTS);
317     if (rv == ERR_IO_PENDING)
318       return;
319 
320     if (rv < 0) {
321       embedded_test_server_->RemoveConnection(this);
322       break;
323     }
324 
325     write_buf_->DidConsume(rv);
326   }
327   write_buf_ = nullptr;
328 }
329 
OnSendInternalDone(int rv)330 void Http2Connection::OnSendInternalDone(int rv) {
331   DCHECK(write_buf_);
332   if (rv < 0) {
333     embedded_test_server_->RemoveConnection(this);
334     write_buf_ = nullptr;
335     return;
336   }
337   write_buf_->DidConsume(rv);
338 
339   SendInternal();
340 
341   if (!write_buf_) {
342     // Now that writing is no longer blocked, any blocked streams can be
343     // resumed.
344     for (const auto& stream_id : blocked_streams_)
345       adapter_->ResumeStream(stream_id);
346 
347     if (adapter_->want_write()) {
348       base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
349           FROM_HERE, base::BindOnce(&Http2Connection::SendIfNotProcessing,
350                                     weak_factory_.GetWeakPtr()));
351     }
352   }
353 }
354 
SendIfNotProcessing()355 void Http2Connection::SendIfNotProcessing() {
356   if (!processing_responses_) {
357     processing_responses_ = true;
358     adapter_->Send();
359     processing_responses_ = false;
360   }
361 }
362 
363 http2::adapter::Http2VisitorInterface::OnHeaderResult
OnHeaderForStream(http2::adapter::Http2StreamId stream_id,std::string_view key,std::string_view value)364 Http2Connection::OnHeaderForStream(http2::adapter::Http2StreamId stream_id,
365                                    std::string_view key,
366                                    std::string_view value) {
367   header_map_[stream_id][std::string(key)] = std::string(value);
368   return http2::adapter::Http2VisitorInterface::OnHeaderResult::HEADER_OK;
369 }
370 
OnEndHeadersForStream(http2::adapter::Http2StreamId stream_id)371 bool Http2Connection::OnEndHeadersForStream(
372     http2::adapter::Http2StreamId stream_id) {
373   HttpRequest::HeaderMap header_map = header_map_[stream_id];
374   auto request = std::make_unique<HttpRequest>();
375   // TODO(crbug.com/40242862): Handle proxy cases.
376   request->relative_url = header_map[":path"];
377   request->base_url = GURL(header_map[":authority"]);
378   request->method_string = header_map[":method"];
379   request->method = HttpRequestParser::GetMethodType(request->method_string);
380   request->headers = header_map;
381 
382   request->has_content = false;
383 
384   SSLInfo ssl_info;
385   DCHECK(socket_->GetSSLInfo(&ssl_info));
386   request->ssl_info = ssl_info;
387   request_map_[stream_id] = std::move(request);
388 
389   return true;
390 }
391 
OnEndStream(http2::adapter::Http2StreamId stream_id)392 bool Http2Connection::OnEndStream(http2::adapter::Http2StreamId stream_id) {
393   ready_streams_.push(stream_id);
394   return true;
395 }
396 
OnFrameHeader(StreamId,size_t,uint8_t,uint8_t)397 bool Http2Connection::OnFrameHeader(StreamId /*stream_id*/,
398                                     size_t /*length*/,
399                                     uint8_t /*type*/,
400                                     uint8_t /*flags*/) {
401   return true;
402 }
403 
OnBeginHeadersForStream(StreamId stream_id)404 bool Http2Connection::OnBeginHeadersForStream(StreamId stream_id) {
405   return true;
406 }
407 
OnBeginDataForStream(StreamId stream_id,size_t payload_length)408 bool Http2Connection::OnBeginDataForStream(StreamId stream_id,
409                                            size_t payload_length) {
410   return true;
411 }
412 
OnDataForStream(StreamId stream_id,std::string_view data)413 bool Http2Connection::OnDataForStream(StreamId stream_id,
414                                       std::string_view data) {
415   auto request = request_map_.find(stream_id);
416   if (request == request_map_.end()) {
417     // We should not receive data before receiving headers.
418     return false;
419   }
420 
421   request->second->has_content = true;
422   request->second->content.append(data);
423   adapter_->MarkDataConsumedForStream(stream_id, data.size());
424   return true;
425 }
426 
OnDataPaddingLength(StreamId stream_id,size_t padding_length)427 bool Http2Connection::OnDataPaddingLength(StreamId stream_id,
428                                           size_t padding_length) {
429   adapter_->MarkDataConsumedForStream(stream_id, padding_length);
430   return true;
431 }
432 
OnGoAway(StreamId last_accepted_stream_id,http2::adapter::Http2ErrorCode error_code,std::string_view opaque_data)433 bool Http2Connection::OnGoAway(StreamId last_accepted_stream_id,
434                                http2::adapter::Http2ErrorCode error_code,
435                                std::string_view opaque_data) {
436   return true;
437 }
438 
OnBeforeFrameSent(uint8_t frame_type,StreamId stream_id,size_t length,uint8_t flags)439 int Http2Connection::OnBeforeFrameSent(uint8_t frame_type,
440                                        StreamId stream_id,
441                                        size_t length,
442                                        uint8_t flags) {
443   return 0;
444 }
445 
OnFrameSent(uint8_t frame_type,StreamId stream_id,size_t length,uint8_t flags,uint32_t error_code)446 int Http2Connection::OnFrameSent(uint8_t frame_type,
447                                  StreamId stream_id,
448                                  size_t length,
449                                  uint8_t flags,
450                                  uint32_t error_code) {
451   return 0;
452 }
453 
OnInvalidFrame(StreamId stream_id,InvalidFrameError error)454 bool Http2Connection::OnInvalidFrame(StreamId stream_id,
455                                      InvalidFrameError error) {
456   return true;
457 }
458 
OnMetadataForStream(StreamId stream_id,std::string_view metadata)459 bool Http2Connection::OnMetadataForStream(StreamId stream_id,
460                                           std::string_view metadata) {
461   return true;
462 }
463 
OnMetadataEndForStream(StreamId stream_id)464 bool Http2Connection::OnMetadataEndForStream(StreamId stream_id) {
465   return true;
466 }
467 
468 }  // namespace test_server
469 
470 }  // namespace net
471