1
#pragma once
2

            
3
#include <atomic>
4
#include <cstdint>
5
#include <list>
6
#include <memory>
7
#include <string>
8

            
9
#include "envoy/common/scope_tracker.h"
10
#include "envoy/network/connection.h"
11
#include "envoy/network/transport_socket.h"
12

            
13
#include "source/common/network/connection_impl.h"
14

            
15
#include "absl/types/optional.h"
16

            
17
namespace Envoy {
18
namespace Network {
19

            
20
/**
21
 * An abstract class for providing next ClientConnectionPtr that can should used by
22
 * the HappyEyeballsConnectionImpl. Classes can inherit this class to provide
23
 * different kinds of connection creation strategies.
24
 */
25
class ConnectionProvider {
26
public:
27
105
  virtual ~ConnectionProvider() = default;
28

            
29
  /**
30
   * Whether there's still next connection to try.
31
   */
32
  virtual bool hasNextConnection() PURE;
33

            
34
  /**
35
   * Create next client connection.
36
   */
37
  virtual ClientConnectionPtr createNextConnection(const uint64_t id) PURE;
38

            
39
  /**
40
   * Return the index for the next connection.
41
   *
42
   */
43
  virtual size_t nextConnection() PURE;
44

            
45
  /**
46
   * Return the total count of connections the connection provider will make.
47
   *
48
   */
49
  virtual size_t totalConnections() PURE;
50
};
51

            
52
using ConnectionProviderPtr = std::unique_ptr<ConnectionProvider>;
53

            
54
/**
55
 * Implementation of ClientConnection which transparently attempts connections
56
 * provided by a ConnectionProvider, 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
 * This is originally a part of the `HapppyEyeballsConnectionImpl` but split for
66
 * broader use cases.
67
 */
68
class MultiConnectionBaseImpl : public ClientConnection,
69
                                Logger::Loggable<Logger::Id::multi_connection> {
70
public:
71
  MultiConnectionBaseImpl(Event::Dispatcher& dispatcher, ConnectionProviderPtr connection_provider);
72

            
73
  ~MultiConnectionBaseImpl() override;
74

            
75
  // Network::ClientConnection
76
  void connect() override;
77

            
78
  // Methods which defer action until the final connection has been determined.
79
  void addWriteFilter(WriteFilterSharedPtr filter) override;
80
  void addFilter(FilterSharedPtr filter) override;
81
  void addReadFilter(ReadFilterSharedPtr filter) override;
82
  void removeReadFilter(ReadFilterSharedPtr filter) override;
83
  bool initializeReadFilters() override;
84
  void addAccessLogHandler(AccessLog::InstanceSharedPtr handler) override;
85
  void addBytesSentCallback(BytesSentCb cb) override;
86
  void write(Buffer::Instance& data, bool end_stream) override;
87
  void addConnectionCallbacks(ConnectionCallbacks& cb) override;
88
  void removeConnectionCallbacks(ConnectionCallbacks& cb) override;
89

            
90
  // Methods which are applied to each connection attempt.
91
  void enableHalfClose(bool enabled) override;
92
  void noDelay(bool enable) override;
93
  ReadDisableStatus readDisable(bool disable) override;
94
  void detectEarlyCloseWhenReadDisabled(bool value) override;
95
  void setConnectionStats(const ConnectionStats& stats) override;
96
  void setDelayedCloseTimeout(std::chrono::milliseconds timeout) override;
97
  void setBufferLimits(uint32_t limit) override;
98
  void setBufferHighWatermarkTimeout(std::chrono::milliseconds timeout) override;
99
  bool startSecureTransport() override;
100
  absl::optional<std::chrono::milliseconds> lastRoundTripTime() const override;
101
  void configureInitialCongestionWindow(uint64_t, std::chrono::microseconds) override {}
102
  absl::optional<uint64_t> congestionWindowInBytes() const override;
103

            
104
  // Simple getters which always delegate to the first connection in connections_.
105
  bool isHalfCloseEnabled() const override;
106
  bool setSocketOption(Network::SocketOptionName name, absl::Span<uint8_t> value) override;
107
  std::string nextProtocol() const override;
108
  // Note, this might change before connect finishes.
109
  ConnectionInfoSetter& connectionInfoSetter() override;
110
  // Note, this might change before connect finishes.
111
  const ConnectionInfoProvider& connectionInfoProvider() const override;
112
  // Note, this might change before connect finishes.
113
  ConnectionInfoProviderSharedPtr connectionInfoProviderSharedPtr() const override;
114
  // Note, this might change before connect finishes.
115
  absl::optional<UnixDomainSocketPeerCredentials> unixSocketPeerCredentials() const override;
116
  // Note, this might change before connect finishes.
117
  Ssl::ConnectionInfoConstSharedPtr ssl() const override;
118
  State state() const override;
119
  bool connecting() const override;
120
  uint32_t bufferLimit() const override;
121
  const ConnectionSocket::OptionsSharedPtr& socketOptions() const override;
122
  absl::string_view requestedServerName() const override;
123
  StreamInfo::StreamInfo& streamInfo() override;
124
  const StreamInfo::StreamInfo& streamInfo() const override;
125
  absl::string_view transportFailureReason() const override;
126
  absl::string_view localCloseReason() const override;
127

            
128
  // Methods implemented largely by this class itself.
129
  uint64_t id() const override;
130
  Event::Dispatcher& dispatcher() const override;
131
3
  void close(ConnectionCloseType type) override { close(type, ""); }
132
  void close(ConnectionCloseType type, absl::string_view details) override;
133
  StreamInfo::DetectedCloseType detectedCloseType() const override;
134
  bool readEnabled() const override;
135
  bool aboveHighWatermark() const override;
136
  void hashKey(std::vector<uint8_t>& hash_key) const override;
137
  void dumpState(std::ostream& os, int indent_level) const override;
138

            
139
  const Network::ConnectionSocketPtr& getSocket() const override { PANIC("not implemented"); }
140

            
141
private:
142
  // ConnectionCallbacks which will be set on an ClientConnection which
143
  // sends connection events back to the MultiConnectionBaseImpl.
144
  class ConnectionCallbacksWrapper : public ConnectionCallbacks {
145
  public:
146
    ConnectionCallbacksWrapper(MultiConnectionBaseImpl& parent, ClientConnection& connection)
147
140
        : parent_(parent), connection_(connection) {}
148

            
149
73
    void onEvent(ConnectionEvent event) override { parent_.onEvent(event, this); }
150

            
151
1
    void onAboveWriteBufferHighWatermark() override {
152
      // No data will be written to the connection while the wrapper is associated with it,
153
      // so the write buffer should never hit the high watermark.
154
1
      IS_ENVOY_BUG("Unexpected data written to MultiConnectionBaseImpl");
155
1
    }
156

            
157
1
    void onBelowWriteBufferLowWatermark() override {
158
      // No data will be written to the connection while the wrapper is associated with it,
159
      // so the write buffer should never hit the high watermark.
160
1
      IS_ENVOY_BUG("Unexpected data drained from MultiConnectionBaseImpl");
161
1
    }
162

            
163
196
    ClientConnection& connection() { return connection_; }
164

            
165
  private:
166
    MultiConnectionBaseImpl& parent_;
167
    ClientConnection& connection_;
168
  };
169

            
170
  // Creates a connection to the next address in address_list_ and applies
171
  // any settings from per_connection_state_ to the newly created connection.
172
  ClientConnectionPtr createNextConnection();
173

            
174
  // Create a new connection, connects it and scheduled a timer to start another
175
  // connection attempt if there are more addresses to connect to.
176
  void tryAnotherConnection();
177

            
178
  // Schedules another connection attempt if there are mode address to connect to.
179
  void maybeScheduleNextAttempt();
180

            
181
  // Called by the wrapper when the wrapped connection raises the specified event.
182
  void onEvent(ConnectionEvent event, ConnectionCallbacksWrapper* wrapper);
183

            
184
  // Called to bind the final connection. All other connections will be closed, and
185
  // and deferred operations will be replayed.
186
  void setUpFinalConnection(ConnectionEvent event, ConnectionCallbacksWrapper* wrapper);
187

            
188
  // Called by the write buffer containing pending writes if it goes below the
189
  // low water mark.
190
  void onWriteBufferLowWatermark();
191

            
192
  // Called by the write buffer containing pending writes if it goes above the
193
  // high water mark.
194
  void onWriteBufferHighWatermark();
195

            
196
  // Cleans up all state for the connection associated with wrapper. Called when the
197
  // connection is no longer needed.
198
  void cleanupWrapperAndConnection(ConnectionCallbacksWrapper* wrapper);
199

            
200
  // State which needs to be applied to every connection attempt.
201
  struct PerConnectionState {
202
    absl::optional<bool> detect_early_close_when_read_disabled_;
203
    absl::optional<bool> no_delay_;
204
    absl::optional<bool> enable_half_close_;
205
    std::unique_ptr<ConnectionStats> connection_stats_;
206
    absl::optional<uint32_t> buffer_limits_;
207
    absl::optional<std::chrono::milliseconds> buffer_high_watermark_timeout_;
208
    absl::optional<bool> start_secure_transport_;
209
    absl::optional<std::chrono::milliseconds> delayed_close_timeout_;
210
  };
211

            
212
  // State which needs to be saved and applied only to the final connection
213
  // attempt.
214
  struct PostConnectState {
215
    std::vector<ConnectionCallbacks*> connection_callbacks_;
216
    std::vector<Connection::BytesSentCb> bytes_sent_callbacks_;
217
    std::vector<ReadFilterSharedPtr> read_filters_;
218
    std::vector<WriteFilterSharedPtr> write_filters_;
219
    std::vector<FilterSharedPtr> filters_;
220
    std::vector<AccessLog::InstanceSharedPtr> access_log_handlers_;
221
    absl::optional<Buffer::InstancePtr> write_buffer_;
222
    absl::optional<int> read_disable_count_;
223
    absl::optional<bool> end_stream_;
224
    absl::optional<bool> initialize_read_filters_;
225
  };
226

            
227
  // State which is needed to construct a new connection.
228
  struct ConnectionConstructionState {
229
    Address::InstanceConstSharedPtr source_address_;
230
    UpstreamTransportSocketFactory& socket_factory_;
231
    TransportSocketOptionsConstSharedPtr transport_socket_options_;
232
    const ConnectionSocket::OptionsSharedPtr options_;
233
  };
234

            
235
  // ID for this connection which is distinct from the ID of the underlying connections.
236
  const uint64_t id_;
237

            
238
  Event::Dispatcher& dispatcher_;
239

            
240
  ConnectionProviderPtr connection_provider_;
241

            
242
  PerConnectionState per_connection_state_;
243
  PostConnectState post_connect_state_;
244

            
245
  // Set of active connections.
246
  std::vector<ClientConnectionPtr> connections_;
247
  std::vector<std::unique_ptr<ConnectionCallbacksWrapper>> callbacks_wrappers_;
248

            
249
  // True when connect() has finished, either success or failure.
250
  bool connect_finished_ = false;
251
  Event::TimerPtr next_attempt_timer_;
252
};
253

            
254
} // namespace Network
255
} // namespace Envoy