Line data Source code
1 : #pragma once 2 : 3 : #include "envoy/upstream/upstream.h" 4 : 5 : #include "source/common/network/multi_connection_base_impl.h" 6 : 7 : namespace Envoy { 8 : namespace Network { 9 : 10 : /** 11 : * Implementation of ConnectionProvider for HappyEyeballs. It provides client 12 : * connections to multiple addresses in an specific order complying to 13 : * HappyEyeballs. 14 : */ 15 : class HappyEyeballsConnectionProvider : public ConnectionProvider, 16 : Logger::Loggable<Logger::Id::happy_eyeballs> { 17 : public: 18 : HappyEyeballsConnectionProvider( 19 : Event::Dispatcher& dispatcher, 20 : const std::vector<Address::InstanceConstSharedPtr>& address_list, 21 : const std::shared_ptr<const Upstream::UpstreamLocalAddressSelector>& 22 : upstream_local_address_selector, 23 : UpstreamTransportSocketFactory& socket_factory, 24 : TransportSocketOptionsConstSharedPtr transport_socket_options, 25 : const Upstream::HostDescriptionConstSharedPtr& host, 26 : const ConnectionSocket::OptionsSharedPtr options); 27 : bool hasNextConnection() override; 28 : ClientConnectionPtr createNextConnection(const uint64_t id) override; 29 : size_t nextConnection() override; 30 : size_t totalConnections() override; 31 : // Returns a new vector containing the contents of |address_list| sorted 32 : // with address families interleaved, as per Section 4 of RFC 8305, Happy 33 : // Eyeballs v2. It is assumed that the list must already be sorted as per 34 : // Section 6 of RFC6724, which happens in the DNS implementations (ares_getaddrinfo() 35 : // and Apple DNS). 36 : static std::vector<Address::InstanceConstSharedPtr> 37 : sortAddresses(const std::vector<Address::InstanceConstSharedPtr>& address_list); 38 : 39 : private: 40 : Event::Dispatcher& dispatcher_; 41 : // List of addresses to attempt to connect to. 42 : const std::vector<Address::InstanceConstSharedPtr> address_list_; 43 : const Upstream::UpstreamLocalAddressSelectorConstSharedPtr upstream_local_address_selector_; 44 : UpstreamTransportSocketFactory& socket_factory_; 45 : TransportSocketOptionsConstSharedPtr transport_socket_options_; 46 : const Upstream::HostDescriptionConstSharedPtr host_; 47 : const ConnectionSocket::OptionsSharedPtr options_; 48 : // Index of the next address to use. 49 : size_t next_address_ = 0; 50 : // True if the first connection has been created. 51 : bool first_connection_created_ = false; 52 : }; 53 : 54 : /** 55 : * Implementation of ClientConnection which transparently attempts connections to 56 : * multiple different IP addresses, and uses the first connection that succeeds. 57 : * After a connection is established, all methods simply delegate to the 58 : * underlying connection. However, before the connection is established 59 : * their behavior depends on their semantics. For anything which can result 60 : * in up-call (e.g. filter registration) or which must only happen once (e.g. 61 : * writing data) the context is saved in until the connection completes, at 62 : * which point they are replayed to the underlying connection. For simple methods 63 : * they are applied to each open connection and applied when creating new ones. 64 : * 65 : * See the Happy Eyeballs RFC at https://datatracker.ietf.org/doc/html/rfc6555 66 : * TODO(RyanTheOptimist): Implement the Happy Eyeballs address sorting algorithm 67 : * either in the class or in the resolution code. 68 : */ 69 : class HappyEyeballsConnectionImpl : public MultiConnectionBaseImpl, 70 : Logger::Loggable<Logger::Id::happy_eyeballs> { 71 : public: 72 : HappyEyeballsConnectionImpl(Event::Dispatcher& dispatcher, 73 : const std::vector<Address::InstanceConstSharedPtr>& address_list, 74 : const std::shared_ptr<const Upstream::UpstreamLocalAddressSelector>& 75 : upstream_local_address_selector, 76 : UpstreamTransportSocketFactory& socket_factory, 77 : TransportSocketOptionsConstSharedPtr transport_socket_options, 78 : const Upstream::HostDescriptionConstSharedPtr& host, 79 : const ConnectionSocket::OptionsSharedPtr options) 80 : : MultiConnectionBaseImpl(dispatcher, 81 : std::make_unique<Network::HappyEyeballsConnectionProvider>( 82 : dispatcher, address_list, upstream_local_address_selector, 83 0 : socket_factory, transport_socket_options, host, options)) {} 84 : }; 85 : 86 : } // namespace Network 87 : } // namespace Envoy