Line data Source code
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 : HttpUpstream(Tcp::ConnectionPool::UpstreamCallbacks& callbacks, 133 : const TunnelingConfigHelper& config, StreamInfo::StreamInfo& downstream_info, 134 : Http::CodecType type); 135 : ~HttpUpstream() override; 136 : bool isValidResponse(const Http::ResponseHeaderMap&); 137 : 138 : void doneReading(); 139 : void doneWriting(); 140 0 : Http::ResponseDecoder& responseDecoder() { return response_decoder_; } 141 : 142 : // GenericUpstream 143 : bool readDisable(bool disable) override; 144 : void encodeData(Buffer::Instance& data, bool end_stream) override; 145 : void addBytesSentCallback(Network::Connection::BytesSentCb cb) override; 146 : Tcp::ConnectionPool::ConnectionData* onDownstreamEvent(Network::ConnectionEvent event) override; 147 : // HTTP upstream must not implement converting upstream transport 148 : // socket from non-secure to secure mode. 149 0 : bool startUpstreamSecureTransport() override { return false; } 150 : 151 : // Http::StreamCallbacks 152 : void onResetStream(Http::StreamResetReason reason, 153 : absl::string_view transport_failure_reason) override; 154 : void onAboveWriteBufferHighWatermark() override; 155 : void onBelowWriteBufferLowWatermark() override; 156 : 157 : void setRequestEncoder(Http::RequestEncoder& request_encoder, bool is_ssl); 158 0 : void setConnPoolCallbacks(std::unique_ptr<HttpConnPool::Callbacks>&& callbacks) { 159 0 : conn_pool_callbacks_ = std::move(callbacks); 160 0 : } 161 0 : Ssl::ConnectionInfoConstSharedPtr getUpstreamConnectionSslInfo() override { return nullptr; } 162 : 163 : protected: 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) {} 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 : const Http::CodecType type_; 212 : bool read_half_closed_{}; 213 : bool write_half_closed_{}; 214 : 215 : // Used to defer onGenericPoolReady and onGenericPoolFailure to the reception 216 : // of the CONNECT response or the resetEncoder. 217 : std::unique_ptr<HttpConnPool::Callbacks> conn_pool_callbacks_; 218 : }; 219 : 220 : } // namespace TcpProxy 221 : } // namespace Envoy