File: http2_connection.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (150 lines) | stat: -rw-r--r-- 6,689 bytes parent folder | download | duplicates (6)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef NET_TEST_EMBEDDED_TEST_SERVER_HTTP2_CONNECTION_H_
#define NET_TEST_EMBEDDED_TEST_SERVER_HTTP2_CONNECTION_H_

#include <memory>
#include <queue>
#include <string>

#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "net/base/io_buffer.h"
#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
#include "net/test/embedded_test_server/http_connection.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/third_party/quiche/src/quiche/http2/adapter/http2_visitor_interface.h"
#include "net/third_party/quiche/src/quiche/http2/adapter/oghttp2_adapter.h"

namespace net::test_server {

using StreamId = http2::adapter::Http2StreamId;
template <class T>
using StreamMap = base::flat_map<StreamId, T>;

class EmbeddedTestServer;

// Outside of the text/binary (which is just a drop-in parser/decoder
// replacement) the main difference from Http1Connection is that multiple
// request/response "streams" can exist on the same connection, which means
// connections don't open on first request and don't close on first response
class Http2Connection : public HttpConnection,
                        public http2::adapter::Http2VisitorInterface {
 public:
  Http2Connection(std::unique_ptr<StreamSocket> socket,
                  EmbeddedTestServerConnectionListener* connection_listener,
                  EmbeddedTestServer* server_delegate);
  ~Http2Connection() override;
  Http2Connection(const HttpConnection&) = delete;
  Http2Connection& operator=(const Http2Connection&) = delete;

  // HttpConnection
  void OnSocketReady() override;
  StreamSocket* Socket() override;
  std::unique_ptr<StreamSocket> TakeSocket() override;
  base::WeakPtr<HttpConnection> GetWeakPtr() override;

  // http2::adapter::Http2VisitorInterface
  int64_t OnReadyToSend(std::string_view serialized) override;
  OnHeaderResult OnHeaderForStream(StreamId stream_id,
                                   std::string_view key,
                                   std::string_view value) override;
  bool OnEndHeadersForStream(StreamId stream_id) override;
  bool OnEndStream(StreamId stream_id) override;
  bool OnCloseStream(StreamId stream_id,
                     http2::adapter::Http2ErrorCode error_code) override;
  DataFrameHeaderInfo OnReadyToSendDataForStream(StreamId stream_id,
                                                 size_t max_length) override;
  bool SendDataFrame(StreamId stream_id,
                     absl::string_view frame_header,
                     size_t payload_bytes) override;
  // Unused functions
  void OnConnectionError(ConnectionError /*error*/) override {}
  bool OnFrameHeader(StreamId /*stream_id*/,
                     size_t /*length*/,
                     uint8_t /*type*/,
                     uint8_t /*flags*/) override;
  void OnSettingsStart() override {}
  void OnSetting(http2::adapter::Http2Setting setting) override {}
  void OnSettingsEnd() override {}
  void OnSettingsAck() override {}
  bool OnBeginHeadersForStream(StreamId stream_id) override;
  bool OnBeginDataForStream(StreamId stream_id, size_t payload_length) override;
  bool OnDataForStream(StreamId stream_id, std::string_view data) override;
  bool OnDataPaddingLength(StreamId stream_id, size_t padding_length) override;
  void OnRstStream(StreamId stream_id,
                   http2::adapter::Http2ErrorCode error_code) override {}
  void OnPriorityForStream(StreamId stream_id,
                           StreamId parent_stream_id,
                           int weight,
                           bool exclusive) override {}
  void OnPing(http2::adapter::Http2PingId ping_id, bool is_ack) override {}
  void OnPushPromiseForStream(StreamId stream_id,
                              StreamId promised_stream_id) override {}
  bool OnGoAway(StreamId last_accepted_stream_id,
                http2::adapter::Http2ErrorCode error_code,
                std::string_view opaque_data) override;
  void OnWindowUpdate(StreamId stream_id, int window_increment) override {}
  int OnBeforeFrameSent(uint8_t frame_type,
                        StreamId stream_id,
                        size_t length,
                        uint8_t flags) override;
  int OnFrameSent(uint8_t frame_type,
                  StreamId stream_id,
                  size_t length,
                  uint8_t flags,
                  uint32_t error_code) override;
  bool OnInvalidFrame(StreamId stream_id, InvalidFrameError error) override;
  void OnBeginMetadataForStream(StreamId stream_id,
                                size_t payload_length) override {}
  bool OnMetadataForStream(StreamId stream_id,
                           std::string_view metadata) override;
  bool OnMetadataEndForStream(StreamId stream_id) override;
  void OnErrorDebug(std::string_view message) override {}

  http2::adapter::OgHttp2Adapter* adapter() { return adapter_.get(); }

 private:
  // Corresponds to one HTTP/2 stream in a connection
  class ResponseDelegate;
  class DataFrameSource;

  void ReadData();
  void OnDataRead(int rv);
  bool HandleData(int rv);
  void SendInternal();
  void OnSendInternalDone(int rv);

  void SendIfNotProcessing();

  StreamMap<std::unique_ptr<HttpRequest>> request_map_;
  StreamMap<std::unique_ptr<ResponseDelegate>> response_map_;
  StreamMap<HttpRequest::HeaderMap> header_map_;
  std::queue<StreamId> ready_streams_;
  std::unique_ptr<http2::adapter::OgHttp2Adapter> adapter_;
  std::unique_ptr<StreamSocket> socket_;
  const raw_ptr<EmbeddedTestServerConnectionListener> connection_listener_;
  const raw_ptr<EmbeddedTestServer> embedded_test_server_;
  scoped_refptr<IOBufferWithSize> read_buf_;
  // Frames can be submitted asynchronusly, so frames will be pulled one at a
  // time by the data frame through ReadyToSend. If the buffer is not null, it
  // is being processed and new frames should be blocked.
  scoped_refptr<DrainableIOBuffer> write_buf_{nullptr};
  // Streams from a DataFrameSource that were blocked.
  base::flat_set<StreamId> blocked_streams_;
  // Whether the connection is in the midst of processing requests, and will
  // send queued frames and data sources. Stops early on an I/O block or
  // depleted flow-control window.
  bool processing_responses_ = false;

  base::WeakPtrFactory<Http2Connection> weak_factory_{this};
};

}  // namespace net::test_server

#endif  // NET_TEST_EMBEDDED_TEST_SERVER_HTTP2_CONNECTION_H_