Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add API for specifying datagram channel strategies per DnsNameResolver #3607

Merged
merged 1 commit into from
Jan 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/modules/ROOT/pages/http-client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,8 @@ Default: 0.
| `completeOncePreferredResolved` | When this setting is enabled, the resolver notifies as soon as all queries for the preferred address type are complete.
When this setting is disabled, the resolver notifies when all possible address types are complete.
This configuration is applicable for `DnsNameResolver#resolveAll(String)`. By default, this setting is enabled.
| `datagramChannelStrategy` | Sets the strategy that is used to determine how a `DatagramChannel` is used by the resolver
for sending queries over UDP protocol. Default to {nettyjavadoc}/io/netty/resolver/dns/DnsNameResolverChannelStrategy.html#ChannelPerResolver[`DnsNameResolverChannelStrategy#ChannelPerResolver`]
| `disableOptionalRecord` | Disables the automatic inclusion of an optional record that tries to give a hint to the remote DNS server about
how much data the resolver can read per response. By default, this setting is enabled.
| `disableRecursionDesired` | Specifies whether this resolver has to send a DNS query with the recursion desired (RD) flag set.
Expand Down
2 changes: 2 additions & 0 deletions docs/modules/ROOT/pages/tcp-client.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -383,6 +383,8 @@ Additionally, https://tools.ietf.org/html/rfc7766[`TCP fallback`] is enabled by
| `completeOncePreferredResolved` | When this setting is enabled, the resolver notifies as soon as all queries for the preferred address type are complete.
When this setting is disabled, the resolver notifies when all possible address types are complete.
This configuration is applicable for `DnsNameResolver#resolveAll(String)`. By default, this setting is enabled.
| `datagramChannelStrategy` | Sets the strategy that is used to determine how a `DatagramChannel` is used by the resolver
for sending queries over UDP protocol. Default to {nettyjavadoc}/io/netty/resolver/dns/DnsNameResolverChannelStrategy.html#ChannelPerResolver[`DnsNameResolverChannelStrategy#ChannelPerResolver`]
| `disableOptionalRecord` | Disables the automatic inclusion of an optional record that tries to give a hint to the remote DNS server about
how much data the resolver can read per response. By default, this setting is enabled.
| `disableRecursionDesired` | Specifies whether this resolver has to send a DNS query with the recursion desired (RD) flag set.
Expand Down
3 changes: 2 additions & 1 deletion reactor-netty-core/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2024 VMware, Inc. or its affiliates, All Rights Reserved.
* Copyright (c) 2020-2025 VMware, Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -266,6 +266,7 @@ task japicmp(type: JapicmpTask) {
compatibilityChangeExcludes = [ "METHOD_NEW_DEFAULT" ]

methodExcludes = [
'reactor.netty.transport.NameResolverProvider$NameResolverSpec#datagramChannelStrategy(io.netty.resolver.dns.DnsNameResolverChannelStrategy)'
]

classExcludes = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import io.netty.resolver.dns.DnsCache;
import io.netty.resolver.dns.DnsNameResolver;
import io.netty.resolver.dns.DnsNameResolverBuilder;
import io.netty.resolver.dns.DnsNameResolverChannelStrategy;
import io.netty.resolver.dns.DnsQueryLifecycleObserverFactory;
import io.netty.resolver.dns.LoggingDnsQueryLifeCycleObserverFactory;
import io.netty.resolver.dns.RoundRobinDnsAddressResolverGroup;
Expand Down Expand Up @@ -115,6 +116,17 @@ public interface NameResolverSpec {
*/
NameResolverSpec completeOncePreferredResolved(boolean enable);

/**
* Sets the strategy that is used to determine how a {@link DatagramChannel} is used by the resolver for sending
* queries over UDP protocol.
* Default to {@link DnsNameResolverChannelStrategy#ChannelPerResolver}
*
* @param datagramChannelStrategy the {@link DnsNameResolverChannelStrategy} to use when doing queries over UDP protocol
* @return {@code this}
* @since 1.2.3
*/
NameResolverSpec datagramChannelStrategy(DnsNameResolverChannelStrategy datagramChannelStrategy);

/**
* Disables the automatic inclusion of an optional record that tries to hint the remote DNS server about
* how much data the resolver can read per response. By default, this is enabled.
Expand Down Expand Up @@ -329,6 +341,17 @@ public Duration cacheNegativeTimeToLive() {
return cacheNegativeTimeToLive;
}

/**
* Returns the configured custom {@link DnsNameResolverChannelStrategy} or null.
*
* @return the configured custom {@link DnsNameResolverChannelStrategy} or null
* @since 1.2.3
*/
@Nullable
public DnsNameResolverChannelStrategy datagramChannelStrategy() {
return datagramChannelStrategy;
}

/**
* Returns the configured custom provider of {@link DnsAddressResolverGroup} or null.
*
Expand Down Expand Up @@ -500,6 +523,7 @@ public boolean equals(Object o) {
cacheMinTimeToLive.equals(that.cacheMinTimeToLive) &&
cacheNegativeTimeToLive.equals(that.cacheNegativeTimeToLive) &&
completeOncePreferredResolved == that.completeOncePreferredResolved &&
datagramChannelStrategy == that.datagramChannelStrategy &&
disableOptionalRecord == that.disableOptionalRecord &&
disableRecursionDesired == that.disableRecursionDesired &&
Objects.equals(dnsAddressResolverGroupProvider, that.dnsAddressResolverGroupProvider) &&
Expand All @@ -526,6 +550,7 @@ public int hashCode() {
result = 31 * result + Objects.hashCode(cacheMinTimeToLive);
result = 31 * result + Objects.hashCode(cacheNegativeTimeToLive);
result = 31 * result + Boolean.hashCode(completeOncePreferredResolved);
result = 31 * result + Objects.hashCode(datagramChannelStrategy);
result = 31 * result + Boolean.hashCode(disableOptionalRecord);
result = 31 * result + Boolean.hashCode(disableRecursionDesired);
result = 31 * result + Objects.hashCode(dnsAddressResolverGroupProvider);
Expand Down Expand Up @@ -573,6 +598,7 @@ public DnsAddressResolverGroup newNameResolverGroup(LoopResources defaultLoopRes
.ndots(ndots)
.queryTimeoutMillis(queryTimeout.toMillis())
.eventLoop(group.next())
.datagramChannelStrategy(datagramChannelStrategy)
.datagramChannelFactory(() -> loop.onChannel(DatagramChannel.class, group))
.socketChannelFactory(() -> loop.onChannel(SocketChannel.class, group), retryTcpOnTimeout);
if (bindAddressSupplier != null) {
Expand Down Expand Up @@ -606,6 +632,7 @@ public DnsAddressResolverGroup newNameResolverGroup(LoopResources defaultLoopRes
final Duration cacheMinTimeToLive;
final Duration cacheNegativeTimeToLive;
final boolean completeOncePreferredResolved;
final DnsNameResolverChannelStrategy datagramChannelStrategy;
final boolean disableOptionalRecord;
final boolean disableRecursionDesired;
final Function<DnsNameResolverBuilder, DnsAddressResolverGroup> dnsAddressResolverGroupProvider;
Expand All @@ -629,6 +656,7 @@ public DnsAddressResolverGroup newNameResolverGroup(LoopResources defaultLoopRes
this.cacheMinTimeToLive = build.cacheMinTimeToLive;
this.cacheNegativeTimeToLive = build.cacheNegativeTimeToLive;
this.completeOncePreferredResolved = build.completeOncePreferredResolved;
this.datagramChannelStrategy = build.datagramChannelStrategy;
this.disableOptionalRecord = build.disableOptionalRecord;
this.disableRecursionDesired = build.disableRecursionDesired;
this.dnsAddressResolverGroupProvider = build.dnsAddressResolverGroupProvider;
Expand All @@ -652,6 +680,7 @@ static final class Build implements NameResolverSpec {
static final Duration DEFAULT_CACHE_MIN_TIME_TO_LIVE = Duration.ofSeconds(0);
static final Duration DEFAULT_CACHE_NEGATIVE_TIME_TO_LIVE = Duration.ofSeconds(0);
static final boolean DEFAULT_COMPLETE_ONCE_PREFERRED_RESOLVED = true;
static final DnsNameResolverChannelStrategy DEFAULT_DATAGRAM_CHANNEL_STRATEGY = DnsNameResolverChannelStrategy.ChannelPerResolver;
static final int DEFAULT_MAX_PAYLOAD_SIZE = 4096;
static final int DEFAULT_MAX_QUERIES_PER_RESOLVE = 16;
static final int DEFAULT_NDOTS = -1;
Expand All @@ -662,6 +691,7 @@ static final class Build implements NameResolverSpec {
Duration cacheMinTimeToLive = DEFAULT_CACHE_MIN_TIME_TO_LIVE;
Duration cacheNegativeTimeToLive = DEFAULT_CACHE_NEGATIVE_TIME_TO_LIVE;
boolean completeOncePreferredResolved = DEFAULT_COMPLETE_ONCE_PREFERRED_RESOLVED;
DnsNameResolverChannelStrategy datagramChannelStrategy = DEFAULT_DATAGRAM_CHANNEL_STRATEGY;
boolean disableOptionalRecord;
boolean disableRecursionDesired;
Function<DnsNameResolverBuilder, DnsAddressResolverGroup> dnsAddressResolverGroupProvider;
Expand Down Expand Up @@ -711,6 +741,12 @@ public NameResolverSpec completeOncePreferredResolved(boolean enable) {
return this;
}

@Override
public NameResolverSpec datagramChannelStrategy(DnsNameResolverChannelStrategy datagramChannelStrategy) {
this.datagramChannelStrategy = Objects.requireNonNull(datagramChannelStrategy);
return this;
}

@Override
public NameResolverSpec disableOptionalRecord(boolean disable) {
this.disableOptionalRecord = disable;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2020-2024 VMware, Inc. or its affiliates, All Rights Reserved.
* Copyright (c) 2020-2025 VMware, Inc. or its affiliates, All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -23,6 +23,7 @@
import io.netty.resolver.dns.DnsCache;
import io.netty.resolver.dns.DnsCacheEntry;
import io.netty.resolver.dns.DnsNameResolverBuilder;
import io.netty.resolver.dns.DnsNameResolverChannelStrategy;
import io.netty.resolver.dns.DnsServerAddressStreamProviders;
import io.netty.resolver.dns.RoundRobinDnsAddressResolverGroup;
import io.netty.resolver.dns.macos.MacOSDnsServerAddressStreamProvider;
Expand All @@ -48,6 +49,7 @@
import static reactor.netty.transport.NameResolverProvider.Build.DEFAULT_CACHE_MAX_TIME_TO_LIVE;
import static reactor.netty.transport.NameResolverProvider.Build.DEFAULT_CACHE_MIN_TIME_TO_LIVE;
import static reactor.netty.transport.NameResolverProvider.Build.DEFAULT_CACHE_NEGATIVE_TIME_TO_LIVE;
import static reactor.netty.transport.NameResolverProvider.Build.DEFAULT_DATAGRAM_CHANNEL_STRATEGY;
import static reactor.netty.transport.NameResolverProvider.Build.DEFAULT_MAX_PAYLOAD_SIZE;
import static reactor.netty.transport.NameResolverProvider.Build.DEFAULT_MAX_QUERIES_PER_RESOLVE;
import static reactor.netty.transport.NameResolverProvider.Build.DEFAULT_NDOTS;
Expand Down Expand Up @@ -145,6 +147,20 @@ void completeOncePreferredResolved() {
assertThat(builder.build().isCompleteOncePreferredResolved()).isFalse();
}

@Test
void datagramChannelStrategy() {
assertThat(builder.build().datagramChannelStrategy()).isEqualTo(DEFAULT_DATAGRAM_CHANNEL_STRATEGY);

builder.datagramChannelStrategy(DnsNameResolverChannelStrategy.ChannelPerResolution);
assertThat(builder.build().datagramChannelStrategy()).isEqualTo(DnsNameResolverChannelStrategy.ChannelPerResolution);
}

@Test
void datagramChannelStrategyBadValues() {
assertThatExceptionOfType(NullPointerException.class)
.isThrownBy(() -> builder.cacheNegativeTimeToLive(null));
}

@Test
void disableOptionalRecord() {
assertThat(builder.build().isDisableOptionalRecord()).isFalse();
Expand Down