diff --git a/envoy/network/connection_handler.h b/envoy/network/connection_handler.h index d3a21b4bebb80..eb88410aba69e 100644 --- a/envoy/network/connection_handler.h +++ b/envoy/network/connection_handler.h @@ -219,6 +219,7 @@ class ActiveUdpListenerFactory { * @param runtime the runtime for this server. * @param worker_index The index of the worker this listener is being created on. * @param parent is the owner of the created ActiveListener objects. + * @param listen_socket_ptr is the UDP socket. * @param dispatcher is used to create actual UDP listener. * @param config provides information needed to create ActiveUdpListener and * UdpListener objects. @@ -226,8 +227,9 @@ class ActiveUdpListenerFactory { */ virtual ConnectionHandler::ActiveUdpListenerPtr createActiveUdpListener(Runtime::Loader& runtime, uint32_t worker_index, - UdpConnectionHandler& parent, Event::Dispatcher& dispatcher, - Network::ListenerConfig& config) PURE; + UdpConnectionHandler& parent, + Network::SocketSharedPtr&& listen_socket_ptr, + Event::Dispatcher& dispatcher, Network::ListenerConfig& config) PURE; /** * @return true if the UDP passing through listener doesn't form stateful connections. diff --git a/envoy/network/listener.h b/envoy/network/listener.h index c24b5ab961e6b..62dbfd4759cc9 100644 --- a/envoy/network/listener.h +++ b/envoy/network/listener.h @@ -146,10 +146,16 @@ class ListenerConfig { virtual FilterChainFactory& filterChainFactory() PURE; /** + * TODO(soulxu): This will be removed when multiple addresses listener implemented. * @return ListenSocketFactory& the factory to create listen socket. */ virtual ListenSocketFactory& listenSocketFactory() PURE; + /** + * @return std::vector& the factories to create listen sockets. + */ + virtual std::vector& listenSocketFactories() PURE; + /** * @return bool specifies whether the listener should actually listen on the port. * A listener that doesn't listen on a port can only receive connections diff --git a/source/common/quic/active_quic_listener.cc b/source/common/quic/active_quic_listener.cc index 17775ef19f663..8cf1db5699bdf 100644 --- a/source/common/quic/active_quic_listener.cc +++ b/source/common/quic/active_quic_listener.cc @@ -26,21 +26,7 @@ bool ActiveQuicListenerFactory::disable_kernel_bpf_packet_routing_for_test_ = fa ActiveQuicListener::ActiveQuicListener( Runtime::Loader& runtime, uint32_t worker_index, uint32_t concurrency, Event::Dispatcher& dispatcher, Network::UdpConnectionHandler& parent, - Network::ListenerConfig& listener_config, const quic::QuicConfig& quic_config, - bool kernel_worker_routing, const envoy::config::core::v3::RuntimeFeatureFlag& enabled, - QuicStatNames& quic_stat_names, uint32_t packets_received_to_connection_count_ratio, - EnvoyQuicCryptoServerStreamFactoryInterface& crypto_server_stream_factory, - EnvoyQuicProofSourceFactoryInterface& proof_source_factory) - : ActiveQuicListener(runtime, worker_index, concurrency, dispatcher, parent, - listener_config.listenSocketFactory().getListenSocket(worker_index), - listener_config, quic_config, kernel_worker_routing, enabled, - quic_stat_names, packets_received_to_connection_count_ratio, - crypto_server_stream_factory, proof_source_factory) {} - -ActiveQuicListener::ActiveQuicListener( - Runtime::Loader& runtime, uint32_t worker_index, uint32_t concurrency, - Event::Dispatcher& dispatcher, Network::UdpConnectionHandler& parent, - Network::SocketSharedPtr listen_socket, Network::ListenerConfig& listener_config, + Network::SocketSharedPtr&& listen_socket, Network::ListenerConfig& listener_config, const quic::QuicConfig& quic_config, bool kernel_worker_routing, const envoy::config::core::v3::RuntimeFeatureFlag& enabled, QuicStatNames& quic_stat_names, uint32_t packets_to_read_to_connection_count_ratio, @@ -338,11 +324,12 @@ ActiveQuicListenerFactory::ActiveQuicListenerFactory( Network::ConnectionHandler::ActiveUdpListenerPtr ActiveQuicListenerFactory::createActiveUdpListener( Runtime::Loader& runtime, uint32_t worker_index, Network::UdpConnectionHandler& parent, - Event::Dispatcher& disptacher, Network::ListenerConfig& config) { + Network::SocketSharedPtr&& listen_socket_ptr, Event::Dispatcher& disptacher, + Network::ListenerConfig& config) { ASSERT(crypto_server_stream_factory_.has_value()); return std::make_unique( - runtime, worker_index, concurrency_, disptacher, parent, config, quic_config_, - kernel_worker_routing_, enabled_, quic_stat_names_, + runtime, worker_index, concurrency_, disptacher, parent, std::move(listen_socket_ptr), config, + quic_config_, kernel_worker_routing_, enabled_, quic_stat_names_, packets_to_read_to_connection_count_ratio_, crypto_server_stream_factory_.value(), proof_source_factory_.value()); } diff --git a/source/common/quic/active_quic_listener.h b/source/common/quic/active_quic_listener.h index 6feda1abc7c22..b8a1b3a58d118 100644 --- a/source/common/quic/active_quic_listener.h +++ b/source/common/quic/active_quic_listener.h @@ -30,17 +30,7 @@ class ActiveQuicListener : public Envoy::Server::ActiveUdpListenerBase, ActiveQuicListener(Runtime::Loader& runtime, uint32_t worker_index, uint32_t concurrency, Event::Dispatcher& dispatcher, Network::UdpConnectionHandler& parent, - Network::ListenerConfig& listener_config, const quic::QuicConfig& quic_config, - bool kernel_worker_routing, - const envoy::config::core::v3::RuntimeFeatureFlag& enabled, - QuicStatNames& quic_stat_names, - uint32_t packets_to_read_to_connection_count_ratio, - EnvoyQuicCryptoServerStreamFactoryInterface& crypto_server_stream_factory, - EnvoyQuicProofSourceFactoryInterface& proof_source_factory); - - ActiveQuicListener(Runtime::Loader& runtime, uint32_t worker_index, uint32_t concurrency, - Event::Dispatcher& dispatcher, Network::UdpConnectionHandler& parent, - Network::SocketSharedPtr listen_socket, + Network::SocketSharedPtr&& listen_socket, Network::ListenerConfig& listener_config, const quic::QuicConfig& quic_config, bool kernel_worker_routing, const envoy::config::core::v3::RuntimeFeatureFlag& enabled, @@ -108,8 +98,9 @@ class ActiveQuicListenerFactory : public Network::ActiveUdpListenerFactory, // Network::ActiveUdpListenerFactory. Network::ConnectionHandler::ActiveUdpListenerPtr createActiveUdpListener(Runtime::Loader& runtime, uint32_t worker_index, - Network::UdpConnectionHandler& parent, Event::Dispatcher& disptacher, - Network::ListenerConfig& config) override; + Network::UdpConnectionHandler& parent, + Network::SocketSharedPtr&& listen_socket_ptr, + Event::Dispatcher& disptacher, Network::ListenerConfig& config) override; bool isTransportConnectionless() const override { return false; } const Network::Socket::OptionsSharedPtr& socketOptions() const override { return options_; } diff --git a/source/server/active_raw_udp_listener_config.cc b/source/server/active_raw_udp_listener_config.cc index e149dadf00716..dca62508ed01e 100644 --- a/source/server/active_raw_udp_listener_config.cc +++ b/source/server/active_raw_udp_listener_config.cc @@ -15,10 +15,11 @@ ActiveRawUdpListenerFactory::ActiveRawUdpListenerFactory(uint32_t concurrency) Network::ConnectionHandler::ActiveUdpListenerPtr ActiveRawUdpListenerFactory::createActiveUdpListener(Runtime::Loader&, uint32_t worker_index, Network::UdpConnectionHandler& parent, + Network::SocketSharedPtr&& listen_socket_ptr, Event::Dispatcher& dispatcher, Network::ListenerConfig& config) { - return std::make_unique(worker_index, concurrency_, parent, dispatcher, - config); + return std::make_unique(worker_index, concurrency_, parent, + std::move(listen_socket_ptr), dispatcher, config); } } // namespace Server diff --git a/source/server/active_raw_udp_listener_config.h b/source/server/active_raw_udp_listener_config.h index 4b79d9ed6d4f5..a94e31e0c1fe3 100644 --- a/source/server/active_raw_udp_listener_config.h +++ b/source/server/active_raw_udp_listener_config.h @@ -11,8 +11,9 @@ class ActiveRawUdpListenerFactory : public Network::ActiveUdpListenerFactory { Network::ConnectionHandler::ActiveUdpListenerPtr createActiveUdpListener(Runtime::Loader&, uint32_t worker_index, - Network::UdpConnectionHandler& parent, Event::Dispatcher& disptacher, - Network::ListenerConfig& config) override; + Network::UdpConnectionHandler& parent, + Network::SocketSharedPtr&& listen_socket_ptr, + Event::Dispatcher& disptacher, Network::ListenerConfig& config) override; bool isTransportConnectionless() const override { return true; } const Network::Socket::OptionsSharedPtr& socketOptions() const override { return options_; } diff --git a/source/server/active_tcp_listener.cc b/source/server/active_tcp_listener.cc index 78b435c0aad62..3581e72ad58ad 100644 --- a/source/server/active_tcp_listener.cc +++ b/source/server/active_tcp_listener.cc @@ -14,13 +14,12 @@ namespace Server { ActiveTcpListener::ActiveTcpListener(Network::TcpConnectionHandler& parent, Network::ListenerConfig& config, Runtime::Loader& runtime, - uint32_t worker_index) - : OwnedActiveStreamListenerBase(parent, parent.dispatcher(), - parent.dispatcher().createListener( - config.listenSocketFactory().getListenSocket(worker_index), - *this, runtime, config.bindToPort(), - config.ignoreGlobalConnLimit()), - config), + Network::SocketSharedPtr&& socket) + : OwnedActiveStreamListenerBase( + parent, parent.dispatcher(), + parent.dispatcher().createListener(std::move(socket), *this, runtime, config.bindToPort(), + config.ignoreGlobalConnLimit()), + config), tcp_conn_handler_(parent) { config.connectionBalancer().registerHandler(*this); } diff --git a/source/server/active_tcp_listener.h b/source/server/active_tcp_listener.h index ba3fc15fbdb63..6e9fd2c2a541b 100644 --- a/source/server/active_tcp_listener.h +++ b/source/server/active_tcp_listener.h @@ -27,7 +27,7 @@ class ActiveTcpListener final : public Network::TcpListenerCallbacks, public Network::BalancedConnectionHandler { public: ActiveTcpListener(Network::TcpConnectionHandler& parent, Network::ListenerConfig& config, - Runtime::Loader& runtime, uint32_t worker_index); + Runtime::Loader& runtime, Network::SocketSharedPtr&& socket); ActiveTcpListener(Network::TcpConnectionHandler& parent, Network::ListenerPtr&& listener, Network::ListenerConfig& config, Runtime::Loader& runtime); ~ActiveTcpListener() override; diff --git a/source/server/active_udp_listener.cc b/source/server/active_udp_listener.cc index e0d4c64f73f89..64a46a0c68ef5 100644 --- a/source/server/active_udp_listener.cc +++ b/source/server/active_udp_listener.cc @@ -63,14 +63,6 @@ void ActiveUdpListenerBase::onData(Network::UdpRecvData&& data) { } } -ActiveRawUdpListener::ActiveRawUdpListener(uint32_t worker_index, uint32_t concurrency, - Network::UdpConnectionHandler& parent, - Event::Dispatcher& dispatcher, - Network::ListenerConfig& config) - : ActiveRawUdpListener(worker_index, concurrency, parent, - config.listenSocketFactory().getListenSocket(worker_index), dispatcher, - config) {} - ActiveRawUdpListener::ActiveRawUdpListener(uint32_t worker_index, uint32_t concurrency, Network::UdpConnectionHandler& parent, Network::SocketSharedPtr listen_socket_ptr, diff --git a/source/server/active_udp_listener.h b/source/server/active_udp_listener.h index dff9406c44366..37e559828cf5d 100644 --- a/source/server/active_udp_listener.h +++ b/source/server/active_udp_listener.h @@ -65,9 +65,6 @@ class ActiveRawUdpListener : public ActiveUdpListenerBase, public Network::UdpReadFilterCallbacks, Logger::Loggable { public: - ActiveRawUdpListener(uint32_t worker_index, uint32_t concurrency, - Network::UdpConnectionHandler& parent, Event::Dispatcher& dispatcher, - Network::ListenerConfig& config); ActiveRawUdpListener(uint32_t worker_index, uint32_t concurrency, Network::UdpConnectionHandler& parent, Network::SocketSharedPtr listen_socket_ptr, Event::Dispatcher& dispatcher, diff --git a/source/server/admin/admin.cc b/source/server/admin/admin.cc index 629b8fcda0171..9efe33c00a191 100644 --- a/source/server/admin/admin.cc +++ b/source/server/admin/admin.cc @@ -128,7 +128,7 @@ void AdminImpl::startHttpListener(const std::list& socket_ = std::make_shared(address, socket_options, true); RELEASE_ASSERT(0 == socket_->ioHandle().listen(ENVOY_TCP_BACKLOG_SIZE).return_value_, "listen() failed on admin listener"); - socket_factory_ = std::make_unique(socket_); + socket_factories_.emplace_back(std::make_unique(socket_)); listener_ = std::make_unique(*this, std::move(listener_scope)); ENVOY_LOG(info, "admin address: {}", socket().connectionInfoProvider().localAddress()->asString()); diff --git a/source/server/admin/admin.h b/source/server/admin/admin.h index 151d10ba6eee9..ef314d9ca4425 100644 --- a/source/server/admin/admin.h +++ b/source/server/admin/admin.h @@ -390,7 +390,11 @@ class AdminImpl : public Admin, Network::FilterChainManager& filterChainManager() override { return parent_; } Network::FilterChainFactory& filterChainFactory() override { return parent_; } Network::ListenSocketFactory& listenSocketFactory() override { - return *parent_.socket_factory_; + ASSERT(parent_.socket_factories_.size() == 1); + return *parent_.socket_factories_[0]; + } + std::vector& listenSocketFactories() override { + return parent_.socket_factories_; } bool bindToPort() override { return true; } bool handOffRestoredDestinationConnections() const override { return false; } @@ -495,7 +499,7 @@ class AdminImpl : public Admin, ConfigTrackerImpl config_tracker_; const Network::FilterChainSharedPtr admin_filter_chain_; Network::SocketSharedPtr socket_; - Network::ListenSocketFactoryPtr socket_factory_; + std::vector socket_factories_; AdminListenerPtr listener_; const AdminInternalAddressConfig internal_address_config_; const LocalReply::LocalReplyPtr local_reply_; diff --git a/source/server/connection_handler_impl.cc b/source/server/connection_handler_impl.cc index 7838584984f8a..93c5ef1357015 100644 --- a/source/server/connection_handler_impl.cc +++ b/source/server/connection_handler_impl.cc @@ -35,11 +35,14 @@ void ConnectionHandlerImpl::addListener(absl::optional overridden_list ActiveListenerDetailsOptRef listener_detail = findActiveListenerByTag(overridden_listener.value()); ASSERT(listener_detail.has_value()); - listener_detail->get().listener_->updateListenerConfig(config); + listener_detail->get().invokeListenerMethod( + [&config](Network::ConnectionHandler::ActiveListener& listener) { + listener.updateListenerConfig(config); + }); return; } - auto details = std::make_shared(); + auto details = std::make_unique(); if (config.internalListenerConfig().has_value()) { // Ensure the this ConnectionHandlerImpl link to the thread local registry. Ideally this step // should be done only once. However, an extra phase and interface is overkill. @@ -52,91 +55,98 @@ void ConnectionHandlerImpl::addListener(absl::optional overridden_list if (overridden_listener.has_value()) { if (auto iter = listener_map_by_tag_.find(overridden_listener.value()); iter != listener_map_by_tag_.end()) { - iter->second->internalListener()->updateListenerConfig(config); + iter->second->invokeListenerMethod( + [&config](Network::ConnectionHandler::ActiveListener& listener) { + listener.updateListenerConfig(config); + }); return; } IS_ENVOY_BUG("unexpected"); } auto internal_listener = local_registry->createActiveInternalListener(*this, config, dispatcher()); - details->typed_listener_ = *internal_listener; - details->listener_ = std::move(internal_listener); - } else if (config.listenSocketFactory().socketType() == Network::Socket::Type::Stream) { + // TODO(soulxu): support multiple internal addresses in listener in the future. + ASSERT(config.listenSocketFactories().size() == 1); + details->addActiveListener(config, config.listenSocketFactories()[0], listener_reject_fraction_, + disable_listeners_, std::move(internal_listener)); + } else if (config.listenSocketFactories()[0]->socketType() == Network::Socket::Type::Stream) { if (!support_udp_in_place_filter_chain_update && overridden_listener.has_value()) { if (auto iter = listener_map_by_tag_.find(overridden_listener.value()); iter != listener_map_by_tag_.end()) { - iter->second->tcpListener()->get().updateListenerConfig(config); + iter->second->invokeListenerMethod( + [&config](Network::ConnectionHandler::ActiveListener& listener) { + listener.updateListenerConfig(config); + }); return; } IS_ENVOY_BUG("unexpected"); } - // worker_index_ doesn't have a value on the main thread for the admin server. - auto tcp_listener = std::make_unique( - *this, config, runtime, worker_index_.has_value() ? *worker_index_ : 0); - details->typed_listener_ = *tcp_listener; - details->listener_ = std::move(tcp_listener); + for (auto& socket_factory : config.listenSocketFactories()) { + // worker_index_ doesn't have a value on the main thread for the admin server. + details->addActiveListener( + config, socket_factory, listener_reject_fraction_, disable_listeners_, + std::make_unique( + *this, config, runtime, + socket_factory->getListenSocket(worker_index_.has_value() ? *worker_index_ : 0))); + } + } else { ASSERT(config.udpListenerConfig().has_value(), "UDP listener factory is not initialized."); ASSERT(worker_index_.has_value()); - ConnectionHandler::ActiveUdpListenerPtr udp_listener = - config.udpListenerConfig()->listenerFactory().createActiveUdpListener( - runtime, *worker_index_, *this, dispatcher_, config); - details->typed_listener_ = *udp_listener; - details->listener_ = std::move(udp_listener); - } - - if (disable_listeners_) { - details->listener_->pauseListening(); - } - if (auto* listener = details->listener_->listener(); listener != nullptr) { - listener->setRejectFraction(listener_reject_fraction_); + for (auto& socket_factory : config.listenSocketFactories()) { + details->addActiveListener( + config, socket_factory, listener_reject_fraction_, disable_listeners_, + config.udpListenerConfig()->listenerFactory().createActiveUdpListener( + runtime, *worker_index_, *this, + config.listenSocketFactories()[0]->getListenSocket(*worker_index_), dispatcher_, + config)); + } } - details->listener_tag_ = config.listenerTag(); - details->address_ = config.listenSocketFactory().localAddress(); - ASSERT(!listener_map_by_tag_.contains(config.listenerTag())); - listener_map_by_tag_.emplace(config.listenerTag(), details); - // This map only store the new listener. - if (absl::holds_alternative>( - details->typed_listener_)) { - tcp_listener_map_by_address_.insert_or_assign( - config.listenSocketFactory().localAddress()->asStringView(), details); - - auto& address = details->address_; - // If the address is Ipv6 and isn't v6only, parse out the ipv4 compatible address from the Ipv6 - // address and put an item to the map. Then this allows the `getBalancedHandlerByAddress` - // can match the Ipv4 request to Ipv4-mapped address also. - if (address->type() == Network::Address::Type::Ip && - address->ip()->version() == Network::Address::IpVersion::v6 && - !address->ip()->ipv6()->v6only()) { - if (address->ip()->isAnyAddress()) { - // Since both "::" with ipv4_compat and "0.0.0.0" can be supported. - // If there already one and it isn't shutdown for compatible addr, - // then won't insert a new one. - auto ipv4_any_address = Network::Address::Ipv4Instance(address->ip()->port()).asString(); - auto ipv4_any_listener = tcp_listener_map_by_address_.find(ipv4_any_address); - if (ipv4_any_listener == tcp_listener_map_by_address_.end() || - ipv4_any_listener->second->listener_->listener() == nullptr) { - tcp_listener_map_by_address_.insert_or_assign(ipv4_any_address, details); - } - } else { - auto v4_compatible_addr = address->ip()->ipv6()->v4CompatibleAddress(); - // Remove this check when runtime flag - // `envoy.reloadable_features.strict_check_on_ipv4_compat` deprecated. - // If this isn't a valid Ipv4-mapped address, then do nothing. - if (v4_compatible_addr != nullptr) { - tcp_listener_map_by_address_.insert_or_assign(v4_compatible_addr->asStringView(), - details); + for (const auto& per_address_details : details->per_address_details_list_) { + // This map only stores the new listener. + if (absl::holds_alternative>( + per_address_details->typed_listener_)) { + tcp_listener_map_by_address_.insert_or_assign(per_address_details->address_->asStringView(), + per_address_details); + + auto& address = per_address_details->address_; + // If the address is Ipv6 and isn't v6only, parse out the ipv4 compatible address from the + // Ipv6 address and put an item to the map. Then this allows the `getBalancedHandlerByAddress` + // can match the Ipv4 request to Ipv4-mapped address also. + if (address->type() == Network::Address::Type::Ip && + address->ip()->version() == Network::Address::IpVersion::v6 && + !address->ip()->ipv6()->v6only()) { + if (address->ip()->isAnyAddress()) { + // Since both "::" with ipv4_compat and "0.0.0.0" can be supported. + // If there already one and it isn't shutdown for compatible addr, + // then won't insert a new one. + auto ipv4_any_address = Network::Address::Ipv4Instance(address->ip()->port()).asString(); + auto ipv4_any_listener = tcp_listener_map_by_address_.find(ipv4_any_address); + if (ipv4_any_listener == tcp_listener_map_by_address_.end() || + ipv4_any_listener->second->listener_->listener() == nullptr) { + tcp_listener_map_by_address_.insert_or_assign(ipv4_any_address, per_address_details); + } + } else { + auto v4_compatible_addr = address->ip()->ipv6()->v4CompatibleAddress(); + // Remove this check when runtime flag + // `envoy.reloadable_features.strict_check_on_ipv4_compat` deprecated. + // If this isn't a valid Ipv4-mapped address, then do nothing. + if (v4_compatible_addr != nullptr) { + tcp_listener_map_by_address_.insert_or_assign(v4_compatible_addr->asStringView(), + per_address_details); + } } } + } else if (absl::holds_alternative>( + per_address_details->typed_listener_)) { + internal_listener_map_by_address_.insert_or_assign( + per_address_details->address_->asStringView(), per_address_details); } - } else if (absl::holds_alternative>( - details->typed_listener_)) { - internal_listener_map_by_address_.insert_or_assign( - config.listenSocketFactory().localAddress()->asStringView(), details); } + listener_map_by_tag_.emplace(config.listenerTag(), std::move(details)); } void ConnectionHandlerImpl::removeListeners(uint64_t listener_tag) { @@ -144,41 +154,43 @@ void ConnectionHandlerImpl::removeListeners(uint64_t listener_tag) { listener_iter != listener_map_by_tag_.end()) { // listener_map_by_address_ may already update to the new listener. Compare it with the one // which find from listener_map_by_tag_, only delete it when it is same listener. - auto& address = listener_iter->second->address_; - auto address_view = address->asStringView(); - if (tcp_listener_map_by_address_.contains(address_view) && - tcp_listener_map_by_address_[address_view]->listener_tag_ == - listener_iter->second->listener_tag_) { - tcp_listener_map_by_address_.erase(address_view); - - // If the address is Ipv6 and isn't v6only, delete the corresponding Ipv4 item from the map. - if (address->type() == Network::Address::Type::Ip && - address->ip()->version() == Network::Address::IpVersion::v6 && - !address->ip()->ipv6()->v6only()) { - if (address->ip()->isAnyAddress()) { - auto ipv4_any_addr_iter = tcp_listener_map_by_address_.find( - Network::Address::Ipv4Instance(address->ip()->port()).asStringView()); - // Since both "::" with ipv4_compat and "0.0.0.0" can be supported, ensure they are same - // listener by tag. - if (ipv4_any_addr_iter != tcp_listener_map_by_address_.end() && - ipv4_any_addr_iter->second->listener_tag_ == listener_iter->second->listener_tag_) { - tcp_listener_map_by_address_.erase(ipv4_any_addr_iter); - } - } else { - auto v4_compatible_addr = address->ip()->ipv6()->v4CompatibleAddress(); - // Remove this check when runtime flag - // `envoy.reloadable_features.strict_check_on_ipv4_compat` deprecated. - if (v4_compatible_addr != nullptr) { - // both "::FFFF:" with ipv4_compat and "" isn't valid case, - // remove the v4 compatible addr item directly. - tcp_listener_map_by_address_.erase(v4_compatible_addr->asStringView()); + for (const auto& per_address_details : listener_iter->second->per_address_details_list_) { + auto& address = per_address_details->address_; + auto address_view = address->asStringView(); + if (tcp_listener_map_by_address_.contains(address_view) && + tcp_listener_map_by_address_[address_view]->listener_tag_ == + per_address_details->listener_tag_) { + tcp_listener_map_by_address_.erase(address_view); + + // If the address is Ipv6 and isn't v6only, delete the corresponding Ipv4 item from the map. + if (address->type() == Network::Address::Type::Ip && + address->ip()->version() == Network::Address::IpVersion::v6 && + !address->ip()->ipv6()->v6only()) { + if (address->ip()->isAnyAddress()) { + auto ipv4_any_addr_iter = tcp_listener_map_by_address_.find( + Network::Address::Ipv4Instance(address->ip()->port()).asStringView()); + // Since both "::" with ipv4_compat and "0.0.0.0" can be supported, ensure they are same + // listener by tag. + if (ipv4_any_addr_iter != tcp_listener_map_by_address_.end() && + ipv4_any_addr_iter->second->listener_tag_ == per_address_details->listener_tag_) { + tcp_listener_map_by_address_.erase(ipv4_any_addr_iter); + } + } else { + auto v4_compatible_addr = address->ip()->ipv6()->v4CompatibleAddress(); + // Remove this check when runtime flag + // `envoy.reloadable_features.strict_check_on_ipv4_compat` deprecated. + if (v4_compatible_addr != nullptr) { + // both "::FFFF:" with ipv4_compat and "" isn't valid case, + // remove the v4 compatible addr item directly. + tcp_listener_map_by_address_.erase(v4_compatible_addr->asStringView()); + } } } + } else if (internal_listener_map_by_address_.contains(address_view) && + internal_listener_map_by_address_[address_view]->listener_tag_ == + per_address_details->listener_tag_) { + internal_listener_map_by_address_.erase(address_view); } - } else if (internal_listener_map_by_address_.contains(address_view) && - internal_listener_map_by_address_[address_view]->listener_tag_ == - listener_iter->second->listener_tag_) { - internal_listener_map_by_address_.erase(address_view); } listener_map_by_tag_.erase(listener_iter); } @@ -189,7 +201,9 @@ ConnectionHandlerImpl::getUdpListenerCallbacks(uint64_t listener_tag) { auto listener = findActiveListenerByTag(listener_tag); if (listener.has_value()) { // If the tag matches this must be a UDP listener. - auto udp_listener = listener->get().udpListener(); + // TODO(soulxu): return first listener here, this will be changed + // when UdpWorkerRouter supports the multiple addresses. + auto udp_listener = listener->get().per_address_details_list_[0]->udpListener(); ASSERT(udp_listener.has_value()); return udp_listener; } @@ -202,7 +216,10 @@ void ConnectionHandlerImpl::removeFilterChains( std::function completion) { if (auto listener_it = listener_map_by_tag_.find(listener_tag); listener_it != listener_map_by_tag_.end()) { - listener_it->second->listener_->onFilterChainDraining(filter_chains); + listener_it->second->invokeListenerMethod( + [&filter_chains](Network::ConnectionHandler::ActiveListener& listener) { + listener.onFilterChainDraining(filter_chains); + }); } // Reach here if the target listener is found or the target listener was removed by a full @@ -213,44 +230,55 @@ void ConnectionHandlerImpl::removeFilterChains( void ConnectionHandlerImpl::stopListeners(uint64_t listener_tag) { if (auto iter = listener_map_by_tag_.find(listener_tag); iter != listener_map_by_tag_.end()) { - if (iter->second->listener_->listener() != nullptr) { - iter->second->listener_->shutdownListener(); - } + iter->second->invokeListenerMethod([](Network::ConnectionHandler::ActiveListener& listener) { + if (listener.listener() != nullptr) { + listener.shutdownListener(); + } + }); } } void ConnectionHandlerImpl::stopListeners() { for (auto& iter : listener_map_by_tag_) { - if (iter.second->listener_->listener() != nullptr) { - iter.second->listener_->shutdownListener(); - } + iter.second->invokeListenerMethod([](Network::ConnectionHandler::ActiveListener& listener) { + if (listener.listener() != nullptr) { + listener.shutdownListener(); + } + }); } } void ConnectionHandlerImpl::disableListeners() { disable_listeners_ = true; for (auto& iter : listener_map_by_tag_) { - if (iter.second->listener_->listener() != nullptr) { - iter.second->listener_->pauseListening(); - } + iter.second->invokeListenerMethod([](Network::ConnectionHandler::ActiveListener& listener) { + if (listener.listener() != nullptr) { + listener.pauseListening(); + } + }); } } void ConnectionHandlerImpl::enableListeners() { disable_listeners_ = false; for (auto& iter : listener_map_by_tag_) { - if (iter.second->listener_->listener() != nullptr) { - iter.second->listener_->resumeListening(); - } + iter.second->invokeListenerMethod([](Network::ConnectionHandler::ActiveListener& listener) { + if (listener.listener() != nullptr) { + listener.resumeListening(); + } + }); } } void ConnectionHandlerImpl::setListenerRejectFraction(UnitFloat reject_fraction) { listener_reject_fraction_ = reject_fraction; for (auto& iter : listener_map_by_tag_) { - if (iter.second->listener_->listener() != nullptr) { - iter.second->listener_->listener()->setRejectFraction(reject_fraction); - } + iter.second->invokeListenerMethod( + [&reject_fraction](Network::ConnectionHandler::ActiveListener& listener) { + if (listener.listener() != nullptr) { + listener.listener()->setRejectFraction(reject_fraction); + } + }); } } @@ -265,18 +293,19 @@ ConnectionHandlerImpl::findByAddress(const Network::Address::InstanceConstShared } ConnectionHandlerImpl::ActiveTcpListenerOptRef -ConnectionHandlerImpl::ActiveListenerDetails::tcpListener() { +ConnectionHandlerImpl::PerAddressActiveListenerDetails::tcpListener() { auto* val = absl::get_if>(&typed_listener_); return (val != nullptr) ? absl::make_optional(*val) : absl::nullopt; } ConnectionHandlerImpl::UdpListenerCallbacksOptRef -ConnectionHandlerImpl::ActiveListenerDetails::udpListener() { +ConnectionHandlerImpl::PerAddressActiveListenerDetails::udpListener() { auto* val = absl::get_if>(&typed_listener_); return (val != nullptr) ? absl::make_optional(*val) : absl::nullopt; } -Network::InternalListenerOptRef ConnectionHandlerImpl::ActiveListenerDetails::internalListener() { +Network::InternalListenerOptRef +ConnectionHandlerImpl::PerAddressActiveListenerDetails::internalListener() { auto* val = absl::get_if>(&typed_listener_); return (val != nullptr) ? makeOptRef(val->get()) : absl::nullopt; } @@ -293,11 +322,12 @@ Network::BalancedConnectionHandlerOptRef ConnectionHandlerImpl::getBalancedHandlerByTag(uint64_t listener_tag) { auto active_listener = findActiveListenerByTag(listener_tag); if (active_listener.has_value()) { + // TODO(soulxu): return first listener here, this will be changed + // when ConnectionBalancer supports the multiple addresses. ASSERT(absl::holds_alternative>( - active_listener->get().typed_listener_) && - active_listener->get().listener_->listener() != nullptr); - return Network::BalancedConnectionHandlerOptRef( - active_listener->get().tcpListener().value().get()); + active_listener->get().per_address_details_list_[0]->typed_listener_) && + active_listener->get().per_address_details_list_[0]->listener_->listener() != nullptr); + return active_listener->get().per_address_details_list_[0]->tcpListener().value().get(); } return absl::nullopt; } @@ -316,7 +346,7 @@ ConnectionHandlerImpl::getBalancedHandlerByAddress(const Network::Address::Insta listener_it->second->tcpListener().value().get()); } - OptRef details; + OptRef details; // Otherwise, we need to look for the wild card match, i.e., 0.0.0.0:[address_port]. // We do not return stopped listeners. // TODO(wattli): consolidate with previous search for more efficiency. diff --git a/source/server/connection_handler_impl.h b/source/server/connection_handler_impl.h index 3b6fd639ea816..95ed03f04e928 100644 --- a/source/server/connection_handler_impl.h +++ b/source/server/connection_handler_impl.h @@ -70,7 +70,7 @@ class ConnectionHandlerImpl : public Network::TcpConnectionHandler, findByAddress(const Network::Address::InstanceConstSharedPtr& listen_address) override; private: - struct ActiveListenerDetails { + struct PerAddressActiveListenerDetails { // Strong pointer to the listener, whether TCP, UDP, QUIC, etc. Network::ConnectionHandler::ActiveListenerPtr listener_; Network::Address::InstanceConstSharedPtr address_; @@ -86,6 +86,45 @@ class ConnectionHandlerImpl : public Network::TcpConnectionHandler, UdpListenerCallbacksOptRef udpListener(); Network::InternalListenerOptRef internalListener(); }; + + struct ActiveListenerDetails { + std::vector> per_address_details_list_; + + using ListenerMethodFn = std::function; + + /** + * A helper to execute specific method on each PerAddressActiveListenerDetails item. + */ + void invokeListenerMethod(ListenerMethodFn fn) { + std::for_each(per_address_details_list_.begin(), per_address_details_list_.end(), + [&fn](std::shared_ptr& details) { + fn(*details->listener_); + }); + } + + /** + * Add an ActiveListener into the list. + */ + template + void addActiveListener(Network::ListenerConfig& config, + const Network::ListenSocketFactoryPtr& socket_factory, + UnitFloat& listener_reject_fraction, bool disable_listeners, + ActiveListener&& listener) { + auto per_address_details = std::make_shared(); + per_address_details->typed_listener_ = *listener; + per_address_details->listener_ = std::move(listener); + per_address_details->address_ = socket_factory->localAddress(); + if (disable_listeners) { + per_address_details->listener_->pauseListening(); + } + if (auto* listener = per_address_details->listener_->listener(); listener != nullptr) { + listener->setRejectFraction(listener_reject_fraction); + } + per_address_details->listener_tag_ = config.listenerTag(); + per_address_details_list_.emplace_back(per_address_details); + } + }; + using ActiveListenerDetailsOptRef = absl::optional>; ActiveListenerDetailsOptRef findActiveListenerByTag(uint64_t listener_tag); @@ -93,10 +132,10 @@ class ConnectionHandlerImpl : public Network::TcpConnectionHandler, const absl::optional worker_index_; Event::Dispatcher& dispatcher_; const std::string per_handler_stat_prefix_; - absl::flat_hash_map> listener_map_by_tag_; - absl::flat_hash_map> + absl::flat_hash_map> listener_map_by_tag_; + absl::flat_hash_map> tcp_listener_map_by_address_; - absl::flat_hash_map> + absl::flat_hash_map> internal_listener_map_by_address_; std::atomic num_handler_connections_{}; diff --git a/source/server/listener_impl.cc b/source/server/listener_impl.cc index 5a13527bfdc19..9e45c0f17ab78 100644 --- a/source/server/listener_impl.cc +++ b/source/server/listener_impl.cc @@ -872,8 +872,8 @@ ListenerImpl::~ListenerImpl() { Init::Manager& ListenerImpl::initManager() { return *dynamic_init_manager_; } void ListenerImpl::setSocketFactory(Network::ListenSocketFactoryPtr&& socket_factory) { - ASSERT(!socket_factory_); - socket_factory_ = std::move(socket_factory); + ASSERT(socket_factories_.empty()); + socket_factories_.emplace_back(std::move(socket_factory)); } bool ListenerImpl::supportUpdateFilterChain(const envoy::config::listener::v3::Listener& config, diff --git a/source/server/listener_impl.h b/source/server/listener_impl.h index 07a525d23fea7..6a1f3baf3a263 100644 --- a/source/server/listener_impl.h +++ b/source/server/listener_impl.h @@ -285,7 +285,7 @@ class ListenerImpl final : public Network::ListenerConfig, Network::Address::InstanceConstSharedPtr address() const { return address_; } const envoy::config::listener::v3::Listener& config() const { return config_; } - const Network::ListenSocketFactory& getSocketFactory() const { return *socket_factory_; } + const Network::ListenSocketFactory& getSocketFactory() const { return *socket_factories_[0]; } void debugLog(const std::string& message); void initialize(); DrainManager& localDrainManager() const { @@ -305,7 +305,10 @@ class ListenerImpl final : public Network::ListenerConfig, // Network::ListenerConfig Network::FilterChainManager& filterChainManager() override { return filter_chain_manager_; } Network::FilterChainFactory& filterChainFactory() override { return *this; } - Network::ListenSocketFactory& listenSocketFactory() override { return *socket_factory_; } + Network::ListenSocketFactory& listenSocketFactory() override { return *socket_factories_[0]; } + std::vector& listenSocketFactories() override { + return socket_factories_; + } bool bindToPort() override { return bind_to_port_; } bool mptcpEnabled() { return mptcp_enabled_; } bool handOffRestoredDestinationConnections() const override { @@ -419,7 +422,7 @@ class ListenerImpl final : public Network::ListenerConfig, ListenerManagerImpl& parent_; Network::Address::InstanceConstSharedPtr address_; - Network::ListenSocketFactoryPtr socket_factory_; + std::vector socket_factories_; const bool bind_to_port_; const bool mptcp_enabled_; const bool hand_off_restored_destination_connections_; diff --git a/test/common/quic/active_quic_listener_test.cc b/test/common/quic/active_quic_listener_test.cc index 85a9955560580..e54bf114f5697 100644 --- a/test/common/quic/active_quic_listener_test.cc +++ b/test/common/quic/active_quic_listener_test.cc @@ -120,7 +120,9 @@ class ActiveQuicListenerTest : public testing::TestWithParam(listener_factory_->createActiveUdpListener( - scoped_runtime_.loader(), 0, connection_handler_, *dispatcher_, listener_config_)); + scoped_runtime_.loader(), 0, connection_handler_, + listener_config_.listenSocketFactory().getListenSocket(0), *dispatcher_, + listener_config_)); quic_dispatcher_ = ActiveQuicListenerPeer::quicDispatcher(*quic_listener_); quic::QuicCryptoServerConfig& crypto_config = ActiveQuicListenerPeer::cryptoConfig(*quic_listener_); diff --git a/test/extensions/bootstrap/internal_listener/active_internal_listener_test.cc b/test/extensions/bootstrap/internal_listener/active_internal_listener_test.cc index 223f6acc6d797..5cb818a9ecf14 100644 --- a/test/extensions/bootstrap/internal_listener/active_internal_listener_test.cc +++ b/test/extensions/bootstrap/internal_listener/active_internal_listener_test.cc @@ -267,6 +267,7 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable()); ON_CALL(*socket_, socketType()).WillByDefault(Return(socket_type)); } @@ -292,7 +293,10 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable& listenSocketFactories() override { + return socket_factories_; + } bool bindToPort() override { return bind_to_port_; } bool handOffRestoredDestinationConnections() const override { return hand_off_restored_destination_connections_; @@ -334,7 +338,7 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable> socket_; - Network::MockListenSocketFactory socket_factory_; + std::vector socket_factories_; uint64_t tag_; bool bind_to_port_; const uint32_t tcp_backlog_size_; @@ -393,7 +397,9 @@ TEST_F(ConnectionHandlerTest, DisableInternalListener) { TestListener* internal_listener = addInternalListener(1, "test_internal_listener", std::chrono::milliseconds(), false, nullptr); - EXPECT_CALL(internal_listener->socket_factory_, localAddress()) + EXPECT_CALL(*static_cast( + internal_listener->socket_factories_[0].get()), + localAddress()) .WillRepeatedly(ReturnRef(local_address)); handler_->addListener(absl::nullopt, *internal_listener, runtime_); auto internal_listener_cb = handler_->findByAddress(local_address); @@ -419,7 +425,9 @@ TEST_F(ConnectionHandlerTest, InternalListenerInplaceUpdate) { TestListener* internal_listener = addInternalListener( old_listener_tag, "test_internal_listener", std::chrono::milliseconds(), false, nullptr); - EXPECT_CALL(internal_listener->socket_factory_, localAddress()) + EXPECT_CALL(*static_cast( + internal_listener->socket_factories_[0].get()), + localAddress()) .WillRepeatedly(ReturnRef(local_address)); handler_->addListener(absl::nullopt, *internal_listener, runtime_); @@ -449,6 +457,48 @@ TEST_F(ConnectionHandlerTest, InternalListenerInplaceUpdate) { dispatcher_.clearDeferredDeleteList(); } +TEST_F(ConnectionHandlerTest, InternalListenerInplaceUpdateWithoutUdpInplaceUpdateSupport) { + runtime_.mergeValues( + {{"envoy.reloadable_features.udp_listener_updates_filter_chain_in_place", "false"}}); + InSequence s; + uint64_t old_listener_tag = 1; + uint64_t new_listener_tag = 2; + Network::Address::InstanceConstSharedPtr local_address{ + new Network::Address::EnvoyInternalInstance("server_internal_address")}; + + TestListener* internal_listener = addInternalListener( + old_listener_tag, "test_internal_listener", std::chrono::milliseconds(), false, nullptr); + EXPECT_CALL(*static_cast( + internal_listener->socket_factories_[0].get()), + localAddress()) + .WillRepeatedly(ReturnRef(local_address)); + handler_->addListener(absl::nullopt, *internal_listener, runtime_); + + ASSERT_NE(internal_listener, nullptr); + + auto overridden_filter_chain_manager = + std::make_shared>(); + TestListener* new_test_listener = + addInternalListener(new_listener_tag, "test_internal_listener", std::chrono::milliseconds(), + false, overridden_filter_chain_manager); + handler_->addListener(old_listener_tag, *new_test_listener, runtime_); + + Network::MockConnectionSocket* connection = new NiceMock(); + + auto internal_listener_cb = handler_->findByAddress(local_address); + + EXPECT_CALL(manager_, findFilterChain(_)).Times(0); + EXPECT_CALL(*overridden_filter_chain_manager, findFilterChain(_)).WillOnce(Return(nullptr)); + EXPECT_CALL(*access_log_, log(_, _, _, _)); + internal_listener_cb.value().get().onAccept(Network::ConnectionSocketPtr{connection}); + EXPECT_EQ(0UL, handler_->numConnections()); + + testing::MockFunction completion; + handler_->removeFilterChains(old_listener_tag, {}, completion.AsStdFunction()); + EXPECT_CALL(completion, Call()); + dispatcher_.clearDeferredDeleteList(); +} + } // namespace } // namespace InternalListener } // namespace Bootstrap diff --git a/test/extensions/common/proxy_protocol/proxy_protocol_regression_test.cc b/test/extensions/common/proxy_protocol/proxy_protocol_regression_test.cc index fe07517d8c84d..090f76a0fa3f1 100644 --- a/test/extensions/common/proxy_protocol/proxy_protocol_regression_test.cc +++ b/test/extensions/common/proxy_protocol/proxy_protocol_regression_test.cc @@ -46,10 +46,16 @@ class ProxyProtocolRegressionTest : public testing::TestWithParam()); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + socketType()) + .WillOnce(Return(Network::Socket::Type::Stream)); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + localAddress()) .WillRepeatedly(ReturnRef(socket_->connectionInfoProvider().localAddress())); - EXPECT_CALL(socket_factory_, getListenSocket(_)).WillOnce(Return(socket_)); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + getListenSocket(_)) + .WillOnce(Return(socket_)); connection_handler_->addListener(absl::nullopt, *this, runtime_); conn_ = dispatcher_->createClientConnection(socket_->connectionInfoProvider().localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -60,7 +66,10 @@ class ProxyProtocolRegressionTest : public testing::TestWithParam& listenSocketFactories() override { + return socket_factories_; + } bool bindToPort() override { return true; } bool handOffRestoredDestinationConnections() const override { return false; } uint32_t perConnectionBufferLimitBytes() const override { return 0; } @@ -166,7 +175,7 @@ class ProxyProtocolRegressionTest : public testing::TestWithParam socket_; - Network::MockListenSocketFactory socket_factory_; + std::vector socket_factories_; Network::NopConnectionBalancerImpl connection_balancer_; Network::ConnectionHandlerPtr connection_handler_; Network::MockFilterChainFactory factory_; diff --git a/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.cc b/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.cc index 6d1e559402fbf..73e2e8aa91fe9 100644 --- a/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.cc +++ b/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.cc @@ -35,10 +35,16 @@ ListenerFilterWithDataFuzzer::ListenerFilterWithDataFuzzer() connection_handler_(new Server::ConnectionHandlerImpl(*dispatcher_, absl::nullopt)), name_("proxy"), filter_chain_(Network::Test::createEmptyFilterChainWithRawBufferSockets()), init_manager_(nullptr) { - EXPECT_CALL(socket_factory_, socketType()).WillOnce(Return(Network::Socket::Type::Stream)); - EXPECT_CALL(socket_factory_, localAddress()) + socket_factories_.emplace_back(std::make_unique()); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + socketType()) + .WillOnce(Return(Network::Socket::Type::Stream)); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + localAddress()) .WillRepeatedly(ReturnRef(socket_->connectionInfoProvider().localAddress())); - EXPECT_CALL(socket_factory_, getListenSocket(_)).WillOnce(Return(socket_)); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + getListenSocket(_)) + .WillOnce(Return(socket_)); connection_handler_->addListener(absl::nullopt, *this, runtime_); conn_ = dispatcher_->createClientConnection(socket_->connectionInfoProvider().localAddress(), Network::Address::InstanceConstSharedPtr(), diff --git a/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.h b/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.h index 2e25eb815cb50..49ff988d2af67 100644 --- a/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.h +++ b/test/extensions/filters/listener/common/fuzz/listener_filter_fuzzer.h @@ -48,7 +48,10 @@ class ListenerFilterWithDataFuzzer : public Network::ListenerConfig, // Network::ListenerConfig Network::FilterChainManager& filterChainManager() override { return *this; } Network::FilterChainFactory& filterChainFactory() override { return factory_; } - Network::ListenSocketFactory& listenSocketFactory() override { return socket_factory_; } + Network::ListenSocketFactory& listenSocketFactory() override { return *socket_factories_[0]; } + std::vector& listenSocketFactories() override { + return socket_factories_; + } bool bindToPort() override { return true; } bool handOffRestoredDestinationConnections() const override { return false; } uint32_t perConnectionBufferLimitBytes() const override { return 0; } @@ -98,7 +101,7 @@ class ListenerFilterWithDataFuzzer : public Network::ListenerConfig, BasicResourceLimitImpl open_connections_; Event::DispatcherPtr dispatcher_; std::shared_ptr socket_; - Network::MockListenSocketFactory socket_factory_; + std::vector socket_factories_; Network::NopConnectionBalancerImpl connection_balancer_; Network::ConnectionHandlerPtr connection_handler_; Network::MockFilterChainFactory factory_; diff --git a/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc b/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc index afeba9505b0ac..033e44c865878 100644 --- a/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc +++ b/test/extensions/filters/listener/proxy_protocol/proxy_protocol_test.cc @@ -63,10 +63,16 @@ class ProxyProtocolTest : public testing::TestWithParam()); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + socketType()) + .WillOnce(Return(Network::Socket::Type::Stream)); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + localAddress()) .WillRepeatedly(ReturnRef(socket_->connectionInfoProvider().localAddress())); - EXPECT_CALL(socket_factory_, getListenSocket(_)).WillOnce(Return(socket_)); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + getListenSocket(_)) + .WillOnce(Return(socket_)); connection_handler_->addListener(absl::nullopt, *this, runtime_); conn_ = dispatcher_->createClientConnection(socket_->connectionInfoProvider().localAddress(), Network::Address::InstanceConstSharedPtr(), @@ -77,7 +83,10 @@ class ProxyProtocolTest : public testing::TestWithParam& listenSocketFactories() override { + return socket_factories_; + } bool bindToPort() override { return true; } bool handOffRestoredDestinationConnections() const override { return false; } uint32_t perConnectionBufferLimitBytes() const override { return 0; } @@ -198,7 +207,7 @@ class ProxyProtocolTest : public testing::TestWithParam socket_; - Network::MockListenSocketFactory socket_factory_; + std::vector socket_factories_; Network::NopConnectionBalancerImpl connection_balancer_; Network::ConnectionHandlerPtr connection_handler_; Network::MockFilterChainFactory factory_; @@ -1745,10 +1754,16 @@ class WildcardProxyProtocolTest : public testing::TestWithParam()); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + socketType()) + .WillOnce(Return(Network::Socket::Type::Stream)); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + localAddress()) .WillRepeatedly(ReturnRef(socket_->connectionInfoProvider().localAddress())); - EXPECT_CALL(socket_factory_, getListenSocket(_)).WillOnce(Return(socket_)); + EXPECT_CALL(*static_cast(socket_factories_[0].get()), + getListenSocket(_)) + .WillOnce(Return(socket_)); connection_handler_->addListener(absl::nullopt, *this, runtime_); conn_ = dispatcher_->createClientConnection(local_dst_address_, Network::Address::InstanceConstSharedPtr(), @@ -1769,7 +1784,10 @@ class WildcardProxyProtocolTest : public testing::TestWithParam& listenSocketFactories() override { + return socket_factories_; + } bool bindToPort() override { return true; } bool handOffRestoredDestinationConnections() const override { return false; } uint32_t perConnectionBufferLimitBytes() const override { return 0; } @@ -1849,7 +1867,7 @@ class WildcardProxyProtocolTest : public testing::TestWithParam socket_factories_; std::shared_ptr socket_; Network::Address::InstanceConstSharedPtr local_dst_address_; Network::NopConnectionBalancerImpl connection_balancer_; diff --git a/test/integration/fake_upstream.cc b/test/integration/fake_upstream.cc index 5312bdd4c7141..550c3d36ef21d 100644 --- a/test/integration/fake_upstream.cc +++ b/test/integration/fake_upstream.cc @@ -561,7 +561,6 @@ FakeUpstream::FakeUpstream(Network::TransportSocketFactoryPtr&& transport_socket : http_type_(config.upstream_protocol_), http2_options_(config.http2_options_), http3_options_(config.http3_options_), quic_options_(config.quic_options_), socket_(Network::SocketSharedPtr(listen_socket.release())), - socket_factory_(std::make_unique(socket_)), api_(Api::createApiForTest(stats_store_)), time_system_(config.time_system_), dispatcher_(api_->allocateDispatcher("fake_upstream")), handler_(new Server::ConnectionHandlerImpl(*dispatcher_, 0)), config_(config), @@ -569,6 +568,7 @@ FakeUpstream::FakeUpstream(Network::TransportSocketFactoryPtr&& transport_socket listener_(*this, http_type_ == Http::CodecType::HTTP3), filter_chain_(Network::Test::createEmptyFilterChain(std::move(transport_socket_factory))), stats_scope_(stats_store_.createScope("test_server_scope")) { + socket_factories_.emplace_back(std::make_unique(socket_)); ENVOY_LOG(info, "starting fake server at {}. UDP={} codec={}", localAddress()->asString(), config.udp_fake_upstream_.has_value(), FakeHttpConnection::typeToString(http_type_)); if (config.udp_fake_upstream_.has_value() && @@ -624,7 +624,7 @@ void FakeUpstream::createUdpListenerFilterChain(Network::UdpListenerFilterManage } void FakeUpstream::threadRoutine() { - socket_factory_->doFinalPreWorkerInit(); + socket_factories_[0]->doFinalPreWorkerInit(); handler_->addListener(absl::nullopt, listener_, runtime_); server_initialized_.setReady(); dispatcher_->run(Event::Dispatcher::RunType::Block); diff --git a/test/integration/fake_upstream.h b/test/integration/fake_upstream.h index 1f49cfacea48d..c5469f7338a41 100644 --- a/test/integration/fake_upstream.h +++ b/test/integration/fake_upstream.h @@ -795,7 +795,10 @@ class FakeUpstream : Logger::Loggable, Network::FilterChainManager& filterChainManager() override { return parent_; } Network::FilterChainFactory& filterChainFactory() override { return parent_; } Network::ListenSocketFactory& listenSocketFactory() override { - return *parent_.socket_factory_; + return *parent_.socket_factories_[0]; + } + std::vector& listenSocketFactories() override { + return parent_.socket_factories_; } bool bindToPort() override { return true; } bool handOffRestoredDestinationConnections() const override { return false; } @@ -845,7 +848,7 @@ class FakeUpstream : Logger::Loggable, const envoy::config::core::v3::Http3ProtocolOptions http3_options_; envoy::config::listener::v3::QuicProtocolOptions quic_options_; Network::SocketSharedPtr socket_; - Network::ListenSocketFactoryPtr socket_factory_; + std::vector socket_factories_; ConditionalInitializer server_initialized_; // Guards any objects which can be altered both in the upstream thread and the // main test thread. diff --git a/test/mocks/network/mocks.h b/test/mocks/network/mocks.h index 27c5799b00f9a..c6741474bd5ab 100644 --- a/test/mocks/network/mocks.h +++ b/test/mocks/network/mocks.h @@ -427,6 +427,7 @@ class MockListenerConfig : public ListenerConfig { MOCK_METHOD(FilterChainManager&, filterChainManager, ()); MOCK_METHOD(FilterChainFactory&, filterChainFactory, ()); MOCK_METHOD(ListenSocketFactory&, listenSocketFactory, ()); + MOCK_METHOD(std::vector&, listenSocketFactories, ()); MOCK_METHOD(bool, bindToPort, ()); MOCK_METHOD(bool, handOffRestoredDestinationConnections, (), (const)); MOCK_METHOD(uint32_t, perConnectionBufferLimitBytes, (), (const)); diff --git a/test/per_file_coverage.sh b/test/per_file_coverage.sh index 0aa174b64e66c..c6d5af030b5ac 100755 --- a/test/per_file_coverage.sh +++ b/test/per_file_coverage.sh @@ -88,7 +88,7 @@ declare -a KNOWN_LOW_COVERAGE=( "source/extensions/watchdog:83.3" # Death tests within extensions "source/extensions/watchdog/profile_action:83.3" "source/server:93.3" # flaky: be careful adjusting. See https://github.com/envoyproxy/envoy/issues/15239 -"source/server/admin:97.6" +"source/server/admin:97.4" # TODO(soulxu) try to raise this back to `97.6` when multiple addresses listener implemented and the old interface of Network::ListenerConfig is removed. "source/server/config_validation:74.8" ) diff --git a/test/server/active_udp_listener_test.cc b/test/server/active_udp_listener_test.cc index 7337c0d2e5550..62eea4f252170 100644 --- a/test/server/active_udp_listener_test.cc +++ b/test/server/active_udp_listener_test.cc @@ -77,8 +77,8 @@ class ActiveUdpListenerTest : public testing::TestWithParam(0, 1, conn_handler_, dispatcher_, listener_config_); + active_listener_ = std::make_unique(0, 1, conn_handler_, listen_socket_, + dispatcher_, listener_config_); } std::string listener_stat_prefix_{"listener_stat_prefix"}; diff --git a/test/server/connection_handler_test.cc b/test/server/connection_handler_test.cc index fb13878403f94..225508b64b308 100644 --- a/test/server/connection_handler_test.cc +++ b/test/server/connection_handler_test.cc @@ -74,7 +74,7 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable> filter_chain_manager = nullptr, uint32_t tcp_backlog_size = ENVOY_TCP_BACKLOG_SIZE, Network::ConnectionBalancerSharedPtr connection_balancer = nullptr, - bool ignore_global_conn_limit = false) + bool ignore_global_conn_limit = false, int num_of_socket_factories = 1) : parent_(parent), socket_(std::make_shared>()), tag_(tag), bind_to_port_(bind_to_port), tcp_backlog_size_(tcp_backlog_size), hand_off_restored_destination_connections_(hand_off_restored_destination_connections), @@ -85,6 +85,9 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable()); + } envoy::config::listener::v3::UdpListenerConfig udp_config; udp_listener_config_ = std::make_unique(udp_config); udp_listener_config_->listener_factory_ = @@ -111,13 +114,21 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable(socket_factories_[index].get()); + } + // Network::ListenerConfig Network::FilterChainManager& filterChainManager() override { return inline_filter_chain_manager_ == nullptr ? parent_.manager_ : *inline_filter_chain_manager_; } Network::FilterChainFactory& filterChainFactory() override { return parent_.factory_; } - Network::ListenSocketFactory& listenSocketFactory() override { return socket_factory_; } + Network::ListenSocketFactory& listenSocketFactory() override { return *socket_factories_[0]; } + std::vector& listenSocketFactories() override { + return socket_factories_; + } bool bindToPort() override { return bind_to_port_; } bool handOffRestoredDestinationConnections() const override { return hand_off_restored_destination_connections_; @@ -153,7 +164,7 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable> socket_; - Network::MockListenSocketFactory socket_factory_; + std::vector socket_factories_; uint64_t tag_; bool bind_to_port_; const uint32_t tcp_backlog_size_; @@ -233,8 +244,8 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggablesocket_factory_, socketType()).WillOnce(Return(socket_type)); - EXPECT_CALL(listeners_.back()->socket_factory_, getListenSocket(_)) + EXPECT_CALL(listeners_.back()->socketFactory(), socketType()).WillOnce(Return(socket_type)); + EXPECT_CALL(listeners_.back()->socketFactory(), getListenSocket(_)) .WillOnce(Return(listeners_.back()->socket_)); if (socket_type == Network::Socket::Type::Stream) { EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, _)) @@ -267,6 +278,43 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggable& mock_listeners, + std::vector& addresses, + Network::TcpListenerCallbacks** listener_callbacks = nullptr, bool disable_listener = false) { + listeners_.emplace_back(std::make_unique( + *this, tag, bind_to_port, hand_off_restored_destination_connections, name, + Network::Socket::Type::Stream, std::chrono::milliseconds(15000), false, access_log_, + nullptr, ENVOY_TCP_BACKLOG_SIZE, nullptr, false, mock_listeners.size())); + + EXPECT_CALL(listeners_.back()->socketFactory(0), socketType()) + .WillOnce(Return(Network::Socket::Type::Stream)); + for (std::vector::size_type i = 0; i < mock_listeners.size(); i++) { + EXPECT_CALL(listeners_.back()->socketFactory(i), getListenSocket(_)) + .WillOnce(Return(listeners_.back()->socket_)); + + EXPECT_CALL(dispatcher_, createListener_(_, _, _, _, _)) + .WillOnce(Invoke([i, &mock_listeners, listener_callbacks]( + Network::SocketSharedPtr&&, Network::TcpListenerCallbacks& cb, + Runtime::Loader&, bool, bool) -> Network::Listener* { + if (listener_callbacks != nullptr) { + *listener_callbacks = &cb; + } + return mock_listeners[i]; + })) + .RetiresOnSaturation(); + + EXPECT_CALL(listeners_.back()->socketFactory(i), localAddress()) + .WillRepeatedly(ReturnRef(addresses[i])); + if (disable_listener) { + EXPECT_CALL(*static_cast(mock_listeners[i]), disable()); + } + } + + return listeners_.back().get(); + } + void validateOriginalDst(Network::TcpListenerCallbacks** listener_callbacks, TestListener* test_listener, Network::MockListener* listener) { Network::Address::InstanceConstSharedPtr normal_address( @@ -276,7 +324,7 @@ class ConnectionHandlerTest : public testing::Test, protected Logger::Loggableip()->port()); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(any_address)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -341,7 +389,7 @@ TEST_F(ConnectionHandlerTest, RemoveListenerDuringRebalance) { TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks, connection_balancer, ¤t_handler); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -382,7 +430,7 @@ TEST_F(ConnectionHandlerTest, ListenerConnectionLimitEnforced) { addListener(1, false, false, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); // Only allow a single connection on this listener. test_listener1->setMaxConnections(1); @@ -394,7 +442,7 @@ TEST_F(ConnectionHandlerTest, ListenerConnectionLimitEnforced) { addListener(2, false, false, "test_listener2", listener2, &listener_callbacks2); Network::Address::InstanceConstSharedPtr alt_address( new Network::Address::Ipv4Instance("127.0.0.2", 20002)); - EXPECT_CALL(test_listener2->socket_factory_, localAddress()) + EXPECT_CALL(test_listener2->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(alt_address)); // Do not allow any connections on this listener. test_listener2->setMaxConnections(0); @@ -467,7 +515,7 @@ TEST_F(ConnectionHandlerTest, RemoveListener) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -491,6 +539,47 @@ TEST_F(ConnectionHandlerTest, RemoveListener) { handler_->removeListeners(0); } +TEST_F(ConnectionHandlerTest, RemoveListenerWithMultiAddrs) { + InSequence s; + + Network::TcpListenerCallbacks* listener_callbacks; + auto listener1 = new NiceMock(); + auto listener2 = new NiceMock(); + std::vector mock_listeners; + mock_listeners.emplace_back(listener1); + mock_listeners.emplace_back(listener2); + Network::Address::InstanceConstSharedPtr address1( + new Network::Address::Ipv4Instance("127.0.0.1", 80, nullptr)); + Network::Address::InstanceConstSharedPtr address2( + new Network::Address::Ipv4Instance("127.0.0.2", 80, nullptr)); + std::vector addresses; + addresses.emplace_back(address1); + addresses.emplace_back(address2); + TestListener* test_listener = addMultiAddrsListener( + 1, true, false, "test_listener", mock_listeners, addresses, &listener_callbacks); + handler_->addListener(absl::nullopt, *test_listener, runtime_); + + Network::MockConnectionSocket* connection = new NiceMock(); + EXPECT_CALL(*access_log_, log(_, _, _, _)); + listener_callbacks->onAccept(Network::ConnectionSocketPtr{connection}); + EXPECT_EQ(0UL, handler_->numConnections()); + + // Test stop/remove of not existent listener. + handler_->stopListeners(0); + handler_->removeListeners(0); + + EXPECT_CALL(*listener1, onDestroy()); + EXPECT_CALL(*listener2, onDestroy()); + handler_->stopListeners(1); + EXPECT_CALL(dispatcher_, clearDeferredDeleteList()).Times(2); + handler_->removeListeners(1); + EXPECT_EQ(0UL, handler_->numConnections()); + + // Test stop/remove of not existent listener. + handler_->stopListeners(0); + handler_->removeListeners(0); +} + TEST_F(ConnectionHandlerTest, DisableListener) { InSequence s; @@ -498,7 +587,7 @@ TEST_F(ConnectionHandlerTest, DisableListener) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, false, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -508,6 +597,32 @@ TEST_F(ConnectionHandlerTest, DisableListener) { handler_->disableListeners(); } +TEST_F(ConnectionHandlerTest, DisableListenerWithMultiAddrs) { + Network::TcpListenerCallbacks* listener_callbacks; + auto listener1 = new NiceMock(); + auto listener2 = new NiceMock(); + std::vector mock_listeners; + mock_listeners.emplace_back(listener1); + mock_listeners.emplace_back(listener2); + Network::Address::InstanceConstSharedPtr address1( + new Network::Address::Ipv4Instance("127.0.0.1", 80, nullptr)); + Network::Address::InstanceConstSharedPtr address2( + new Network::Address::Ipv4Instance("127.0.0.2", 80, nullptr)); + std::vector addresses; + addresses.emplace_back(address1); + addresses.emplace_back(address2); + TestListener* test_listener = addMultiAddrsListener( + 1, false, false, "test_listener", mock_listeners, addresses, &listener_callbacks); + handler_->addListener(absl::nullopt, *test_listener, runtime_); + + EXPECT_CALL(*listener1, disable()); + EXPECT_CALL(*listener2, disable()); + EXPECT_CALL(*listener1, onDestroy()); + EXPECT_CALL(*listener2, onDestroy()); + + handler_->disableListeners(); +} + // Envoy doesn't have such case yet, just ensure the code won't break with it. TEST_F(ConnectionHandlerTest, StopAndDisableStoppedListener) { InSequence s; @@ -516,7 +631,7 @@ TEST_F(ConnectionHandlerTest, StopAndDisableStoppedListener) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, false, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -537,15 +652,38 @@ TEST_F(ConnectionHandlerTest, AddDisabledListener) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, false, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(*listener, disable()); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); + EXPECT_CALL(*listener, disable()); EXPECT_CALL(*listener, onDestroy()); handler_->disableListeners(); handler_->addListener(absl::nullopt, *test_listener, runtime_); } +TEST_F(ConnectionHandlerTest, AddDisabledListenerWithMultiAddrs) { + Network::TcpListenerCallbacks* listener_callbacks; + auto listener1 = new NiceMock(); + auto listener2 = new NiceMock(); + std::vector mock_listeners; + mock_listeners.emplace_back(listener1); + mock_listeners.emplace_back(listener2); + Network::Address::InstanceConstSharedPtr address1( + new Network::Address::Ipv4Instance("127.0.0.1", 80, nullptr)); + Network::Address::InstanceConstSharedPtr address2( + new Network::Address::Ipv4Instance("127.0.0.2", 80, nullptr)); + std::vector addresses; + addresses.emplace_back(address1); + addresses.emplace_back(address2); + TestListener* test_listener = addMultiAddrsListener( + 1, false, false, "test_listener", mock_listeners, addresses, &listener_callbacks, true); + EXPECT_CALL(*listener1, onDestroy()); + EXPECT_CALL(*listener2, onDestroy()); + + handler_->disableListeners(); + handler_->addListener(absl::nullopt, *test_listener, runtime_); +} + TEST_F(ConnectionHandlerTest, SetListenerRejectFraction) { InSequence s; @@ -553,7 +691,7 @@ TEST_F(ConnectionHandlerTest, SetListenerRejectFraction) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, false, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -570,9 +708,9 @@ TEST_F(ConnectionHandlerTest, AddListenerSetRejectFraction) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, false, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(*listener, setRejectFraction(UnitFloat(0.12345f))); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); + EXPECT_CALL(*listener, setRejectFraction(UnitFloat(0.12345f))); EXPECT_CALL(*listener, onDestroy()); handler_->setListenerRejectFraction(UnitFloat(0.12345f)); @@ -587,7 +725,7 @@ TEST_F(ConnectionHandlerTest, SetsTransportSocketConnectTimeout) { TestListener* test_listener = addListener(1, false, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -613,7 +751,7 @@ TEST_F(ConnectionHandlerTest, DestroyCloseConnections) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -634,7 +772,7 @@ TEST_F(ConnectionHandlerTest, CloseDuringFilterChainCreate) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -659,7 +797,7 @@ TEST_F(ConnectionHandlerTest, CloseConnectionOnEmptyFilterChain) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -684,7 +822,7 @@ TEST_F(ConnectionHandlerTest, NormalRedirect) { addListener(1, true, true, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -694,7 +832,7 @@ TEST_F(ConnectionHandlerTest, NormalRedirect) { addListener(2, false, false, "test_listener2", listener2, &listener_callbacks2); Network::Address::InstanceConstSharedPtr alt_address( new Network::Address::Ipv4Instance("127.0.0.2", 20002)); - EXPECT_CALL(test_listener2->socket_factory_, localAddress()) + EXPECT_CALL(test_listener2->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(alt_address)); handler_->addListener(absl::nullopt, *test_listener2, runtime_); @@ -744,6 +882,70 @@ TEST_F(ConnectionHandlerTest, NormalRedirect) { EXPECT_CALL(*listener1, onDestroy()); } +TEST_F(ConnectionHandlerTest, NormalRedirectWithMultiAddrs) { + Network::TcpListenerCallbacks* listener_callbacks1; + auto listener1 = new NiceMock(); + auto listener2 = new NiceMock(); + std::vector mock_listeners; + mock_listeners.emplace_back(listener1); + mock_listeners.emplace_back(listener2); + Network::Address::InstanceConstSharedPtr normal_address( + new Network::Address::Ipv4Instance("127.0.0.1", 10001, nullptr)); + Network::Address::InstanceConstSharedPtr alt_address( + new Network::Address::Ipv4Instance("127.0.0.2", 20002, nullptr)); + std::vector addresses; + addresses.emplace_back(normal_address); + addresses.emplace_back(alt_address); + TestListener* test_listener1 = addMultiAddrsListener( + 1, true, true, "test_listener1", mock_listeners, addresses, &listener_callbacks1); + handler_->addListener(absl::nullopt, *test_listener1, runtime_); + + auto* test_filter = new NiceMock(); + EXPECT_CALL(*test_filter, destroy_()); + Network::MockConnectionSocket* accepted_socket = new NiceMock(); + bool redirected = false; + EXPECT_CALL(factory_, createListenerFilterChain(_)) + .WillRepeatedly(Invoke([&](Network::ListenerFilterManager& manager) -> bool { + // Insert the Mock filter. + if (!redirected) { + manager.addAcceptFilter(nullptr, Network::ListenerFilterPtr{test_filter}); + redirected = true; + } + return true; + })); + EXPECT_CALL(*test_filter, onAccept(_)) + .WillOnce(Invoke([&](Network::ListenerFilterCallbacks& cb) -> Network::FilterStatus { + cb.socket().connectionInfoProvider().restoreLocalAddress(alt_address); + return Network::FilterStatus::Continue; + })); + EXPECT_CALL(manager_, findFilterChain(_)).WillOnce(Return(filter_chain_.get())); + auto* connection = new NiceMock(); + EXPECT_CALL(dispatcher_, createServerConnection_()).WillOnce(Return(connection)); + EXPECT_CALL(factory_, createNetworkFilterChain(_, _)).WillOnce(Return(true)); + listener_callbacks1->onAccept(Network::ConnectionSocketPtr{accepted_socket}); + + // Verify per-listener connection stats. + EXPECT_EQ(1UL, handler_->numConnections()); + EXPECT_EQ(1UL, TestUtility::findCounter(stats_store_, "downstream_cx_total")->value()); + EXPECT_EQ(1UL, TestUtility::findGauge(stats_store_, "downstream_cx_active")->value()); + EXPECT_EQ(1UL, TestUtility::findCounter(stats_store_, "test.downstream_cx_total")->value()); + EXPECT_EQ(1UL, TestUtility::findGauge(stats_store_, "test.downstream_cx_active")->value()); + + EXPECT_CALL(*access_log_, log(_, _, _, _)) + .WillOnce( + Invoke([&](const Http::RequestHeaderMap*, const Http::ResponseHeaderMap*, + const Http::ResponseTrailerMap*, const StreamInfo::StreamInfo& stream_info) { + EXPECT_EQ(alt_address, stream_info.downstreamAddressProvider().localAddress()); + })); + connection->close(Network::ConnectionCloseType::NoFlush); + dispatcher_.clearDeferredDeleteList(); + EXPECT_EQ(0UL, TestUtility::findGauge(stats_store_, "downstream_cx_active")->value()); + EXPECT_EQ(0UL, TestUtility::findGauge(stats_store_, "test.downstream_cx_active")->value()); + + EXPECT_CALL(*listener2, onDestroy()); + EXPECT_CALL(*listener1, onDestroy()); +} + // When update a listener, the old listener will be stopped and the new listener will // be added into ConnectionHandler before remove the old listener from ConnectionHandler. // This test ensure ConnectionHandler can query the correct Listener when redirect the connection @@ -754,7 +956,7 @@ TEST_F(ConnectionHandlerTest, MatchLatestListener) { auto listener1 = new NiceMock(); TestListener* test_listener1 = addListener(1, true, true, "test_listener1", listener1, &listener_callbacks); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -768,7 +970,7 @@ TEST_F(ConnectionHandlerTest, MatchLatestListener) { listener2_overridden_filter_chain_manager); Network::Address::InstanceConstSharedPtr listener2_address( new Network::Address::Ipv4Instance("127.0.0.1", 10002)); - EXPECT_CALL(test_listener2->socket_factory_, localAddress()) + EXPECT_CALL(test_listener2->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(listener2_address)); handler_->addListener(absl::nullopt, *test_listener2, runtime_); @@ -782,7 +984,7 @@ TEST_F(ConnectionHandlerTest, MatchLatestListener) { listener3_overridden_filter_chain_manager); Network::Address::InstanceConstSharedPtr listener3_address( new Network::Address::Ipv4Instance("127.0.0.1", 10002)); - EXPECT_CALL(test_listener3->socket_factory_, localAddress()) + EXPECT_CALL(test_listener3->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(listener3_address)); // This emulated the case of update listener in-place. Stop the old listener and @@ -837,7 +1039,7 @@ TEST_F(ConnectionHandlerTest, EnsureNotMatchStoppedListener) { auto listener1 = new NiceMock(); TestListener* test_listener1 = addListener(1, true, true, "test_listener1", listener1, &listener_callbacks); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -850,7 +1052,7 @@ TEST_F(ConnectionHandlerTest, EnsureNotMatchStoppedListener) { listener2_overridden_filter_chain_manager); Network::Address::InstanceConstSharedPtr listener2_address( new Network::Address::Ipv4Instance("127.0.0.1", 10002)); - EXPECT_CALL(test_listener2->socket_factory_, localAddress()) + EXPECT_CALL(test_listener2->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(listener2_address)); handler_->addListener(absl::nullopt, *test_listener2, runtime_); @@ -901,7 +1103,7 @@ TEST_F(ConnectionHandlerTest, EnsureNotMatchStoppedAnyAddressListener) { auto listener1 = new NiceMock(); TestListener* test_listener1 = addListener(1, true, true, "test_listener1", listener1, &listener_callbacks); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -914,7 +1116,7 @@ TEST_F(ConnectionHandlerTest, EnsureNotMatchStoppedAnyAddressListener) { listener2_overridden_filter_chain_manager); Network::Address::InstanceConstSharedPtr listener2_address( new Network::Address::Ipv4Instance("0.0.0.0", 10002)); - EXPECT_CALL(test_listener2->socket_factory_, localAddress()) + EXPECT_CALL(test_listener2->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(listener2_address)); handler_->addListener(absl::nullopt, *test_listener2, runtime_); @@ -966,7 +1168,7 @@ TEST_F(ConnectionHandlerTest, FallbackToWildcardListener) { addListener(1, true, true, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -975,7 +1177,7 @@ TEST_F(ConnectionHandlerTest, FallbackToWildcardListener) { TestListener* test_listener2 = addListener(2, false, false, "test_listener2", listener2, &listener_callbacks2); Network::Address::InstanceConstSharedPtr any_address = Network::Utility::getIpv4AnyAddress(); - EXPECT_CALL(test_listener2->socket_factory_, localAddress()) + EXPECT_CALL(test_listener2->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(any_address)); handler_->addListener(absl::nullopt, *test_listener2, runtime_); @@ -1020,7 +1222,7 @@ TEST_F(ConnectionHandlerTest, MatchIPv6WildcardListener) { addListener(1, true, true, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -1035,7 +1237,7 @@ TEST_F(ConnectionHandlerTest, MatchIPv6WildcardListener) { Network::Address::InstanceConstSharedPtr any_address( new Network::Address::Ipv4Instance("0.0.0.0", 80)); - EXPECT_CALL(ipv4_any_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv4_any_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(any_address)); handler_->addListener(absl::nullopt, *ipv4_any_listener, runtime_); @@ -1049,7 +1251,7 @@ TEST_F(ConnectionHandlerTest, MatchIPv6WildcardListener) { std::chrono::milliseconds(15000), false, ipv6_overridden_filter_chain_manager); Network::Address::InstanceConstSharedPtr any_address_ipv6( new Network::Address::Ipv6Instance("::", 80)); - EXPECT_CALL(ipv6_any_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv6_any_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(any_address_ipv6)); handler_->addListener(absl::nullopt, *ipv6_any_listener, runtime_); @@ -1103,7 +1305,7 @@ TEST_F(ConnectionHandlerTest, MatchIPv6WildcardListenerWithAnyAddressAndIpv4Comp addListener(1, true, true, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -1118,7 +1320,7 @@ TEST_F(ConnectionHandlerTest, MatchIPv6WildcardListenerWithAnyAddressAndIpv4Comp // Set the ipv6only as false. Network::Address::InstanceConstSharedPtr any_address_ipv6( new Network::Address::Ipv6Instance("::", 80, nullptr, false)); - EXPECT_CALL(ipv6_any_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv6_any_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(any_address_ipv6)); handler_->addListener(absl::nullopt, *ipv6_any_listener, runtime_); @@ -1172,7 +1374,7 @@ TEST_F(ConnectionHandlerTest, MatchhIpv4CompatiableIPv6ListenerWithIpv4CompatFla addListener(1, true, true, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -1187,7 +1389,7 @@ TEST_F(ConnectionHandlerTest, MatchhIpv4CompatiableIPv6ListenerWithIpv4CompatFla // Set the ipv6only as false. Network::Address::InstanceConstSharedPtr ipv4_mapped_ipv6_address( new Network::Address::Ipv6Instance("::FFFF:192.168.0.1", 80, nullptr, false)); - EXPECT_CALL(ipv6_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv6_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(ipv4_mapped_ipv6_address)); handler_->addListener(absl::nullopt, *ipv6_listener, runtime_); @@ -1241,7 +1443,7 @@ TEST_F(ConnectionHandlerTest, NotMatchIPv6WildcardListenerWithoutIpv4CompatFlag) addListener(1, true, true, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -1256,7 +1458,7 @@ TEST_F(ConnectionHandlerTest, NotMatchIPv6WildcardListenerWithoutIpv4CompatFlag) // not set the ipv6only flag, the default value is true. Network::Address::InstanceConstSharedPtr any_address_ipv6( new Network::Address::Ipv6Instance("::", 80)); - EXPECT_CALL(ipv6_any_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv6_any_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(any_address_ipv6)); handler_->addListener(absl::nullopt, *ipv6_any_listener, runtime_); @@ -1307,7 +1509,7 @@ TEST_F(ConnectionHandlerTest, MatchhIpv4WhenBothIpv4AndIPv6WithIpv4CompatFlag) { addListener(1, true, true, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -1323,7 +1525,7 @@ TEST_F(ConnectionHandlerTest, MatchhIpv4WhenBothIpv4AndIPv6WithIpv4CompatFlag) { // Set the ipv6only as false. Network::Address::InstanceConstSharedPtr ipv6_any_address( new Network::Address::Ipv6Instance("::", 80, nullptr, false)); - EXPECT_CALL(ipv6_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv6_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(ipv6_any_address)); handler_->addListener(absl::nullopt, *ipv6_listener, runtime_); @@ -1338,7 +1540,7 @@ TEST_F(ConnectionHandlerTest, MatchhIpv4WhenBothIpv4AndIPv6WithIpv4CompatFlag) { false, ipv4_overridden_filter_chain_manager); Network::Address::InstanceConstSharedPtr ipv4_address( new Network::Address::Ipv4Instance("0.0.0.0", 80, nullptr)); - EXPECT_CALL(ipv4_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv4_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(ipv4_address)); handler_->addListener(absl::nullopt, *ipv4_listener, runtime_); @@ -1393,7 +1595,7 @@ TEST_F(ConnectionHandlerTest, MatchhIpv4WhenBothIpv4AndIPv6WithIpv4CompatFlag2) addListener(1, true, true, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -1408,7 +1610,7 @@ TEST_F(ConnectionHandlerTest, MatchhIpv4WhenBothIpv4AndIPv6WithIpv4CompatFlag2) false, ipv4_overridden_filter_chain_manager); Network::Address::InstanceConstSharedPtr ipv4_address( new Network::Address::Ipv4Instance("0.0.0.0", 80, nullptr)); - EXPECT_CALL(ipv4_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv4_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(ipv4_address)); handler_->addListener(absl::nullopt, *ipv4_listener, runtime_); @@ -1424,7 +1626,7 @@ TEST_F(ConnectionHandlerTest, MatchhIpv4WhenBothIpv4AndIPv6WithIpv4CompatFlag2) // Set the ipv6only as false. Network::Address::InstanceConstSharedPtr ipv4_mapped_ipv6_address( new Network::Address::Ipv6Instance("::", 80, nullptr, false)); - EXPECT_CALL(ipv6_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv6_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(ipv4_mapped_ipv6_address)); handler_->addListener(absl::nullopt, *ipv6_listener, runtime_); @@ -1480,7 +1682,7 @@ TEST_F(ConnectionHandlerTest, AddIpv4MappedListenerAfterIpv4ListenerStopped) { addListener(1, true, true, "test_listener1", listener1, &listener_callbacks1); Network::Address::InstanceConstSharedPtr normal_address( new Network::Address::Ipv4Instance("127.0.0.1", 10001)); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(normal_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -1495,7 +1697,7 @@ TEST_F(ConnectionHandlerTest, AddIpv4MappedListenerAfterIpv4ListenerStopped) { false, ipv4_overridden_filter_chain_manager); Network::Address::InstanceConstSharedPtr ipv4_address( new Network::Address::Ipv4Instance("0.0.0.0", 80, nullptr)); - EXPECT_CALL(ipv4_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv4_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(ipv4_address)); handler_->addListener(absl::nullopt, *ipv4_listener, runtime_); @@ -1515,7 +1717,7 @@ TEST_F(ConnectionHandlerTest, AddIpv4MappedListenerAfterIpv4ListenerStopped) { // Set the ipv6only as false. Network::Address::InstanceConstSharedPtr ipv4_mapped_ipv6_address( new Network::Address::Ipv6Instance("::", 80, nullptr, false)); - EXPECT_CALL(ipv6_listener->socket_factory_, localAddress()) + EXPECT_CALL(ipv6_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(ipv4_mapped_ipv6_address)); handler_->addListener(absl::nullopt, *ipv6_listener, runtime_); @@ -1589,7 +1791,7 @@ TEST_F(ConnectionHandlerTest, WildcardListenerWithNoOriginalDst) { new Network::Address::Ipv4Instance("127.0.0.1", 80)); Network::Address::InstanceConstSharedPtr any_address = Network::Utility::getAddressWithPort( *Network::Utility::getIpv4AnyAddress(), normal_address->ip()->port()); - EXPECT_CALL(test_listener1->socket_factory_, localAddress()) + EXPECT_CALL(test_listener1->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(any_address)); handler_->addListener(absl::nullopt, *test_listener1, runtime_); @@ -1619,7 +1821,7 @@ TEST_F(ConnectionHandlerTest, TransportProtocolDefault) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -1639,7 +1841,7 @@ TEST_F(ConnectionHandlerTest, TransportProtocolCustom) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -1674,7 +1876,7 @@ TEST_F(ConnectionHandlerTest, ListenerFilterTimeout) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -1727,7 +1929,7 @@ TEST_F(ConnectionHandlerTest, ContinueOnListenerFilterTimeout) { TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks, nullptr, nullptr, Network::Socket::Type::Stream, std::chrono::milliseconds(15000), true); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -1789,7 +1991,7 @@ TEST_F(ConnectionHandlerTest, ListenerFilterTimeoutResetOnSuccess) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -1843,7 +2045,7 @@ TEST_F(ConnectionHandlerTest, ListenerFilterDisabledTimeout) { TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks, nullptr, nullptr, Network::Socket::Type::Stream, std::chrono::milliseconds()); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -1880,7 +2082,7 @@ TEST_F(ConnectionHandlerTest, ListenerFilterReportError) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -1926,7 +2128,7 @@ TEST_F(ConnectionHandlerTest, UdpListenerNoFilter) { EXPECT_CALL(factory_, createUdpListenerFilterChain(_, _)) .WillOnce(Invoke([&](Network::UdpListenerFilterManager&, Network::UdpReadFilterCallbacks&) -> bool { return true; })); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -1952,7 +2154,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerInplaceUpdate) { TestListener* old_test_listener = addListener(old_listener_tag, true, false, "test_listener", old_listener, &old_listener_callbacks, mock_connection_balancer, ¤t_handler); - EXPECT_CALL(old_test_listener->socket_factory_, localAddress()) + EXPECT_CALL(old_test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *old_test_listener, runtime_); ASSERT_NE(old_test_listener, nullptr); @@ -1983,6 +2185,54 @@ TEST_F(ConnectionHandlerTest, TcpListenerInplaceUpdate) { EXPECT_CALL(*old_listener, onDestroy()); } +TEST_F(ConnectionHandlerTest, TcpListenerInplaceUpdateWithoutUdpInplaceSupport) { + runtime_.mergeValues( + {{"envoy.reloadable_features.udp_listener_updates_filter_chain_in_place", "false"}}); + InSequence s; + uint64_t old_listener_tag = 1; + uint64_t new_listener_tag = 2; + Network::TcpListenerCallbacks* old_listener_callbacks; + Network::BalancedConnectionHandler* current_handler; + + auto old_listener = new NiceMock(); + auto mock_connection_balancer = std::make_shared(); + + TestListener* old_test_listener = + addListener(old_listener_tag, true, false, "test_listener", old_listener, + &old_listener_callbacks, mock_connection_balancer, ¤t_handler); + EXPECT_CALL(old_test_listener->socketFactory(), localAddress()) + .WillRepeatedly(ReturnRef(local_address_)); + handler_->addListener(absl::nullopt, *old_test_listener, runtime_); + ASSERT_NE(old_test_listener, nullptr); + + Network::TcpListenerCallbacks* new_listener_callbacks = nullptr; + + auto overridden_filter_chain_manager = + std::make_shared>(); + TestListener* new_test_listener = addListener( + new_listener_tag, true, false, "test_listener", /* Network::Listener */ nullptr, + &new_listener_callbacks, mock_connection_balancer, nullptr, Network::Socket::Type::Stream, + std::chrono::milliseconds(15000), false, overridden_filter_chain_manager); + EXPECT_CALL(new_test_listener->socketFactory(), socketType()) + .WillOnce(Return(Network::Socket::Type::Stream)); + handler_->addListener(old_listener_tag, *new_test_listener, runtime_); + ASSERT_EQ(new_listener_callbacks, nullptr) + << "new listener should be inplace added and callback should not change"; + + Network::MockConnectionSocket* connection = new NiceMock(); + current_handler->incNumConnections(); + + EXPECT_CALL(*mock_connection_balancer, pickTargetHandler(_)) + .WillOnce(ReturnRef(*current_handler)); + EXPECT_CALL(manager_, findFilterChain(_)).Times(0); + EXPECT_CALL(*overridden_filter_chain_manager, findFilterChain(_)).WillOnce(Return(nullptr)); + EXPECT_CALL(*access_log_, log(_, _, _, _)); + EXPECT_CALL(*mock_connection_balancer, unregisterHandler(_)); + old_listener_callbacks->onAccept(Network::ConnectionSocketPtr{connection}); + EXPECT_EQ(0UL, handler_->numConnections()); + EXPECT_CALL(*old_listener, onDestroy()); +} + TEST_F(ConnectionHandlerTest, TcpListenerRemoveFilterChain) { InSequence s; uint64_t listener_tag = 1; @@ -1990,7 +2240,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerRemoveFilterChain) { auto listener = new NiceMock(); TestListener* test_listener = addListener(listener_tag, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -2039,7 +2289,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerRemoveFilterChainCalledAfterListenerIsR auto listener = new NiceMock(); TestListener* test_listener = addListener(listener_tag, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -2102,7 +2352,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerRemoveListener) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -2136,7 +2386,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerRemoveIpv6AnyAddressWithIpv4CompatListe addListener(1, true, false, "test_listener", listener, &listener_callbacks); Network::Address::InstanceConstSharedPtr any_address_ipv6( new Network::Address::Ipv6Instance("::", 80, nullptr, false)); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(any_address_ipv6)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -2167,7 +2417,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerRemoveIpv4CompatAddressListener) { addListener(1, true, false, "test_listener", listener, &listener_callbacks); Network::Address::InstanceConstSharedPtr address_ipv6( new Network::Address::Ipv6Instance("::FFFF:192.168.0.1", 80, nullptr, false)); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(address_ipv6)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -2198,7 +2448,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerRemoveWithBothIpv4AnyAndIpv6Any) { addListener(1, true, false, "test_listener", listener, &listener_callbacks); Network::Address::InstanceConstSharedPtr address_ipv6( new Network::Address::Ipv6Instance("::", 80, nullptr, false)); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(address_ipv6)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -2208,7 +2458,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerRemoveWithBothIpv4AnyAndIpv6Any) { addListener(2, true, false, "test_listener2", listener2, &listener_callbacks2); Network::Address::InstanceConstSharedPtr address_ipv4( new Network::Address::Ipv4Instance("0.0.0.0", 80, nullptr)); - EXPECT_CALL(test_listener2->socket_factory_, localAddress()) + EXPECT_CALL(test_listener2->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(address_ipv4)); handler_->addListener(absl::nullopt, *test_listener2, runtime_); @@ -2248,7 +2498,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerGlobalCxLimitReject) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -2264,7 +2514,7 @@ TEST_F(ConnectionHandlerTest, TcpListenerOverloadActionReject) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -2281,7 +2531,7 @@ TEST_F(ConnectionHandlerTest, ListenerFilterWorks) { auto listener = new NiceMock(); TestListener* test_listener = addListener(1, true, false, "test_listener", listener, &listener_callbacks); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); handler_->addListener(absl::nullopt, *test_listener, runtime_); @@ -2327,7 +2577,7 @@ TEST_F(ConnectionHandlerTest, ShutdownUdpListener) { udp_listener.addReadFilter(std::move(filter)); return true; })); - EXPECT_CALL(test_listener->socket_factory_, localAddress()) + EXPECT_CALL(test_listener->socketFactory(), localAddress()) .WillRepeatedly(ReturnRef(local_address_)); EXPECT_CALL(dummy_callbacks.udp_listener_, onDestroy()); @@ -2337,6 +2587,7 @@ TEST_F(ConnectionHandlerTest, ShutdownUdpListener) { ASSERT_TRUE(deleted_before_listener_) << "The read_filter_ should be deleted before the udp_listener_ is deleted."; } + } // namespace } // namespace Server } // namespace Envoy