using UpstreamConnectMode = envoy::extensions::filters::network::tcp_proxy::v3::UpstreamConnectMode;
REGISTER_FACTORY(PerConnectionIdleTimeoutMsObjectFactory, StreamInfo::FilterState::ObjectFactory);
flush_access_log_on_connected_ = config.access_log_options().flush_access_log_on_connected();
const uint64_t max_jitter_ms = std::ceil(max_downstream_connection_duration.value().count() *
Config::SharedConfig::parseTLVs(absl::Span<const envoy::config::core::v3::TlvEntry* const> tlvs,
Config::SharedConfig::evaluateDynamicTLVs(const StreamInfo::StreamInfo& stream_info) const {
void Filter::initialize(Network::ReadFilterCallbacks& callbacks, bool set_connection_stats) {
if (read_disable_status == Network::Connection::ReadDisableStatus::TransitionedToReadDisabled) {
void Filter::UpstreamCallbacks::onUpstreamData(Buffer::Instance& data, bool end_stream) {
// Check this here because the TCP conn pool will queue our request waiting for a connection that
if (!cluster->resourceManager(Upstream::ResourcePriority::Default).connections().canCreate()) {
StreamInfo::FilterState::StateType::Mutable, StreamInfo::FilterState::LifeSpan::Connection);
if (auto typed_state = filter_state->getDataReadOnly<Network::UpstreamSocketOptionsFilterState>(
// No need to set information using address_provider in case routing via Router::UpstreamRequest
const auto filter_it = request_metadata.find(Envoy::Config::MetadataFilters::get().ENVOY_LB);
propagate_response_headers_(config_message.tunneling_config().propagate_response_headers()),
propagate_response_trailers_(config_message.tunneling_config().propagate_response_trailers()),
hostname_fmt_ = THROW_OR_RETURN_VALUE(Formatter::SubstitutionFormatStringUtils::fromProtoConfig(
std::string TunnelingConfigHelperImpl::host(const StreamInfo::StreamInfo& stream_info) const {
StreamInfo::FilterState::StateType::Mutable, StreamInfo::FilterState::LifeSpan::Connection);
TunnelResponseTrailers::key(), std::make_shared<TunnelResponseTrailers>(std::move(trailers)),
StreamInfo::FilterState::StateType::ReadOnly, StreamInfo::FilterState::LifeSpan::Connection);
resetIdleTimer(); // TODO(ggreenway) PERF: do we need to reset timer on both send and receive?
ENVOY_CONN_LOG(debug, "Delaying upstream connection establishment until initial data received",
ENVOY_CONN_LOG(trace, "on downstream event {}, has upstream = {}", read_callbacks_->connection(),
absl::string_view downstream_close_details = read_callbacks_->connection().localCloseReason();
resetIdleTimer(); // TODO(ggreenway) PERF: do we need to reset timer on both send and receive?
// Update the connecting flag before processing the event because we may start a new connection
getStreamInfo().upstreamInfo()->setUpstreamLocalCloseReason(upstream_->localCloseReason());
getStreamInfo().upstreamInfo()->setUpstreamDetectedCloseType(upstream_->detectedCloseType());
thread_local_cluster->info()->trafficStats()->upstream_cx_connect_attempts_exceeded_.inc();
// If we have received any data before upstream connection is established, or if the downstream
upstream_->addBytesSentCallback([upstream_callbacks = upstream_callbacks_](uint64_t) -> bool {
// earlier `ThreadLocal` slots (for accessing the runtime snapshot) so they must run before that
ENVOY_CONN_LOG(trace, "draining the upstream connection", upstream_conn_data_->connection());
Event::Dispatcher& Drainer::dispatcher() { return upstream_conn_data_->connection().dispatcher(); }