Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/source/common/tcp_proxy/upstream.h
Line
Count
Source (jump to first uncovered line)
1
#pragma once
2
3
#include "envoy/http/conn_pool.h"
4
#include "envoy/network/connection.h"
5
#include "envoy/tcp/conn_pool.h"
6
#include "envoy/tcp/upstream.h"
7
#include "envoy/upstream/load_balancer.h"
8
#include "envoy/upstream/thread_local_cluster.h"
9
#include "envoy/upstream/upstream.h"
10
11
#include "source/common/common/dump_state_utils.h"
12
#include "source/common/http/codec_client.h"
13
#include "source/common/router/header_parser.h"
14
15
namespace Envoy {
16
namespace TcpProxy {
17
18
constexpr absl::string_view DisableTunnelingFilterStateKey = "envoy.tcp_proxy.disable_tunneling";
19
20
class TcpConnPool : public GenericConnPool, public Tcp::ConnectionPool::Callbacks {
21
public:
22
  TcpConnPool(Upstream::ThreadLocalCluster& thread_local_cluster,
23
              Upstream::LoadBalancerContext* context,
24
              Tcp::ConnectionPool::UpstreamCallbacks& upstream_callbacks,
25
              StreamInfo::StreamInfo& downstream_info);
26
  ~TcpConnPool() override;
27
28
0
  bool valid() const { return conn_pool_data_.has_value(); }
29
30
  // GenericConnPool
31
  void newStream(GenericConnectionPoolCallbacks& callbacks) override;
32
33
  // Tcp::ConnectionPool::Callbacks
34
  void onPoolFailure(ConnectionPool::PoolFailureReason reason,
35
                     absl::string_view transport_failure_reason,
36
                     Upstream::HostDescriptionConstSharedPtr host) override;
37
  void onPoolReady(Tcp::ConnectionPool::ConnectionDataPtr&& conn_data,
38
                   Upstream::HostDescriptionConstSharedPtr host) override;
39
40
private:
41
  absl::optional<Upstream::TcpPoolData> conn_pool_data_{};
42
  Tcp::ConnectionPool::Cancellable* upstream_handle_{};
43
  GenericConnectionPoolCallbacks* callbacks_{};
44
  Tcp::ConnectionPool::UpstreamCallbacks& upstream_callbacks_;
45
  StreamInfo::StreamInfo& downstream_info_;
46
};
47
48
class HttpUpstream;
49
50
class HttpConnPool : public GenericConnPool, public Http::ConnectionPool::Callbacks {
51
public:
52
  HttpConnPool(Upstream::ThreadLocalCluster& thread_local_cluster,
53
               Upstream::LoadBalancerContext* context, const TunnelingConfigHelper& config,
54
               Tcp::ConnectionPool::UpstreamCallbacks& upstream_callbacks, Http::CodecType type,
55
               StreamInfo::StreamInfo& downstream_info);
56
  ~HttpConnPool() override;
57
58
0
  bool valid() const { return conn_pool_data_.has_value(); }
59
60
  // GenericConnPool
61
  void newStream(GenericConnectionPoolCallbacks& callbacks) override;
62
63
  // Http::ConnectionPool::Callbacks,
64
  void onPoolFailure(ConnectionPool::PoolFailureReason reason,
65
                     absl::string_view transport_failure_reason,
66
                     Upstream::HostDescriptionConstSharedPtr host) override;
67
  void onPoolReady(Http::RequestEncoder& request_encoder,
68
                   Upstream::HostDescriptionConstSharedPtr host, StreamInfo::StreamInfo& info,
69
                   absl::optional<Http::Protocol>) override;
70
71
  class Callbacks {
72
  public:
73
    Callbacks(HttpConnPool& conn_pool, Upstream::HostDescriptionConstSharedPtr host,
74
              Ssl::ConnectionInfoConstSharedPtr ssl_info)
75
0
        : conn_pool_(&conn_pool), host_(host), ssl_info_(ssl_info) {}
76
0
    virtual ~Callbacks() = default;
77
0
    virtual void onSuccess(Http::RequestEncoder& request_encoder) {
78
0
      ASSERT(conn_pool_ != nullptr);
79
0
      conn_pool_->onGenericPoolReady(host_, request_encoder.getStream().connectionInfoProvider(),
80
0
                                     ssl_info_);
81
0
    }
82
0
    virtual void onFailure() {
83
0
      ASSERT(conn_pool_ != nullptr);
84
0
      conn_pool_->callbacks_->onGenericPoolFailure(
85
0
          ConnectionPool::PoolFailureReason::RemoteConnectionFailure, "", host_);
86
0
    }
87
88
  protected:
89
    Callbacks() = default;
90
91
  private:
92
    HttpConnPool* conn_pool_{};
93
    Upstream::HostDescriptionConstSharedPtr host_;
94
    Ssl::ConnectionInfoConstSharedPtr ssl_info_;
95
  };
96
97
private:
98
  void onGenericPoolReady(Upstream::HostDescriptionConstSharedPtr& host,
99
                          const Network::ConnectionInfoProvider& address_provider,
100
                          Ssl::ConnectionInfoConstSharedPtr ssl_info);
101
  const TunnelingConfigHelper& config_;
102
  Http::CodecType type_;
103
  absl::optional<Upstream::HttpPoolData> conn_pool_data_{};
104
  Http::ConnectionPool::Cancellable* upstream_handle_{};
105
  GenericConnectionPoolCallbacks* callbacks_{};
106
  Tcp::ConnectionPool::UpstreamCallbacks& upstream_callbacks_;
107
  std::unique_ptr<HttpUpstream> upstream_;
108
  StreamInfo::StreamInfo& downstream_info_;
109
};
110
111
class TcpUpstream : public GenericUpstream {
112
public:
113
  TcpUpstream(Tcp::ConnectionPool::ConnectionDataPtr&& data,
114
              Tcp::ConnectionPool::UpstreamCallbacks& callbacks);
115
116
  // GenericUpstream
117
  bool readDisable(bool disable) override;
118
  void encodeData(Buffer::Instance& data, bool end_stream) override;
119
  void addBytesSentCallback(Network::Connection::BytesSentCb cb) override;
120
  Tcp::ConnectionPool::ConnectionData* onDownstreamEvent(Network::ConnectionEvent event) override;
121
  bool startUpstreamSecureTransport() override;
122
  Ssl::ConnectionInfoConstSharedPtr getUpstreamConnectionSslInfo() override;
123
124
private:
125
  Tcp::ConnectionPool::ConnectionDataPtr upstream_conn_data_;
126
};
127
128
class HttpUpstream : public GenericUpstream, protected Http::StreamCallbacks {
129
public:
130
  using TunnelingConfig =
131
      envoy::extensions::filters::network::tcp_proxy::v3::TcpProxy_TunnelingConfig;
132
133
  ~HttpUpstream() override;
134
  virtual bool isValidResponse(const Http::ResponseHeaderMap&) PURE;
135
136
  void doneReading();
137
  void doneWriting();
138
0
  Http::ResponseDecoder& responseDecoder() { return response_decoder_; }
139
140
  // GenericUpstream
141
  bool readDisable(bool disable) override;
142
  void encodeData(Buffer::Instance& data, bool end_stream) override;
143
  void addBytesSentCallback(Network::Connection::BytesSentCb cb) override;
144
  Tcp::ConnectionPool::ConnectionData* onDownstreamEvent(Network::ConnectionEvent event) override;
145
  // HTTP upstream must not implement converting upstream transport
146
  // socket from non-secure to secure mode.
147
0
  bool startUpstreamSecureTransport() override { return false; }
148
149
  // Http::StreamCallbacks
150
  void onResetStream(Http::StreamResetReason reason,
151
                     absl::string_view transport_failure_reason) override;
152
  void onAboveWriteBufferHighWatermark() override;
153
  void onBelowWriteBufferLowWatermark() override;
154
155
  virtual void setRequestEncoder(Http::RequestEncoder& request_encoder, bool is_ssl) PURE;
156
0
  void setConnPoolCallbacks(std::unique_ptr<HttpConnPool::Callbacks>&& callbacks) {
157
0
    conn_pool_callbacks_ = std::move(callbacks);
158
0
  }
159
0
  Ssl::ConnectionInfoConstSharedPtr getUpstreamConnectionSslInfo() override { return nullptr; }
160
161
protected:
162
  HttpUpstream(Tcp::ConnectionPool::UpstreamCallbacks& callbacks,
163
               const TunnelingConfigHelper& config, StreamInfo::StreamInfo& downstream_info);
164
  void resetEncoder(Network::ConnectionEvent event, bool inform_downstream = true);
165
166
  // The encoder offered by the upstream http client.
167
  Http::RequestEncoder* request_encoder_{};
168
  // The config object that is owned by the downstream network filter chain factory.
169
  const TunnelingConfigHelper& config_;
170
  // The downstream info that is owned by the downstream connection.
171
  StreamInfo::StreamInfo& downstream_info_;
172
173
private:
174
  class DecoderShim : public Http::ResponseDecoder {
175
  public:
176
0
    DecoderShim(HttpUpstream& parent) : parent_(parent) {}
Unexecuted instantiation: Envoy::TcpProxy::HttpUpstream::DecoderShim::DecoderShim(Envoy::TcpProxy::HttpUpstream&)
Unexecuted instantiation: Envoy::TcpProxy::HttpUpstream::DecoderShim::DecoderShim(Envoy::TcpProxy::HttpUpstream&)
177
    // Http::ResponseDecoder
178
0
    void decode1xxHeaders(Http::ResponseHeaderMapPtr&&) override {}
179
0
    void decodeHeaders(Http::ResponseHeaderMapPtr&& headers, bool end_stream) override {
180
0
      bool is_valid_response = parent_.isValidResponse(*headers);
181
0
      parent_.config_.propagateResponseHeaders(std::move(headers),
182
0
                                               parent_.downstream_info_.filterState());
183
0
      if (!is_valid_response || end_stream) {
184
0
        parent_.resetEncoder(Network::ConnectionEvent::LocalClose);
185
0
      } else if (parent_.conn_pool_callbacks_ != nullptr) {
186
0
        parent_.conn_pool_callbacks_->onSuccess(*parent_.request_encoder_);
187
0
        parent_.conn_pool_callbacks_.reset();
188
0
      }
189
0
    }
190
0
    void decodeData(Buffer::Instance& data, bool end_stream) override {
191
0
      parent_.upstream_callbacks_.onUpstreamData(data, end_stream);
192
0
      if (end_stream) {
193
0
        parent_.doneReading();
194
0
      }
195
0
    }
196
0
    void decodeTrailers(Http::ResponseTrailerMapPtr&& trailers) override {
197
0
      parent_.config_.propagateResponseTrailers(std::move(trailers),
198
0
                                                parent_.downstream_info_.filterState());
199
0
      parent_.doneReading();
200
0
    }
201
0
    void decodeMetadata(Http::MetadataMapPtr&&) override {}
202
0
    void dumpState(std::ostream& os, int indent_level) const override {
203
0
      DUMP_STATE_UNIMPLEMENTED(DecoderShim);
204
0
    }
205
206
  private:
207
    HttpUpstream& parent_;
208
  };
209
  DecoderShim response_decoder_;
210
  Tcp::ConnectionPool::UpstreamCallbacks& upstream_callbacks_;
211
  bool read_half_closed_{};
212
  bool write_half_closed_{};
213
214
  // Used to defer onGenericPoolReady and onGenericPoolFailure to the reception
215
  // of the CONNECT response or the resetEncoder.
216
  std::unique_ptr<HttpConnPool::Callbacks> conn_pool_callbacks_;
217
};
218
219
class Http1Upstream : public HttpUpstream {
220
public:
221
  Http1Upstream(Tcp::ConnectionPool::UpstreamCallbacks& callbacks,
222
                const TunnelingConfigHelper& config, StreamInfo::StreamInfo& downstream_info);
223
224
  void encodeData(Buffer::Instance& data, bool end_stream) override;
225
  void setRequestEncoder(Http::RequestEncoder& request_encoder, bool is_ssl) override;
226
  bool isValidResponse(const Http::ResponseHeaderMap& headers) override;
227
};
228
229
class Http2Upstream : public HttpUpstream {
230
public:
231
  Http2Upstream(Tcp::ConnectionPool::UpstreamCallbacks& callbacks,
232
                const TunnelingConfigHelper& config, StreamInfo::StreamInfo& downstream_info);
233
234
  void setRequestEncoder(Http::RequestEncoder& request_encoder, bool is_ssl) override;
235
  bool isValidResponse(const Http::ResponseHeaderMap& headers) override;
236
};
237
238
} // namespace TcpProxy
239
} // namespace Envoy