1
#pragma once
2

            
3
#include <memory>
4
#include <ostream>
5

            
6
#include "source/common/http/session_idle_list_interface.h"
7
#include "source/common/quic/envoy_quic_connection_debug_visitor_factory_interface.h"
8
#include "source/common/quic/envoy_quic_server_connection.h"
9
#include "source/common/quic/envoy_quic_server_crypto_stream_factory.h"
10
#include "source/common/quic/envoy_quic_server_stream.h"
11
#include "source/common/quic/quic_filter_manager_connection_impl.h"
12
#include "source/common/quic/quic_stat_names.h"
13
#include "source/common/quic/send_buffer_monitor.h"
14

            
15
#include "quiche/quic/core/http/quic_server_session_base.h"
16
#include "quiche/quic/core/quic_crypto_server_stream.h"
17
#include "quiche/quic/core/tls_server_handshaker.h"
18

            
19
namespace Envoy {
20
namespace Quic {
21

            
22
#define QUIC_CONNECTION_STATS(COUNTER)                                                             \
23
2239
  COUNTER(num_server_migration_detected)                                                           \
24
2239
  COUNTER(num_packets_rx_on_preferred_address)
25

            
26
struct QuicConnectionStats {
27
  QUIC_CONNECTION_STATS(GENERATE_COUNTER_STRUCT)
28
};
29

            
30
using FilterChainToConnectionMap =
31
    absl::flat_hash_map<const Network::FilterChain*,
32
                        std::list<std::reference_wrapper<Network::Connection>>>;
33
using ConnectionMapIter = std::list<std::reference_wrapper<Network::Connection>>::iterator;
34

            
35
// Used to track the matching filter chain and its position in the filter chain to connection map.
36
struct ConnectionMapPosition {
37
  ConnectionMapPosition(FilterChainToConnectionMap& connection_map,
38
                        const Network::FilterChain& filter_chain, ConnectionMapIter iterator)
39
2970
      : connection_map_(connection_map), filter_chain_(filter_chain), iterator_(iterator) {}
40

            
41
  // Stores the map from filter chain of connections.
42
  FilterChainToConnectionMap& connection_map_;
43
  // The matching filter chain of a connection.
44
  const Network::FilterChain& filter_chain_;
45
  // The position of the connection in the map.
46
  ConnectionMapIter iterator_;
47
};
48

            
49
// Act as a Network::Connection to HCM and a FilterManager to FilterFactoryCb.
50
// TODO(danzh) Lifetime of quic connection and filter manager connection can be
51
// simplified by changing the inheritance to a member variable instantiated
52
// before quic_connection_.
53
class EnvoyQuicServerSession : public quic::QuicServerSessionBase,
54
                               public QuicFilterManagerConnectionImpl,
55
                               public Envoy::Http::IdleSessionInterface {
56
public:
57
  EnvoyQuicServerSession(
58
      const quic::QuicConfig& config, const quic::ParsedQuicVersionVector& supported_versions,
59
      std::unique_ptr<EnvoyQuicServerConnection> connection, quic::QuicSession::Visitor* visitor,
60
      quic::QuicCryptoServerStreamBase::Helper* helper,
61
      const quic::QuicCryptoServerConfig* crypto_config,
62
      quic::QuicCompressedCertsCache* compressed_certs_cache, Event::Dispatcher& dispatcher,
63
      uint32_t send_buffer_limit, QuicStatNames& quic_stat_names, Stats::Scope& listener_scope,
64
      EnvoyQuicCryptoServerStreamFactoryInterface& crypto_server_stream_factory,
65
      std::unique_ptr<StreamInfo::StreamInfo>&& stream_info, QuicConnectionStats& connection_stats,
66
      EnvoyQuicConnectionDebugVisitorFactoryInterfaceOptRef debug_visitor_factory,
67
      Http::SessionIdleListInterface* session_idle_list);
68

            
69
  ~EnvoyQuicServerSession() override;
70

            
71
  // Network::Connection
72
  absl::string_view requestedServerName() const override;
73
  void dumpState(std::ostream&, int) const override {
74
    // TODO(kbaichoo): Implement dumpState for H3.
75
  }
76

            
77
  // Called by QuicHttpServerConnectionImpl before creating data streams.
78
2950
  void setHttpConnectionCallbacks(Http::ServerConnectionCallbacks& callbacks) {
79
2950
    http_connection_callbacks_ = &callbacks;
80
2950
  }
81

            
82
  void setH3GoAwayLoadShedPoints(Server::LoadShedPoint* should_send_go_away_and_close_on_dispatch,
83
2950
                                 Server::LoadShedPoint* should_send_go_away_on_dispatch) {
84
2950
    ENVOY_LOG_ONCE_IF(trace, should_send_go_away_and_close_on_dispatch == nullptr,
85
2950
                      "LoadShedPoint "
86
2950
                      "envoy.load_shed_points.http3_server_go_away_and_close_on_dispatch "
87
2950
                      "is not found. Is it configured?");
88
2950
    ENVOY_LOG_ONCE_IF(trace, should_send_go_away_on_dispatch == nullptr,
89
2950
                      "LoadShedPoint envoy.load_shed_points.http3_server_go_away_on_dispatch "
90
2950
                      "is not found. Is it configured?");
91
2950
    should_send_go_away_and_close_on_dispatch_ = should_send_go_away_and_close_on_dispatch;
92
2950
    should_send_go_away_on_dispatch_ = should_send_go_away_on_dispatch;
93
2950
  }
94

            
95
  // quic::QuicSession
96
  void OnConnectionClosed(const quic::QuicConnectionCloseFrame& frame,
97
                          quic::ConnectionCloseSource source) override;
98
  void Initialize() override;
99
  void OnCanWrite() override;
100
  void OnTlsHandshakeComplete() override;
101
  void OnRstStream(const quic::QuicRstStreamFrame& frame) override;
102
  void ProcessUdpPacket(const quic::QuicSocketAddress& self_address,
103
                        const quic::QuicSocketAddress& peer_address,
104
                        const quic::QuicReceivedPacket& packet) override;
105
  std::vector<absl::string_view>::const_iterator
106
  SelectAlpn(const std::vector<absl::string_view>& alpns) const override;
107

            
108
  void setHeadersWithUnderscoreAction(
109
      envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction
110
2950
          headers_with_underscores_action) {
111
2950
    headers_with_underscores_action_ = headers_with_underscores_action;
112
2950
  }
113

            
114
  void storeConnectionMapPosition(FilterChainToConnectionMap& connection_map,
115
                                  const Network::FilterChain& filter_chain,
116
                                  ConnectionMapIter position);
117

            
118
1
  bool setSocketOption(Envoy::Network::SocketOptionName, absl::Span<uint8_t>) override {
119
1
    return false;
120
1
  }
121

            
122
  void setHttp3Options(const envoy::config::core::v3::Http3ProtocolOptions& http3_options) override;
123

            
124
  // Overridden to remove the session from the idle list when the last stream is
125
  // closed.
126
  void OnStreamClosed(quic::QuicStreamId id) override;
127

            
128
  // IdleSessionInterface
129
  void TerminateIdleSession() override;
130

            
131
  using quic::QuicSession::PerformActionOnActiveStreams;
132

            
133
protected:
134
  // quic::QuicServerSessionBase
135
  std::unique_ptr<quic::QuicCryptoServerStreamBase>
136
  CreateQuicCryptoServerStream(const quic::QuicCryptoServerConfig* crypto_config,
137
                               quic::QuicCompressedCertsCache* compressed_certs_cache) override;
138
  quic::QuicSSLConfig GetSSLConfig() const override;
139

            
140
  // quic::QuicSession
141
  // Overridden to create stream as encoder and associate it with an decoder.
142
  quic::QuicSpdyStream* CreateIncomingStream(quic::QuicStreamId id) override;
143
  quic::QuicSpdyStream* CreateIncomingStream(quic::PendingStream* pending) override;
144
  quic::QuicSpdyStream* CreateOutgoingBidirectionalStream() override;
145

            
146
293411
  quic::HttpDatagramSupport LocalHttpDatagramSupport() override { return http_datagram_support_; }
147

            
148
  // QuicFilterManagerConnectionImpl
149
  bool hasDataToWrite() override;
150
  // Used by base class to access quic connection after initialization.
151
  const quic::QuicConnection* quicConnection() const override;
152
  quic::QuicConnection* quicConnection() override;
153
  void MaybeAddSessionToIdleList();
154
  void MaybeRemoveSessionFromIdleList();
155

            
156
private:
157
  void setUpRequestDecoder(EnvoyQuicServerStream& stream);
158
  void ActivateStream(std::unique_ptr<quic::QuicStream> stream) override;
159
  void OnLastActiveStreamClosed();
160

            
161
  std::unique_ptr<EnvoyQuicServerConnection> quic_connection_;
162
  // These callbacks are owned by network filters and quic session should out live
163
  // them.
164
  Http::ServerConnectionCallbacks* http_connection_callbacks_{nullptr};
165

            
166
  envoy::config::core::v3::HttpProtocolOptions::HeadersWithUnderscoresAction
167
      headers_with_underscores_action_;
168

            
169
  EnvoyQuicCryptoServerStreamFactoryInterface& crypto_server_stream_factory_;
170
  absl::optional<ConnectionMapPosition> position_;
171
  QuicConnectionStats& connection_stats_;
172
  quic::HttpDatagramSupport http_datagram_support_ = quic::HttpDatagramSupport::kNone;
173
  std::unique_ptr<quic::QuicConnectionDebugVisitor> debug_visitor_;
174
  // Load shed points for H3 GoAway
175
  Server::LoadShedPoint* should_send_go_away_and_close_on_dispatch_ = nullptr;
176
  Server::LoadShedPoint* should_send_go_away_on_dispatch_ = nullptr;
177
  Http::SessionIdleListInterface* session_idle_list_;
178
  bool h3_go_away_sent_ = false;
179
  bool on_connection_closed_called_ = false;
180
  bool is_in_idle_list_ = false;
181
};
182

            
183
} // namespace Quic
184
} // namespace Envoy