1
#pragma once
2

            
3
#include "envoy/common/optref.h"
4
#include "envoy/config/cluster/v3/cluster.pb.h"
5
#include "envoy/upstream/upstream.h"
6

            
7
#include "source/common/network/multi_connection_base_impl.h"
8

            
9
namespace Envoy {
10
namespace Network {
11

            
12
/**
13
 * Implementation of ConnectionProvider for HappyEyeballs. It provides client
14
 * connections to multiple addresses in an specific order complying to
15
 * HappyEyeballs.
16
 */
17
class HappyEyeballsConnectionProvider : public ConnectionProvider,
18
                                        Logger::Loggable<Logger::Id::happy_eyeballs> {
19
public:
20
  HappyEyeballsConnectionProvider(
21
      Event::Dispatcher& dispatcher,
22
      const std::vector<Address::InstanceConstSharedPtr>& address_list,
23
      const std::shared_ptr<const Upstream::UpstreamLocalAddressSelector>&
24
          upstream_local_address_selector,
25
      UpstreamTransportSocketFactory& socket_factory,
26
      TransportSocketOptionsConstSharedPtr transport_socket_options,
27
      const Upstream::HostDescriptionConstSharedPtr& host,
28
      const ConnectionSocket::OptionsSharedPtr options,
29
      const envoy::config::cluster::v3::UpstreamConnectionOptions::HappyEyeballsConfig&
30
          happy_eyeballs_config);
31
  bool hasNextConnection() override;
32
  ClientConnectionPtr createNextConnection(const uint64_t id) override;
33
  size_t nextConnection() override;
34
  size_t totalConnections() override;
35
  // Returns a new vector containing the contents of |address_list| sorted
36
  // with address families interleaved, as per Section 4 of RFC 8305, Happy
37
  // Eyeballs v2. It is assumed that the list must already be sorted as per
38
  // Section 6 of RFC6724, which happens in the DNS implementations (ares_getaddrinfo()
39
  // and Apple DNS).
40
  static std::vector<Address::InstanceConstSharedPtr>
41
  sortAddresses(const std::vector<Address::InstanceConstSharedPtr>& address_list,
42
                const envoy::config::cluster::v3::UpstreamConnectionOptions::HappyEyeballsConfig&
43
                    happy_eyeballs_config);
44

            
45
private:
46
  Event::Dispatcher& dispatcher_;
47
  // List of addresses to attempt to connect to.
48
  const std::vector<Address::InstanceConstSharedPtr> address_list_;
49
  const Upstream::UpstreamLocalAddressSelectorConstSharedPtr upstream_local_address_selector_;
50
  UpstreamTransportSocketFactory& socket_factory_;
51
  TransportSocketOptionsConstSharedPtr transport_socket_options_;
52
  const Upstream::HostDescriptionConstSharedPtr host_;
53
  const ConnectionSocket::OptionsSharedPtr options_;
54
  // Index of the next address to use.
55
  size_t next_address_ = 0;
56
  // True if the first connection has been created.
57
  bool first_connection_created_ = false;
58
};
59

            
60
/**
61
 * Implementation of ClientConnection which transparently attempts connections to
62
 * multiple different IP addresses, and uses the first connection that succeeds.
63
 * After a connection is established, all methods simply delegate to the
64
 * underlying connection. However, before the connection is established
65
 * their behavior depends on their semantics. For anything which can result
66
 * in up-call (e.g. filter registration) or which must only happen once (e.g.
67
 * writing data) the context is saved in until the connection completes, at
68
 * which point they are replayed to the underlying connection. For simple methods
69
 * they are applied to each open connection and applied when creating new ones.
70
 *
71
 * See the Happy Eyeballs RFC at https://datatracker.ietf.org/doc/html/rfc6555
72
 * TODO(RyanTheOptimist): Implement the Happy Eyeballs address sorting algorithm
73
 * either in the class or in the resolution code.
74
 */
75
class HappyEyeballsConnectionImpl : public MultiConnectionBaseImpl,
76
                                    Logger::Loggable<Logger::Id::happy_eyeballs> {
77
public:
78
  HappyEyeballsConnectionImpl(
79
      Event::Dispatcher& dispatcher,
80
      const std::vector<Address::InstanceConstSharedPtr>& address_list,
81
      const std::shared_ptr<const Upstream::UpstreamLocalAddressSelector>&
82
          upstream_local_address_selector,
83
      UpstreamTransportSocketFactory& socket_factory,
84
      TransportSocketOptionsConstSharedPtr transport_socket_options,
85
      const Upstream::HostDescriptionConstSharedPtr& host,
86
      const ConnectionSocket::OptionsSharedPtr options,
87
      const envoy::config::cluster::v3::UpstreamConnectionOptions::HappyEyeballsConfig&
88
          happy_eyeballs_config)
89
38
      : MultiConnectionBaseImpl(dispatcher,
90
38
                                std::make_unique<Network::HappyEyeballsConnectionProvider>(
91
38
                                    dispatcher, address_list, upstream_local_address_selector,
92
38
                                    socket_factory, transport_socket_options, host, options,
93
38
                                    happy_eyeballs_config)) {}
94
};
95

            
96
} // namespace Network
97
} // namespace Envoy