diff --git a/docs/root/version_history/current.rst b/docs/root/version_history/current.rst index 8300923b8150..b1a92597465f 100644 --- a/docs/root/version_history/current.rst +++ b/docs/root/version_history/current.rst @@ -13,6 +13,7 @@ Bug Fixes --------- *Changes expected to improve the state of the world and are unlikely to have negative effects* * listener: fix crash when disabling or re-enabling listeners due to overload while processing LDS updates. +* proxy_proto: fixed a bug where the wrong downstream address got sent to upstream connections. Removed Config or Runtime ------------------------- diff --git a/include/envoy/network/proxy_protocol.h b/include/envoy/network/proxy_protocol.h index 52c111859b11..12f7323c4ccc 100644 --- a/include/envoy/network/proxy_protocol.h +++ b/include/envoy/network/proxy_protocol.h @@ -8,7 +8,11 @@ namespace Network { struct ProxyProtocolData { const Network::Address::InstanceConstSharedPtr src_addr_; const Network::Address::InstanceConstSharedPtr dst_addr_; + std::string asStringForHash() const { + return std::string(src_addr_ ? src_addr_->asString() : "null") + + (dst_addr_ ? dst_addr_->asString() : "null"); + } }; } // namespace Network -} // namespace Envoy \ No newline at end of file +} // namespace Envoy diff --git a/include/envoy/network/transport_socket.h b/include/envoy/network/transport_socket.h index fe054ce2f16d..95d07ac2e182 100644 --- a/include/envoy/network/transport_socket.h +++ b/include/envoy/network/transport_socket.h @@ -14,6 +14,7 @@ namespace Envoy { namespace Network { +class TransportSocketFactory; class Connection; enum class ConnectionEvent; @@ -198,11 +199,13 @@ class TransportSocketOptions { virtual absl::optional proxyProtocolOptions() const PURE; /** - * @param vector of bytes to which the option should append hash key data that will be used - * to separate connections based on the option. Any data already in the key vector must - * not be modified. + * @param key supplies a vector of bytes to which the option should append hash key data that will + * be used to separate connections based on the option. Any data already in the key vector + * must not be modified. + * @param factory supplies the factor which will be used for creating the transport socket. */ - virtual void hashKey(std::vector& key) const PURE; + virtual void hashKey(std::vector& key, + const Network::TransportSocketFactory& factory) const PURE; }; // TODO(mattklein123): Rename to TransportSocketOptionsConstSharedPtr in a dedicated follow up. @@ -226,6 +229,11 @@ class TransportSocketFactory { */ virtual TransportSocketPtr createTransportSocket(TransportSocketOptionsSharedPtr options) const PURE; + + /** + * @return bool whether the transport socket will use proxy protocol options. + */ + virtual bool usesProxyProtocolOptions() const PURE; }; using TransportSocketFactoryPtr = std::unique_ptr; diff --git a/source/common/network/raw_buffer_socket.h b/source/common/network/raw_buffer_socket.h index fe87bbeda605..9a17fe35516b 100644 --- a/source/common/network/raw_buffer_socket.h +++ b/source/common/network/raw_buffer_socket.h @@ -32,6 +32,7 @@ class RawBufferSocketFactory : public TransportSocketFactory { // Network::TransportSocketFactory TransportSocketPtr createTransportSocket(TransportSocketOptionsSharedPtr options) const override; bool implementsSecureTransport() const override; + bool usesProxyProtocolOptions() const override { return false; } }; } // namespace Network diff --git a/source/common/network/transport_socket_options_impl.cc b/source/common/network/transport_socket_options_impl.cc index 62358ce48710..66b139bba6e1 100644 --- a/source/common/network/transport_socket_options_impl.cc +++ b/source/common/network/transport_socket_options_impl.cc @@ -16,7 +16,8 @@ namespace Envoy { namespace Network { namespace { -void commonHashKey(const TransportSocketOptions& options, std::vector& key) { +void commonHashKey(const TransportSocketOptions& options, std::vector& key, + const Network::TransportSocketFactory& factory) { const auto& server_name_overide = options.serverNameOverride(); if (server_name_overide.has_value()) { pushScalarToByteVector(StringUtil::CaseInsensitiveHash()(server_name_overide.value()), key); @@ -35,19 +36,30 @@ void commonHashKey(const TransportSocketOptions& options, std::vector& key) const { - commonHashKey(*this, key); +void AlpnDecoratingTransportSocketOptions::hashKey( + std::vector& key, const Network::TransportSocketFactory& factory) const { + commonHashKey(*this, key, factory); } -void TransportSocketOptionsImpl::hashKey(std::vector& key) const { - commonHashKey(*this, key); +void TransportSocketOptionsImpl::hashKey(std::vector& key, + const Network::TransportSocketFactory& factory) const { + commonHashKey(*this, key, factory); } TransportSocketOptionsSharedPtr diff --git a/source/common/network/transport_socket_options_impl.h b/source/common/network/transport_socket_options_impl.h index 3611f117c8e5..4e08da3f292d 100644 --- a/source/common/network/transport_socket_options_impl.h +++ b/source/common/network/transport_socket_options_impl.h @@ -29,7 +29,8 @@ class AlpnDecoratingTransportSocketOptions : public TransportSocketOptions { absl::optional proxyProtocolOptions() const override { return inner_options_->proxyProtocolOptions(); } - void hashKey(std::vector& key) const override; + void hashKey(std::vector& key, + const Network::TransportSocketFactory& factory) const override; private: const absl::optional alpn_fallback_; @@ -67,7 +68,8 @@ class TransportSocketOptionsImpl : public TransportSocketOptions { absl::optional proxyProtocolOptions() const override { return proxy_protocol_options_; } - void hashKey(std::vector& key) const override; + void hashKey(std::vector& key, + const Network::TransportSocketFactory& factory) const override; private: const absl::optional override_server_name_; diff --git a/source/common/upstream/cluster_manager_impl.cc b/source/common/upstream/cluster_manager_impl.cc index 15df928be990..4b425789ee98 100644 --- a/source/common/upstream/cluster_manager_impl.cc +++ b/source/common/upstream/cluster_manager_impl.cc @@ -1380,7 +1380,7 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::ClusterEntry::connPool( bool have_transport_socket_options = false; if (context && context->upstreamTransportSocketOptions()) { - context->upstreamTransportSocketOptions()->hashKey(hash_key); + context->upstreamTransportSocketOptions()->hashKey(hash_key, host->transportSocketFactory()); have_transport_socket_options = true; } @@ -1440,7 +1440,7 @@ ClusterManagerImpl::ThreadLocalClusterManagerImpl::ClusterEntry::tcpConnPool( bool have_transport_socket_options = false; if (context != nullptr && context->upstreamTransportSocketOptions() != nullptr) { have_transport_socket_options = true; - context->upstreamTransportSocketOptions()->hashKey(hash_key); + context->upstreamTransportSocketOptions()->hashKey(hash_key, host->transportSocketFactory()); } TcpConnPoolsContainer& container = parent_.host_tcp_conn_pool_map_[host]; diff --git a/source/extensions/quic_listeners/quiche/quic_transport_socket_factory.h b/source/extensions/quic_listeners/quiche/quic_transport_socket_factory.h index 2ada9e2de17b..142489b39d9b 100644 --- a/source/extensions/quic_listeners/quiche/quic_transport_socket_factory.h +++ b/source/extensions/quic_listeners/quiche/quic_transport_socket_factory.h @@ -24,6 +24,7 @@ class QuicTransportSocketFactoryBase : public Network::TransportSocketFactory { NOT_REACHED_GCOVR_EXCL_LINE; } bool implementsSecureTransport() const override { return true; } + bool usesProxyProtocolOptions() const override { return false; } }; // TODO(danzh): when implement ProofSource, examine of it's necessary to diff --git a/source/extensions/transport_sockets/alts/tsi_socket.h b/source/extensions/transport_sockets/alts/tsi_socket.h index 0acba405022d..a4a7423bd927 100644 --- a/source/extensions/transport_sockets/alts/tsi_socket.h +++ b/source/extensions/transport_sockets/alts/tsi_socket.h @@ -98,6 +98,7 @@ class TsiSocketFactory : public Network::TransportSocketFactory { TsiSocketFactory(HandshakerFactory handshaker_factory, HandshakeValidator handshake_validator); bool implementsSecureTransport() const override; + bool usesProxyProtocolOptions() const override { return false; } Network::TransportSocketPtr createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override; diff --git a/source/extensions/transport_sockets/proxy_protocol/proxy_protocol.h b/source/extensions/transport_sockets/proxy_protocol/proxy_protocol.h index 4a191ebf539d..c4c9a80f629e 100644 --- a/source/extensions/transport_sockets/proxy_protocol/proxy_protocol.h +++ b/source/extensions/transport_sockets/proxy_protocol/proxy_protocol.h @@ -49,6 +49,7 @@ class UpstreamProxyProtocolSocketFactory : public Network::TransportSocketFactor Network::TransportSocketPtr createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override; bool implementsSecureTransport() const override; + bool usesProxyProtocolOptions() const override { return true; } private: Network::TransportSocketFactoryPtr transport_socket_factory_; @@ -58,4 +59,4 @@ class UpstreamProxyProtocolSocketFactory : public Network::TransportSocketFactor } // namespace ProxyProtocol } // namespace TransportSockets } // namespace Extensions -} // namespace Envoy \ No newline at end of file +} // namespace Envoy diff --git a/source/extensions/transport_sockets/tap/tap.cc b/source/extensions/transport_sockets/tap/tap.cc index 7674ba6b584d..2f58c23703ce 100644 --- a/source/extensions/transport_sockets/tap/tap.cc +++ b/source/extensions/transport_sockets/tap/tap.cc @@ -66,6 +66,10 @@ bool TapSocketFactory::implementsSecureTransport() const { return transport_socket_factory_->implementsSecureTransport(); } +bool TapSocketFactory::usesProxyProtocolOptions() const { + return transport_socket_factory_->usesProxyProtocolOptions(); +} + } // namespace Tap } // namespace TransportSockets } // namespace Extensions diff --git a/source/extensions/transport_sockets/tap/tap.h b/source/extensions/transport_sockets/tap/tap.h index 33156b705153..2971c3e846ba 100644 --- a/source/extensions/transport_sockets/tap/tap.h +++ b/source/extensions/transport_sockets/tap/tap.h @@ -41,6 +41,7 @@ class TapSocketFactory : public Network::TransportSocketFactory, Network::TransportSocketPtr createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override; bool implementsSecureTransport() const override; + bool usesProxyProtocolOptions() const override; private: Network::TransportSocketFactoryPtr transport_socket_factory_; diff --git a/source/extensions/transport_sockets/tls/ssl_socket.h b/source/extensions/transport_sockets/tls/ssl_socket.h index c14cb502bed1..cb7417837d65 100644 --- a/source/extensions/transport_sockets/tls/ssl_socket.h +++ b/source/extensions/transport_sockets/tls/ssl_socket.h @@ -108,6 +108,7 @@ class ClientSslSocketFactory : public Network::TransportSocketFactory, Network::TransportSocketPtr createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override; bool implementsSecureTransport() const override; + bool usesProxyProtocolOptions() const override { return false; } // Secret::SecretCallbacks void onAddOrUpdateSecret() override; @@ -132,6 +133,7 @@ class ServerSslSocketFactory : public Network::TransportSocketFactory, Network::TransportSocketPtr createTransportSocket(Network::TransportSocketOptionsSharedPtr options) const override; bool implementsSecureTransport() const override; + bool usesProxyProtocolOptions() const override { return false; } // Secret::SecretCallbacks void onAddOrUpdateSecret() override; diff --git a/test/common/network/BUILD b/test/common/network/BUILD index ef62c131dba5..3db38e6825a9 100644 --- a/test/common/network/BUILD +++ b/test/common/network/BUILD @@ -234,6 +234,15 @@ envoy_cc_test( ], ) +envoy_cc_test( + name = "raw_buffer_socket_test", + srcs = ["raw_buffer_socket_test.cc"], + deps = [ + "//source/common/network:raw_buffer_socket_lib", + "//test/test_common:network_utility_lib", + ], +) + envoy_cc_test_library( name = "udp_listener_impl_test_base_lib", hdrs = ["udp_listener_impl_test_base.h"], diff --git a/test/common/network/raw_buffer_socket_test.cc b/test/common/network/raw_buffer_socket_test.cc new file mode 100644 index 000000000000..f28e54f53bc9 --- /dev/null +++ b/test/common/network/raw_buffer_socket_test.cc @@ -0,0 +1,16 @@ +#include "common/network/raw_buffer_socket.h" + +#include "test/test_common/network_utility.h" + +#include "gtest/gtest.h" + +namespace Envoy { +namespace Network { + +TEST(RawBufferSocketFactory, RawBufferSocketFactory) { + TransportSocketFactoryPtr factory = Envoy::Network::Test::createRawBufferSocketFactory(); + EXPECT_FALSE(factory->usesProxyProtocolOptions()); +} + +} // namespace Network +} // namespace Envoy diff --git a/test/common/upstream/transport_socket_matcher_test.cc b/test/common/upstream/transport_socket_matcher_test.cc index cfde130d1d1f..b5e495c8e592 100644 --- a/test/common/upstream/transport_socket_matcher_test.cc +++ b/test/common/upstream/transport_socket_matcher_test.cc @@ -31,6 +31,7 @@ namespace { class FakeTransportSocketFactory : public Network::TransportSocketFactory { public: MOCK_METHOD(bool, implementsSecureTransport, (), (const)); + MOCK_METHOD(bool, usesProxyProtocolOptions, (), (const)); MOCK_METHOD(Network::TransportSocketPtr, createTransportSocket, (Network::TransportSocketOptionsSharedPtr), (const)); FakeTransportSocketFactory(std::string id) : id_(std::move(id)) {} @@ -46,6 +47,7 @@ class FooTransportSocketFactory Logger::Loggable { public: MOCK_METHOD(bool, implementsSecureTransport, (), (const)); + MOCK_METHOD(bool, usesProxyProtocolOptions, (), (const)); MOCK_METHOD(Network::TransportSocketPtr, createTransportSocket, (Network::TransportSocketOptionsSharedPtr), (const)); diff --git a/test/extensions/transport_sockets/alts/tsi_socket_test.cc b/test/extensions/transport_sockets/alts/tsi_socket_test.cc index 3fd39b520020..85f40ab3fcd8 100644 --- a/test/extensions/transport_sockets/alts/tsi_socket_test.cc +++ b/test/extensions/transport_sockets/alts/tsi_socket_test.cc @@ -55,7 +55,6 @@ class TsiSocketTest : public testing::Test { client_.tsi_socket_ = std::make_unique(client_.handshaker_factory_, client_validator, Network::TransportSocketPtr{client_.raw_socket_}); - ON_CALL(client_.callbacks_.connection_, dispatcher()).WillByDefault(ReturnRef(dispatcher_)); ON_CALL(server_.callbacks_.connection_, dispatcher()).WillByDefault(ReturnRef(dispatcher_)); @@ -194,6 +193,7 @@ static const std::string ClientToServerData = "hello from client"; TEST_F(TsiSocketTest, DoesNotHaveSsl) { initialize(nullptr, nullptr); EXPECT_EQ(nullptr, client_.tsi_socket_->ssl()); + EXPECT_FALSE(client_.tsi_socket_->canFlushClose()); const auto& socket_ = *client_.tsi_socket_; EXPECT_EQ(nullptr, socket_.ssl()); @@ -406,6 +406,10 @@ TEST_F(TsiSocketFactoryTest, ImplementsSecureTransport) { EXPECT_TRUE(socket_factory_->implementsSecureTransport()); } +TEST_F(TsiSocketFactoryTest, UsesProxyProtocolOptions) { + EXPECT_FALSE(socket_factory_->usesProxyProtocolOptions()); +} + } // namespace } // namespace Alts } // namespace TransportSockets diff --git a/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_integration_test.cc b/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_integration_test.cc index 99e04a348746..5747ec73d125 100644 --- a/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_integration_test.cc +++ b/test/extensions/transport_sockets/proxy_protocol/proxy_protocol_integration_test.cc @@ -104,6 +104,36 @@ TEST_P(ProxyProtocolIntegrationTest, TestV1ProxyProtocol) { ASSERT_TRUE(fake_upstream_connection_->waitForDisconnect()); } +TEST_P(ProxyProtocolIntegrationTest, TestV1ProxyProtocolMultipleConnections) { + if (GetParam() != Network::Address::IpVersion::v4) { + return; + } + + setup(envoy::config::core::v3::ProxyProtocolConfig::V1, false, + "envoy.transport_sockets.raw_buffer"); + initialize(); + auto listener_port = lookupPort("listener_0"); + + auto loopback2 = Network::Utility::resolveUrl("tcp://127.0.0.2:0"); + auto tcp_client2 = makeTcpConnection(listener_port, nullptr, loopback2); + + auto tcp_client = makeTcpConnection(listener_port); + + ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(fake_upstream_connection_)); + FakeRawConnectionPtr conn2; + ASSERT_TRUE(fake_upstreams_[0]->waitForRawConnection(conn2)); + + std::string data1, data2; + ASSERT_TRUE( + fake_upstream_connection_->waitForData(FakeRawConnection::waitForAtLeastBytes(32), &data1)); + ASSERT_TRUE(conn2->waitForData(FakeRawConnection::waitForAtLeastBytes(32), &data2)); + + EXPECT_NE(data1, data2); + + tcp_client->close(); + tcp_client2->close(); +} + // Test header is sent unencrypted using a TLS inner socket TEST_P(ProxyProtocolIntegrationTest, TestTLSSocket) { setup(envoy::config::core::v3::ProxyProtocolConfig::V1, false, "envoy.transport_sockets.tls"); @@ -201,4 +231,4 @@ TEST_P(ProxyProtocolIntegrationTest, TestV2ProxyProtocol) { } } // namespace -} // namespace Envoy \ No newline at end of file +} // namespace Envoy diff --git a/test/extensions/transport_sockets/tap/tap_config_impl_test.cc b/test/extensions/transport_sockets/tap/tap_config_impl_test.cc index c8bcefbf623d..99f10e518e8d 100644 --- a/test/extensions/transport_sockets/tap/tap_config_impl_test.cc +++ b/test/extensions/transport_sockets/tap/tap_config_impl_test.cc @@ -58,7 +58,11 @@ class PerSocketTapperImplTest : public testing::Test { EXPECT_CALL(matcher_, onNewStream(_)) .WillOnce(Invoke([this](TapCommon::Matcher::MatchStatusVector& statuses) { statuses_ = &statuses; - statuses[0].matches_ = true; + if (fail_match_) { + statuses[0].matches_ = false; + } else { + statuses[0].matches_ = true; + } statuses[0].might_change_status_ = false; })); EXPECT_CALL(*config_, streaming()).WillRepeatedly(Return(streaming)); @@ -79,6 +83,7 @@ class PerSocketTapperImplTest : public testing::Test { TapCommon::Matcher::MatchStatusVector* statuses_; NiceMock connection_; Event::SimulatedTimeSystem time_system_; + bool fail_match_{}; }; // Verify the full streaming flow. @@ -139,6 +144,15 @@ TEST_F(PerSocketTapperImplTest, StreamingFlow) { tapper_->closeSocket(Network::ConnectionEvent::RemoteClose); } +TEST_F(PerSocketTapperImplTest, NonMatchingFlow) { + fail_match_ = true; + setup(true); + + EXPECT_CALL(*sink_manager_, submitTrace_(_)).Times(0); + time_system_.setSystemTime(std::chrono::seconds(2)); + tapper_->closeSocket(Network::ConnectionEvent::RemoteClose); +} + } // namespace } // namespace Tap } // namespace TransportSockets diff --git a/test/integration/base_integration_test.cc b/test/integration/base_integration_test.cc index 4a2623f43ae4..ade05762720c 100644 --- a/test/integration/base_integration_test.cc +++ b/test/integration/base_integration_test.cc @@ -190,9 +190,10 @@ void BaseIntegrationTest::setUpstreamProtocol(FakeHttpConnection::Type protocol) IntegrationTcpClientPtr BaseIntegrationTest::makeTcpConnection(uint32_t port, - const Network::ConnectionSocket::OptionsSharedPtr& options) { + const Network::ConnectionSocket::OptionsSharedPtr& options, + Network::Address::InstanceConstSharedPtr source_address) { return std::make_unique(*dispatcher_, *mock_buffer_factory_, port, version_, - enable_half_close_, options); + enable_half_close_, options, source_address); } void BaseIntegrationTest::registerPort(const std::string& key, uint32_t port) { diff --git a/test/integration/base_integration_test.h b/test/integration/base_integration_test.h index 2a17a1cf07b5..394ab89e91f6 100644 --- a/test/integration/base_integration_test.h +++ b/test/integration/base_integration_test.h @@ -86,7 +86,9 @@ class BaseIntegrationTest : protected Logger::Loggable { IntegrationTcpClientPtr makeTcpConnection(uint32_t port, - const Network::ConnectionSocket::OptionsSharedPtr& options = nullptr); + const Network::ConnectionSocket::OptionsSharedPtr& options = nullptr, + Network::Address::InstanceConstSharedPtr source_address = + Network::Address::InstanceConstSharedPtr()); // Test-wide port map. void registerPort(const std::string& key, uint32_t port); diff --git a/test/integration/fake_upstream.h b/test/integration/fake_upstream.h index 0607d6926fd7..538b2808b69c 100644 --- a/test/integration/fake_upstream.h +++ b/test/integration/fake_upstream.h @@ -513,6 +513,12 @@ class FakeRawConnection : public FakeConnectionBase { }; } + // Creates a ValidatorFunction which returns true when data_to_wait_for is + // contains at least bytes_read bytes. + static ValidatorFunction waitForAtLeastBytes(uint32_t bytes) { + return [bytes](const std::string& data) -> bool { return data.size() >= bytes; }; + } + private: struct ReadFilter : public Network::ReadFilterBaseImpl { ReadFilter(FakeRawConnection& parent) : parent_(parent) {} diff --git a/test/integration/integration_tcp_client.cc b/test/integration/integration_tcp_client.cc index 590b5c92fcf4..39c040d4b3b0 100644 --- a/test/integration/integration_tcp_client.cc +++ b/test/integration/integration_tcp_client.cc @@ -37,7 +37,8 @@ using ::testing::NiceMock; IntegrationTcpClient::IntegrationTcpClient( Event::Dispatcher& dispatcher, MockBufferFactory& factory, uint32_t port, Network::Address::IpVersion version, bool enable_half_close, - const Network::ConnectionSocket::OptionsSharedPtr& options) + const Network::ConnectionSocket::OptionsSharedPtr& options, + Network::Address::InstanceConstSharedPtr source_address) : payload_reader_(new WaitForPayloadReader(dispatcher)), callbacks_(new ConnectionCallbacks(*this)) { EXPECT_CALL(factory, create_(_, _, _)) @@ -51,7 +52,7 @@ IntegrationTcpClient::IntegrationTcpClient( connection_ = dispatcher.createClientConnection( Network::Utility::resolveUrl( fmt::format("tcp://{}:{}", Network::Test::getLoopbackAddressUrlString(version), port)), - Network::Address::InstanceConstSharedPtr(), Network::Test::createRawBufferSocket(), options); + source_address, Network::Test::createRawBufferSocket(), options); ON_CALL(*client_write_buffer_, drain(_)) .WillByDefault(Invoke(client_write_buffer_, &MockWatermarkBuffer::trackDrains)); diff --git a/test/integration/integration_tcp_client.h b/test/integration/integration_tcp_client.h index f353c8a3188c..af75b84de08c 100644 --- a/test/integration/integration_tcp_client.h +++ b/test/integration/integration_tcp_client.h @@ -28,7 +28,8 @@ class IntegrationTcpClient { public: IntegrationTcpClient(Event::Dispatcher& dispatcher, MockBufferFactory& factory, uint32_t port, Network::Address::IpVersion version, bool enable_half_close, - const Network::ConnectionSocket::OptionsSharedPtr& options); + const Network::ConnectionSocket::OptionsSharedPtr& options, + Network::Address::InstanceConstSharedPtr source_address = nullptr); void close(); void waitForData(const std::string& data, bool exact_match = true); diff --git a/test/mocks/network/transport_socket.h b/test/mocks/network/transport_socket.h index ee53570c20ac..ed8fa15b7be3 100644 --- a/test/mocks/network/transport_socket.h +++ b/test/mocks/network/transport_socket.h @@ -36,6 +36,7 @@ class MockTransportSocketFactory : public TransportSocketFactory { ~MockTransportSocketFactory() override; MOCK_METHOD(bool, implementsSecureTransport, (), (const)); + MOCK_METHOD(bool, usesProxyProtocolOptions, (), (const)); MOCK_METHOD(TransportSocketPtr, createTransportSocket, (TransportSocketOptionsSharedPtr), (const)); };