Line data Source code
1 : #pragma once 2 : 3 : #include "source/common/http/conn_pool_base.h" 4 : #include "source/common/http/http3/conn_pool.h" 5 : #include "source/common/http/http_server_properties_cache_impl.h" 6 : #include "source/common/quic/quic_stat_names.h" 7 : 8 : #include "absl/container/flat_hash_map.h" 9 : 10 : namespace Envoy { 11 : namespace Http { 12 : 13 : // An HTTP connection pool which will handle the connectivity grid of 14 : // [WiFi / cellular] [ipv4 / ipv6] [QUIC / TCP]. 15 : // Currently only [QUIC / TCP are handled] 16 : class ConnectivityGrid : public ConnectionPool::Instance, 17 : public Http3::PoolConnectResultCallback, 18 : protected Logger::Loggable<Logger::Id::pool> { 19 : public: 20 : struct ConnectivityOptions { 21 : explicit ConnectivityOptions(const std::vector<Http::Protocol>& protocols) 22 0 : : protocols_(protocols) {} 23 : std::vector<Http::Protocol> protocols_; 24 : }; 25 : 26 : enum class StreamCreationResult { 27 : ImmediateResult, 28 : StreamCreationPending, 29 : }; 30 : 31 : using PoolIterator = std::list<ConnectionPool::InstancePtr>::iterator; 32 : 33 : // This is a class which wraps a caller's connection pool callbacks to 34 : // auto-retry pools in the case of connection failure. 35 : // 36 : // It also relays cancellation calls between the original caller and the 37 : // current connection attempts. 38 : class WrapperCallbacks : public ConnectionPool::Cancellable, 39 : public LinkedObject<WrapperCallbacks> { 40 : public: 41 : WrapperCallbacks(ConnectivityGrid& grid, Http::ResponseDecoder& decoder, PoolIterator pool_it, 42 : ConnectionPool::Callbacks& callbacks, const Instance::StreamOptions& options); 43 : 44 : // This holds state for a single connection attempt to a specific pool. 45 : class ConnectionAttemptCallbacks : public ConnectionPool::Callbacks, 46 : public LinkedObject<ConnectionAttemptCallbacks> { 47 : public: 48 : ConnectionAttemptCallbacks(WrapperCallbacks& parent, PoolIterator it); 49 : ~ConnectionAttemptCallbacks() override; 50 : 51 : StreamCreationResult newStream(); 52 : 53 : // ConnectionPool::Callbacks 54 : void onPoolFailure(ConnectionPool::PoolFailureReason reason, 55 : absl::string_view transport_failure_reason, 56 : Upstream::HostDescriptionConstSharedPtr host) override; 57 : void onPoolReady(RequestEncoder& encoder, Upstream::HostDescriptionConstSharedPtr host, 58 : StreamInfo::StreamInfo& info, 59 : absl::optional<Http::Protocol> protocol) override; 60 : 61 0 : ConnectionPool::Instance& pool() { return **pool_it_; } 62 : 63 : void cancel(Envoy::ConnectionPool::CancelPolicy cancel_policy); 64 : 65 : private: 66 : // A pointer back up to the parent. 67 : WrapperCallbacks& parent_; 68 : // The pool for this connection attempt. 69 : const PoolIterator pool_it_; 70 : // The handle to cancel this connection attempt. 71 : // This is owned by the pool which created it. 72 : Cancellable* cancellable_{nullptr}; 73 : }; 74 : using ConnectionAttemptCallbacksPtr = std::unique_ptr<ConnectionAttemptCallbacks>; 75 : 76 : // ConnectionPool::Cancellable 77 : void cancel(Envoy::ConnectionPool::CancelPolicy cancel_policy) override; 78 : 79 : // Attempt to create a new stream for pool(). 80 : StreamCreationResult newStream(); 81 : 82 : // Called on pool failure or timeout to kick off another connection attempt. 83 : // Returns true if there is a failover pool and a connection has been 84 : // attempted, false if all pools have been tried. 85 : bool tryAnotherConnection(); 86 : 87 : // Called by a ConnectionAttempt when the underlying pool fails. 88 : void onConnectionAttemptFailed(ConnectionAttemptCallbacks* attempt, 89 : ConnectionPool::PoolFailureReason reason, 90 : absl::string_view transport_failure_reason, 91 : Upstream::HostDescriptionConstSharedPtr host); 92 : 93 : // Called by a ConnectionAttempt when the underlying pool is ready. 94 : void onConnectionAttemptReady(ConnectionAttemptCallbacks* attempt, RequestEncoder& encoder, 95 : Upstream::HostDescriptionConstSharedPtr host, 96 : StreamInfo::StreamInfo& info, 97 : absl::optional<Http::Protocol> protocol); 98 : 99 : private: 100 : // Removes this from the owning list, deleting it. 101 : void deleteThis(); 102 : 103 : // Marks HTTP/3 broken if the HTTP/3 attempt failed but a TCP attempt succeeded. 104 : // While HTTP/3 is broken the grid will not attempt to make new HTTP/3 connections. 105 : void maybeMarkHttp3Broken(); 106 : 107 : // Cancels any pending attempts and deletes them. 108 : void cancelAllPendingAttempts(Envoy::ConnectionPool::CancelPolicy cancel_policy); 109 : 110 : // Tracks all the connection attempts which currently in flight. 111 : std::list<ConnectionAttemptCallbacksPtr> connection_attempts_; 112 : 113 : // The owning grid. 114 : ConnectivityGrid& grid_; 115 : // The decoder for the original newStream, needed to create streams on subsequent pools. 116 : Http::ResponseDecoder& decoder_; 117 : // The callbacks from the original caller, which must get onPoolFailure or 118 : // onPoolReady unless there is call to cancel(). Will be nullptr if the caller 119 : // has been notified while attempts are still pending. 120 : ConnectionPool::Callbacks* inner_callbacks_; 121 : // The timer which tracks when new connections should be attempted. 122 : Event::TimerPtr next_attempt_timer_; 123 : // The iterator to the last pool which had a connection attempt. 124 : PoolIterator current_; 125 : // True if the HTTP/3 attempt failed. 126 : bool http3_attempt_failed_{}; 127 : // True if the TCP attempt succeeded. 128 : bool tcp_attempt_succeeded_{}; 129 : // Latch the passed-in stream options. 130 : const Instance::StreamOptions stream_options_{}; 131 : }; 132 : using WrapperCallbacksPtr = std::unique_ptr<WrapperCallbacks>; 133 : 134 : ConnectivityGrid(Event::Dispatcher& dispatcher, Random::RandomGenerator& random_generator, 135 : Upstream::HostConstSharedPtr host, Upstream::ResourcePriority priority, 136 : const Network::ConnectionSocket::OptionsSharedPtr& options, 137 : const Network::TransportSocketOptionsConstSharedPtr& transport_socket_options, 138 : Upstream::ClusterConnectivityState& state, TimeSource& time_source, 139 : HttpServerPropertiesCacheSharedPtr alternate_protocols, 140 : ConnectivityOptions connectivity_options, Quic::QuicStatNames& quic_stat_names, 141 : Stats::Scope& scope, Http::PersistentQuicInfo& quic_info); 142 : ~ConnectivityGrid() override; 143 : 144 : // Event::DeferredDeletable 145 : void deleteIsPending() override; 146 : 147 : // Http::ConnPool::Instance 148 : bool hasActiveConnections() const override; 149 : ConnectionPool::Cancellable* newStream(Http::ResponseDecoder& response_decoder, 150 : ConnectionPool::Callbacks& callbacks, 151 : const Instance::StreamOptions& options) override; 152 : void addIdleCallback(IdleCb cb) override; 153 : bool isIdle() const override; 154 : void drainConnections(Envoy::ConnectionPool::DrainBehavior drain_behavior) override; 155 : Upstream::HostDescriptionConstSharedPtr host() const override; 156 : bool maybePreconnect(float preconnect_ratio) override; 157 0 : absl::string_view protocolDescription() const override { return "connection grid"; } 158 : 159 : // Returns the next pool in the ordered priority list. 160 : absl::optional<PoolIterator> nextPool(PoolIterator pool_it); 161 : 162 : // Returns true if pool is the grid's HTTP/3 connection pool. 163 : bool isPoolHttp3(const ConnectionPool::Instance& pool); 164 : 165 : // Returns true if HTTP/3 is currently broken. While HTTP/3 is broken the grid will not 166 : // attempt to make new HTTP/3 connections. 167 : bool isHttp3Broken() const; 168 : 169 : // Marks HTTP/3 broken for a period of time subject to exponential backoff. While HTTP/3 170 : // is broken the grid will not attempt to make new HTTP/3 connections. 171 : void markHttp3Broken(); 172 : 173 : // Marks that HTTP/3 is working, which resets the exponential backoff counter in the 174 : // event that HTTP/3 is marked broken again. 175 : void markHttp3Confirmed(); 176 : 177 : // Http3::PoolConnectResultCallback 178 : void onHandshakeComplete() override; 179 : void onZeroRttHandshakeFailed() override; 180 : 181 : protected: 182 : // Set the required idle callback on the pool. 183 : void setupPool(ConnectionPool::Instance& pool); 184 : 185 : private: 186 : friend class ConnectivityGridForTest; 187 : 188 : // Return origin of the remote host. If the host doesn't have an IP address, 189 : // the port of the origin will be 0. 190 : HttpServerPropertiesCache::Http3StatusTracker& getHttp3StatusTracker() const; 191 : 192 : // Called by each pool as it idles. The grid is responsible for calling 193 : // idle_callbacks_ once all pools have idled. 194 : void onIdleReceived(); 195 : 196 : // Returns true if HTTP/3 should be attempted because there is an alternate protocol 197 : // that specifies HTTP/3 and HTTP/3 is not broken. 198 : bool shouldAttemptHttp3(); 199 : 200 : // Creates the next pool in the priority list, or absl::nullopt if all pools 201 : // have been created. 202 : virtual absl::optional<PoolIterator> createNextPool(); 203 : 204 : // This batch of member variables are latched objects required for pool creation. 205 : Event::Dispatcher& dispatcher_; 206 : Random::RandomGenerator& random_generator_; 207 : Upstream::HostConstSharedPtr host_; 208 : Upstream::ResourcePriority priority_; 209 : const Network::ConnectionSocket::OptionsSharedPtr options_; 210 : const Network::TransportSocketOptionsConstSharedPtr transport_socket_options_; 211 : Upstream::ClusterConnectivityState& state_; 212 : std::chrono::milliseconds next_attempt_duration_; 213 : TimeSource& time_source_; 214 : HttpServerPropertiesCacheSharedPtr alternate_protocols_; 215 : 216 : // True iff this pool is draining. No new streams or connections should be created 217 : // in this state. 218 : bool draining_{false}; 219 : 220 : // Tracks the callbacks to be called on drain completion. 221 : std::list<Instance::IdleCb> idle_callbacks_; 222 : 223 : // The connection pools to use to create new streams, ordered in the order of 224 : // desired use. 225 : std::list<ConnectionPool::InstancePtr> pools_; 226 : 227 : // True iff under the stack of the destructor, to avoid calling drain 228 : // callbacks on deletion. 229 : bool destroying_{}; 230 : 231 : // True iff this pool is being being defer deleted. 232 : bool deferred_deleting_{}; 233 : 234 : // Wrapped callbacks are stashed in the wrapped_callbacks_ for ownership. 235 : std::list<WrapperCallbacksPtr> wrapped_callbacks_; 236 : 237 : Quic::QuicStatNames& quic_stat_names_; 238 : Stats::Scope& scope_; 239 : // The origin for this pool. 240 : // Note the host name here is based off of the host name used for SNI, which 241 : // may be from the cluster config, or the request headers for auto-sni. 242 : HttpServerPropertiesCache::Origin origin_; 243 : Http::PersistentQuicInfo& quic_info_; 244 : }; 245 : 246 : } // namespace Http 247 : } // namespace Envoy