1
#pragma once
2

            
3
#include "source/common/quic/quic_transport_socket_factory.h"
4
#include "source/common/tls/client_ssl_socket.h"
5

            
6
namespace Envoy {
7
namespace Quic {
8

            
9
class QuicClientTransportSocketFactory : public Network::CommonUpstreamTransportSocketFactory,
10
                                         public QuicTransportSocketFactoryBase {
11
public:
12
  static absl::StatusOr<std::unique_ptr<QuicClientTransportSocketFactory>>
13
  create(Ssl::ClientContextConfigPtr config,
14
         Server::Configuration::TransportSocketFactoryContext& factory_context);
15

            
16
  void initialize() override;
17
107
  bool implementsSecureTransport() const override { return true; }
18
1097
  bool supportsAlpn() const override { return true; }
19
939
  absl::string_view defaultServerNameIndication() const override {
20
939
    return clientContextConfig()->serverNameIndication();
21
939
  }
22

            
23
  // As documented above for QuicTransportSocketFactoryBase, the actual HTTP/3
24
  // code does not create transport sockets.
25
  // QuicClientTransportSocketFactory::createTransportSocket is called by the
26
  // connection grid when upstream HTTP/3 fails over to TCP, and a raw SSL socket
27
  // is needed. In this case the QuicClientTransportSocketFactory falls over to
28
  // using the fallback factory.
29
  Network::TransportSocketPtr
30
  createTransportSocket(Network::TransportSocketOptionsConstSharedPtr options,
31
27
                        Upstream::HostDescriptionConstSharedPtr host) const override {
32
27
    return fallback_factory_->createTransportSocket(options, host);
33
27
  }
34

            
35
5155
  Envoy::Ssl::ClientContextSharedPtr sslCtx() override { return fallback_factory_->sslCtx(); }
36

            
37
8441
  OptRef<const Ssl::ClientContextConfig> clientContextConfig() const override {
38
8441
    return fallback_factory_->clientContextConfig();
39
8441
  }
40

            
41
  // Returns a crypto config generated from the up-to-date client context config. Once the passed in
42
  // context config gets updated, a new crypto config object will be returned by this method.
43
  std::shared_ptr<quic::QuicCryptoClientConfig> getCryptoConfig() override;
44

            
45
protected:
46
  QuicClientTransportSocketFactory(
47
      Ssl::ClientContextConfigPtr config,
48
      Server::Configuration::TransportSocketFactoryContext& factory_context,
49
      absl::Status& creation_status);
50

            
51
  // fallback_factory_ will update the context.
52
  absl::Status onSecretUpdated() override { return absl::OkStatus(); }
53

            
54
  // The cache in the QuicCryptoClientConfig is not thread-safe, so crypto_config_ needs to
55
  // be a thread local object. client_context lets the thread local object determine if the crypto
56
  // config needs to be updated.
57
  struct ThreadLocalQuicConfig : public ThreadLocal::ThreadLocalObject {
58
    // Latch the latest client context, to determine if it has updated since last
59
    // checked.
60
    Envoy::Ssl::ClientContextSharedPtr client_context_;
61
    // If client_context_ changes, client config will be updated as well.
62
    std::shared_ptr<quic::QuicCryptoClientConfig> crypto_config_;
63
  };
64

            
65
private:
66
  // The QUIC client transport socket can create TLS sockets for fallback to TCP.
67
  std::unique_ptr<Envoy::Extensions::TransportSockets::Tls::ClientSslSocketFactory>
68
      fallback_factory_;
69
  // The storage for thread local quic config.
70
  ThreadLocal::TypedSlot<ThreadLocalQuicConfig> tls_slot_;
71
};
72

            
73
class QuicClientTransportSocketConfigFactory
74
    : public QuicTransportSocketConfigFactory,
75
      public Server::Configuration::UpstreamTransportSocketConfigFactory {
76
public:
77
  // Server::Configuration::UpstreamTransportSocketConfigFactory
78
  absl::StatusOr<Network::UpstreamTransportSocketFactoryPtr> createTransportSocketFactory(
79
      const Protobuf::Message& config,
80
      Server::Configuration::TransportSocketFactoryContext& context) override;
81

            
82
  // Server::Configuration::TransportSocketConfigFactory
83
  ProtobufTypes::MessagePtr createEmptyConfigProto() override;
84
};
85

            
86
DECLARE_FACTORY(QuicClientTransportSocketConfigFactory);
87

            
88
} // namespace Quic
89
} // namespace Envoy