Skip to content

Commit

Permalink
mobile: Expose disable_dns_refresh_on_failure (envoyproxy#38255)
Browse files Browse the repository at this point in the history
This PR exposes the `DnsConfig.disable_dns_refresh_on_failure` config
into the `EngineBuilder`.

Risk Level: low
Testing: integration test
Docs Changes: n/a
Release Notes: n/a
Platform Specific Features: mobile

---------

Signed-off-by: Fredy Wijaya <[email protected]>
  • Loading branch information
fredyw authored Jan 29, 2025
1 parent 8584f9c commit fcaea94
Show file tree
Hide file tree
Showing 10 changed files with 121 additions and 51 deletions.
6 changes: 6 additions & 0 deletions mobile/library/cc/engine_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ EngineBuilder& EngineBuilder::addDnsQueryTimeoutSeconds(int dns_query_timeout_se
return *this;
}

EngineBuilder& EngineBuilder::setDisableDnsRefreshOnFailure(bool dns_refresh_on_failure) {
disable_dns_refresh_on_failure_ = dns_refresh_on_failure;
return *this;
}

EngineBuilder& EngineBuilder::setDnsNumRetries(uint32_t dns_num_retries) {
dns_num_retries_ = dns_num_retries;
return *this;
Expand Down Expand Up @@ -480,6 +485,7 @@ std::unique_ptr<envoy::config::bootstrap::v3::Bootstrap> EngineBuilder::generate
dns_cache_config->mutable_dns_failure_refresh_rate()->mutable_max_interval()->set_seconds(
dns_failure_refresh_seconds_max_);
dns_cache_config->mutable_dns_query_timeout()->set_seconds(dns_query_timeout_seconds_);
dns_cache_config->set_disable_dns_refresh_on_failure(disable_dns_refresh_on_failure_);
if (dns_cache_on_) {
envoymobile::extensions::key_value::platform::PlatformKeyValueStoreConfig kv_config;
kv_config.set_key("dns_persistent_cache");
Expand Down
2 changes: 2 additions & 0 deletions mobile/library/cc/engine_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class EngineBuilder {
EngineBuilder& addDnsRefreshSeconds(int dns_refresh_seconds);
EngineBuilder& addDnsFailureRefreshSeconds(int base, int max);
EngineBuilder& addDnsQueryTimeoutSeconds(int dns_query_timeout_seconds);
EngineBuilder& setDisableDnsRefreshOnFailure(bool dns_refresh_on_failure);
EngineBuilder& addDnsMinRefreshSeconds(int dns_min_refresh_seconds);
EngineBuilder& setDnsNumRetries(uint32_t dns_num_retries);
EngineBuilder& addMaxConnectionsPerHost(int max_connections_per_host);
Expand Down Expand Up @@ -152,6 +153,7 @@ class EngineBuilder {
int dns_failure_refresh_seconds_base_ = 2;
int dns_failure_refresh_seconds_max_ = 10;
int dns_query_timeout_seconds_ = 5;
bool disable_dns_refresh_on_failure_{false};
absl::optional<uint32_t> dns_num_retries_ = 3;
int h2_connection_keepalive_idle_interval_milliseconds_ = 100000000;
int h2_connection_keepalive_timeout_seconds_ = 10;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public enum TrustChainVerification {
}

public final int connectTimeoutSeconds;
public final boolean disableDnsRefreshOnFailure;
public final int dnsRefreshSeconds;
public final int dnsFailureRefreshSecondsBase;
public final int dnsFailureRefreshSecondsMax;
Expand Down Expand Up @@ -68,8 +69,9 @@ public enum TrustChainVerification {
* Create a new instance of the configuration.
*
* @param connectTimeoutSeconds timeout for new network connections to
* hosts in
* the cluster.
* hosts in the cluster.
* @param disableDnsRefreshOnFailure whether to disable the DNS refresh on
* failure
* @param dnsRefreshSeconds default rate in seconds at which to
* refresh DNS.
* @param dnsFailureRefreshSecondsBase base rate in seconds to refresh DNS on
Expand Down Expand Up @@ -131,18 +133,18 @@ public enum TrustChainVerification {
* HTTP/3.
*/
public EnvoyConfiguration(
int connectTimeoutSeconds, int dnsRefreshSeconds, int dnsFailureRefreshSecondsBase,
int dnsFailureRefreshSecondsMax, int dnsQueryTimeoutSeconds, int dnsMinRefreshSeconds,
List<String> dnsPreresolveHostnames, boolean enableDNSCache, int dnsCacheSaveIntervalSeconds,
int dnsNumRetries, boolean enableDrainPostDnsRefresh, boolean enableHttp3, boolean useCares,
String http3ConnectionOptions, String http3ClientConnectionOptions,
Map<String, Integer> quicHints, List<String> quicCanonicalSuffixes,
boolean enableGzipDecompression, boolean enableBrotliDecompression,
int numTimeoutsToTriggerPortMigration, boolean enableSocketTagging,
boolean enableInterfaceBinding, int h2ConnectionKeepaliveIdleIntervalMilliseconds,
int h2ConnectionKeepaliveTimeoutSeconds, int maxConnectionsPerHost,
int streamIdleTimeoutSeconds, int perTryIdleTimeoutSeconds, String appVersion, String appId,
TrustChainVerification trustChainVerification,
int connectTimeoutSeconds, boolean disableDnsRefreshOnFailure, int dnsRefreshSeconds,
int dnsFailureRefreshSecondsBase, int dnsFailureRefreshSecondsMax, int dnsQueryTimeoutSeconds,
int dnsMinRefreshSeconds, List<String> dnsPreresolveHostnames, boolean enableDNSCache,
int dnsCacheSaveIntervalSeconds, int dnsNumRetries, boolean enableDrainPostDnsRefresh,
boolean enableHttp3, boolean useCares, String http3ConnectionOptions,
String http3ClientConnectionOptions, Map<String, Integer> quicHints,
List<String> quicCanonicalSuffixes, boolean enableGzipDecompression,
boolean enableBrotliDecompression, int numTimeoutsToTriggerPortMigration,
boolean enableSocketTagging, boolean enableInterfaceBinding,
int h2ConnectionKeepaliveIdleIntervalMilliseconds, int h2ConnectionKeepaliveTimeoutSeconds,
int maxConnectionsPerHost, int streamIdleTimeoutSeconds, int perTryIdleTimeoutSeconds,
String appVersion, String appId, TrustChainVerification trustChainVerification,
List<EnvoyNativeFilterConfig> nativeFilterChain,
List<EnvoyHTTPFilterFactory> httpPlatformFilterFactories,
Map<String, EnvoyStringAccessor> stringAccessors,
Expand All @@ -152,6 +154,7 @@ public EnvoyConfiguration(
int h3ConnectionKeepaliveInitialIntervalMilliseconds) {
JniLibrary.load();
this.connectTimeoutSeconds = connectTimeoutSeconds;
this.disableDnsRefreshOnFailure = disableDnsRefreshOnFailure;
this.dnsRefreshSeconds = dnsRefreshSeconds;
this.dnsFailureRefreshSecondsBase = dnsFailureRefreshSecondsBase;
this.dnsFailureRefreshSecondsMax = dnsFailureRefreshSecondsMax;
Expand Down Expand Up @@ -229,16 +232,16 @@ public long createBootstrap() {
JniBridgeUtility.listOfStringPairsToJniBytes(this.caresFallbackResolvers);

return JniLibrary.createBootstrap(
connectTimeoutSeconds, dnsRefreshSeconds, dnsFailureRefreshSecondsBase,
dnsFailureRefreshSecondsMax, dnsQueryTimeoutSeconds, dnsMinRefreshSeconds, dnsPreresolve,
enableDNSCache, dnsCacheSaveIntervalSeconds, dnsNumRetries, enableDrainPostDnsRefresh,
enableHttp3, useCares, http3ConnectionOptions, http3ClientConnectionOptions, quicHints,
quicSuffixes, enableGzipDecompression, enableBrotliDecompression,
numTimeoutsToTriggerPortMigration, enableSocketTagging, enableInterfaceBinding,
h2ConnectionKeepaliveIdleIntervalMilliseconds, h2ConnectionKeepaliveTimeoutSeconds,
maxConnectionsPerHost, streamIdleTimeoutSeconds, perTryIdleTimeoutSeconds, appVersion,
appId, enforceTrustChainVerification, filterChain, enablePlatformCertificatesValidation,
upstreamTlsSni, runtimeGuards, caresFallbackResolvers,
connectTimeoutSeconds, disableDnsRefreshOnFailure, dnsRefreshSeconds,
dnsFailureRefreshSecondsBase, dnsFailureRefreshSecondsMax, dnsQueryTimeoutSeconds,
dnsMinRefreshSeconds, dnsPreresolve, enableDNSCache, dnsCacheSaveIntervalSeconds,
dnsNumRetries, enableDrainPostDnsRefresh, enableHttp3, useCares, http3ConnectionOptions,
http3ClientConnectionOptions, quicHints, quicSuffixes, enableGzipDecompression,
enableBrotliDecompression, numTimeoutsToTriggerPortMigration, enableSocketTagging,
enableInterfaceBinding, h2ConnectionKeepaliveIdleIntervalMilliseconds,
h2ConnectionKeepaliveTimeoutSeconds, maxConnectionsPerHost, streamIdleTimeoutSeconds,
perTryIdleTimeoutSeconds, appVersion, appId, enforceTrustChainVerification, filterChain,
enablePlatformCertificatesValidation, upstreamTlsSni, runtimeGuards, caresFallbackResolvers,
h3ConnectionKeepaliveInitialIntervalMilliseconds);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -300,10 +300,11 @@ public static native Object callCertificateVerificationFromNative(byte[][] certC
*
*/
public static native long createBootstrap(
long connectTimeoutSeconds, long dnsRefreshSeconds, long dnsFailureRefreshSecondsBase,
long dnsFailureRefreshSecondsMax, long dnsQueryTimeoutSeconds, long dnsMinRefreshSeconds,
byte[][] dnsPreresolveHostnames, boolean enableDNSCache, long dnsCacheSaveIntervalSeconds,
int dnsNumRetries, boolean enableDrainPostDnsRefresh, boolean enableHttp3, boolean useCares,
long connectTimeoutSeconds, boolean disableDnsRefreshOnFailure, long dnsRefreshSeconds,
long dnsFailureRefreshSecondsBase, long dnsFailureRefreshSecondsMax,
long dnsQueryTimeoutSeconds, long dnsMinRefreshSeconds, byte[][] dnsPreresolveHostnames,
boolean enableDNSCache, long dnsCacheSaveIntervalSeconds, int dnsNumRetries,
boolean enableDrainPostDnsRefresh, boolean enableHttp3, boolean useCares,
String http3ConnectionOptions, String http3ClientConnectionOptions, byte[][] quicHints,
byte[][] quicCanonicalSuffixes, boolean enableGzipDecompression,
boolean enableBrotliDecompression, int numTimeoutsToTriggerPortMigration,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public class NativeCronvoyEngineBuilderImpl extends CronvoyEngineBuilderImpl {
private final EnvoyEventTracker mEnvoyEventTracker = null;
private int mConnectTimeoutSeconds = 10;
private final int mDnsRefreshSeconds = 60;
private boolean mDisableDnsRefreshOnFailure = false;
private final int mDnsFailureRefreshSecondsBase = 2;
private final int mDnsFailureRefreshSecondsMax = 10;
private int mDnsQueryTimeoutSeconds = 5;
Expand Down Expand Up @@ -133,6 +134,13 @@ public NativeCronvoyEngineBuilderImpl setEnableProxying(boolean enable) {
return this;
}

/** Disables the DNS refresh on failure. */
public NativeCronvoyEngineBuilderImpl
setDisableDnsRefreshOnFailure(boolean disableDnsRefreshOnFailure) {
mDisableDnsRefreshOnFailure = disableDnsRefreshOnFailure;
return this;
}

/**
* Set the DNS minimum refresh time, in seconds, which ensures that we wait to refresh a DNS
* entry for at least the minimum refresh time. For example, if the DNS record TTL is 60 seconds
Expand Down Expand Up @@ -275,12 +283,12 @@ private EnvoyConfiguration createEnvoyConfiguration() {
Map<String, EnvoyKeyValueStore> keyValueStores = Collections.emptyMap();

return new EnvoyConfiguration(
mConnectTimeoutSeconds, mDnsRefreshSeconds, mDnsFailureRefreshSecondsBase,
mDnsFailureRefreshSecondsMax, mDnsQueryTimeoutSeconds, mDnsMinRefreshSeconds,
mDnsPreresolveHostnames, mEnableDNSCache, mDnsCacheSaveIntervalSeconds,
mDnsNumRetries.orElse(-1), mEnableDrainPostDnsRefresh, quicEnabled(), mUseCares,
quicConnectionOptions(), quicClientConnectionOptions(), quicHints(),
quicCanonicalSuffixes(), mEnableGzipDecompression, brotliEnabled(),
mConnectTimeoutSeconds, mDisableDnsRefreshOnFailure, mDnsRefreshSeconds,
mDnsFailureRefreshSecondsBase, mDnsFailureRefreshSecondsMax, mDnsQueryTimeoutSeconds,
mDnsMinRefreshSeconds, mDnsPreresolveHostnames, mEnableDNSCache,
mDnsCacheSaveIntervalSeconds, mDnsNumRetries.orElse(-1), mEnableDrainPostDnsRefresh,
quicEnabled(), mUseCares, quicConnectionOptions(), quicClientConnectionOptions(),
quicHints(), quicCanonicalSuffixes(), mEnableGzipDecompression, brotliEnabled(),
numTimeoutsToTriggerPortMigration(), mEnableSocketTag, mEnableInterfaceBinding,
mH2ConnectionKeepaliveIdleIntervalMilliseconds, mH2ConnectionKeepaliveTimeoutSeconds,
mMaxConnectionsPerHost, mStreamIdleTimeoutSeconds, mPerTryIdleTimeoutSeconds, mAppVersion,
Expand Down
34 changes: 18 additions & 16 deletions mobile/library/jni/jni_impl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1213,12 +1213,13 @@ javaObjectArrayToStringPairVector(Envoy::JNI::JniHelper& jni_helper, jobjectArra
}

void configureBuilder(Envoy::JNI::JniHelper& jni_helper, jlong connect_timeout_seconds,
jlong dns_refresh_seconds, jlong dns_failure_refresh_seconds_base,
jlong dns_failure_refresh_seconds_max, jlong dns_query_timeout_seconds,
jlong dns_min_refresh_seconds, jobjectArray dns_preresolve_hostnames,
jboolean enable_dns_cache, jlong dns_cache_save_interval_seconds,
jint dns_num_retries, jboolean enable_drain_post_dns_refresh,
jboolean enable_http3, jboolean use_cares, jstring http3_connection_options,
jboolean disable_dns_refresh_on_failure, jlong dns_refresh_seconds,
jlong dns_failure_refresh_seconds_base, jlong dns_failure_refresh_seconds_max,
jlong dns_query_timeout_seconds, jlong dns_min_refresh_seconds,
jobjectArray dns_preresolve_hostnames, jboolean enable_dns_cache,
jlong dns_cache_save_interval_seconds, jint dns_num_retries,
jboolean enable_drain_post_dns_refresh, jboolean enable_http3,
jboolean use_cares, jstring http3_connection_options,
jstring http3_client_connection_options, jobjectArray quic_hints,
jobjectArray quic_canonical_suffixes, jboolean enable_gzip_decompression,
jboolean enable_brotli_decompression,
Expand All @@ -1234,6 +1235,7 @@ void configureBuilder(Envoy::JNI::JniHelper& jni_helper, jlong connect_timeout_s
jlong h3_connection_keepalive_initial_interval_milliseconds,
Envoy::Platform::EngineBuilder& builder) {
builder.addConnectTimeoutSeconds((connect_timeout_seconds));
builder.setDisableDnsRefreshOnFailure(disable_dns_refresh_on_failure);
builder.addDnsRefreshSeconds((dns_refresh_seconds));
builder.addDnsFailureRefreshSeconds((dns_failure_refresh_seconds_base),
(dns_failure_refresh_seconds_max));
Expand Down Expand Up @@ -1318,10 +1320,10 @@ Java_io_envoyproxy_envoymobile_engine_JniLibrary_getNativeFilterConfig(JNIEnv* e
}

extern "C" JNIEXPORT jlong JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibrary_createBootstrap(
JNIEnv* env, jclass, jlong connect_timeout_seconds, jlong dns_refresh_seconds,
jlong dns_failure_refresh_seconds_base, jlong dns_failure_refresh_seconds_max,
jlong dns_query_timeout_seconds, jlong dns_min_refresh_seconds,
jobjectArray dns_preresolve_hostnames, jboolean enable_dns_cache,
JNIEnv* env, jclass, jlong connect_timeout_seconds, jboolean disable_dns_refresh_on_failure,
jlong dns_refresh_seconds, jlong dns_failure_refresh_seconds_base,
jlong dns_failure_refresh_seconds_max, jlong dns_query_timeout_seconds,
jlong dns_min_refresh_seconds, jobjectArray dns_preresolve_hostnames, jboolean enable_dns_cache,
jlong dns_cache_save_interval_seconds, jint dns_num_retries,
jboolean enable_drain_post_dns_refresh, jboolean enable_http3, jboolean use_cares,
jstring http3_connection_options, jstring http3_client_connection_options,
Expand All @@ -1339,12 +1341,12 @@ extern "C" JNIEXPORT jlong JNICALL Java_io_envoyproxy_envoymobile_engine_JniLibr
Envoy::Platform::EngineBuilder builder;

configureBuilder(
jni_helper, connect_timeout_seconds, dns_refresh_seconds, dns_failure_refresh_seconds_base,
dns_failure_refresh_seconds_max, dns_query_timeout_seconds, dns_min_refresh_seconds,
dns_preresolve_hostnames, enable_dns_cache, dns_cache_save_interval_seconds, dns_num_retries,
enable_drain_post_dns_refresh, enable_http3, use_cares, http3_connection_options,
http3_client_connection_options, quic_hints, quic_canonical_suffixes,
enable_gzip_decompression, enable_brotli_decompression,
jni_helper, connect_timeout_seconds, disable_dns_refresh_on_failure, dns_refresh_seconds,
dns_failure_refresh_seconds_base, dns_failure_refresh_seconds_max, dns_query_timeout_seconds,
dns_min_refresh_seconds, dns_preresolve_hostnames, enable_dns_cache,
dns_cache_save_interval_seconds, dns_num_retries, enable_drain_post_dns_refresh, enable_http3,
use_cares, http3_connection_options, http3_client_connection_options, quic_hints,
quic_canonical_suffixes, enable_gzip_decompression, enable_brotli_decompression,
num_timeouts_to_trigger_port_migration, enable_socket_tagging, enable_interface_binding,
h2_connection_keepalive_idle_interval_milliseconds, h2_connection_keepalive_timeout_seconds,
max_connections_per_host, stream_idle_timeout_seconds, per_try_idle_timeout_seconds,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ open class EngineBuilder() {
}
private var logLevel = LogLevel.INFO
private var connectTimeoutSeconds = 10
private var disableDnsRefreshOnFailure = false
private var dnsRefreshSeconds = 60
private var dnsFailureRefreshSecondsBase = 2
private var dnsFailureRefreshSecondsMax = 10
Expand Down Expand Up @@ -540,6 +541,7 @@ open class EngineBuilder() {
val engineConfiguration =
EnvoyConfiguration(
connectTimeoutSeconds,
disableDnsRefreshOnFailure,
dnsRefreshSeconds,
dnsFailureRefreshSecondsBase,
dnsFailureRefreshSecondsMax,
Expand Down
13 changes: 13 additions & 0 deletions mobile/test/cc/unit/envoy_config_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ TEST(TestConfig, ConfigIsApplied) {
.addQuicCanonicalSuffix(".xyz.com")
.setNumTimeoutsToTriggerPortMigration(4)
.addConnectTimeoutSeconds(123)
.setDisableDnsRefreshOnFailure(true)
.addDnsRefreshSeconds(456)
.addDnsMinRefreshSeconds(567)
.addDnsFailureRefreshSeconds(789, 987)
Expand Down Expand Up @@ -246,6 +247,18 @@ TEST(TestConfig, SetDnsQueryTimeout) {
EXPECT_THAT(bootstrap->ShortDebugString(), HasSubstr("dns_query_timeout { seconds: 30 }"));
}

TEST(TestConfig, SetDisableDnsRefreshOnFailure) {
EngineBuilder engine_builder;

std::unique_ptr<Bootstrap> bootstrap = engine_builder.generateBootstrap();
// The default value.
EXPECT_THAT(bootstrap->ShortDebugString(), Not(HasSubstr("disable_dns_refresh_on_failure")));

engine_builder.setDisableDnsRefreshOnFailure(true);
bootstrap = engine_builder.generateBootstrap();
EXPECT_THAT(bootstrap->ShortDebugString(), HasSubstr("disable_dns_refresh_on_failure: true"));
}

TEST(TestConfig, EnforceTrustChainVerification) {
EngineBuilder engine_builder;

Expand Down
29 changes: 29 additions & 0 deletions mobile/test/common/integration/client_integration_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,35 @@ TEST_P(ClientIntegrationTest, BasicWithCares) {
}
#endif

TEST_P(ClientIntegrationTest, DisableDnsRefreshOnFailure) {
builder_.setLogLevel(Logger::Logger::debug);
std::atomic<bool> found_cache_miss{false};
auto logger = std::make_unique<EnvoyLogger>();
logger->on_log_ = [&](Logger::Logger::Levels, const std::string& msg) {
if (msg.find("ignoring failed address cache hit for miss for host 'doesnotexist") !=
std::string::npos) {
found_cache_miss = true;
}
};
builder_.setLogger(std::move(logger));
builder_.addRuntimeGuard("dns_nodata_noname_is_success", false);
builder_.setDisableDnsRefreshOnFailure(true);
initialize();

default_request_headers_.setHost("doesnotexist");
stream_ = createNewStream(createDefaultStreamCallbacks());
stream_->sendHeaders(std::make_unique<Http::TestRequestHeaderMapImpl>(default_request_headers_),
true);
terminal_callback_.waitReady();

stream_ = createNewStream(createDefaultStreamCallbacks());
stream_->sendHeaders(std::make_unique<Http::TestRequestHeaderMapImpl>(default_request_headers_),
true);
terminal_callback_.waitReady();

EXPECT_TRUE(found_cache_miss);
}

TEST_P(ClientIntegrationTest, LargeResponse) {
initialize();
std::string data(1024 * 32, 'a');
Expand Down
Loading

0 comments on commit fcaea94

Please sign in to comment.