public final class DohResolver extends java.lang.Object implements Resolver
Resolver
using e.g. OkHttp.
On Java 8, it uses HTTP/1.1, which is against the recommendation of RFC 8484 to use HTTP/2 and thus slower. On Java 11 or newer, HTTP/2 is always used, but the built-in HttpClient has its own issues with connection handling.
As of 2020-09-13, the following limits of public resolvers for HTTP/2 were observed:
Modifier and Type | Class and Description |
---|---|
private static class |
DohResolver.SendAndGetMessageBytesResponse |
Modifier and Type | Field and Description |
---|---|
private static java.lang.String |
APPLICATION_DNS_MESSAGE |
private static java.lang.reflect.Method |
byteArrayBodyPublisherMethod |
private java.util.concurrent.Executor |
defaultExecutor |
private static java.lang.Object |
defaultHttpRequestBuilder |
private static java.lang.reflect.Method |
httpClientBuilderBuildMethod |
private static java.lang.reflect.Method |
httpClientBuilderExecutorMethod |
private static java.lang.reflect.Method |
httpClientBuilderTimeoutMethod |
private static java.lang.reflect.Method |
httpClientNewBuilderMethod |
private static java.util.Map<java.util.concurrent.Executor,java.lang.Object> |
httpClients |
private static java.lang.reflect.Method |
httpClientSendAsyncMethod |
private static java.lang.reflect.Method |
httpResponseBodyMethod |
private static java.lang.reflect.Method |
httpResponseStatusCodeMethod |
private java.time.Duration |
idleConnectionTimeout |
private AsyncSemaphore |
initialRequestLock |
private java.util.concurrent.atomic.AtomicLong |
lastRequest |
private AsyncSemaphore |
maxConcurrentRequests
Maximum concurrent HTTP/2 streams or HTTP/1.1 connections.
|
private static java.lang.reflect.Method |
publisherOfByteArrayMethod |
private OPTRecord |
queryOPT |
private static java.lang.reflect.Method |
requestBuilderBuildMethod |
private static java.lang.reflect.Method |
requestBuilderCopyMethod |
private static java.lang.reflect.Method |
requestBuilderPostMethod |
private static java.lang.reflect.Method |
requestBuilderTimeoutMethod |
private static java.lang.reflect.Method |
requestBuilderUriMethod |
private javax.net.ssl.SSLSocketFactory |
sslSocketFactory |
private java.time.Duration |
timeout |
private TSIG |
tsig |
private java.lang.String |
uriTemplate |
private static boolean |
USE_HTTP_CLIENT |
private boolean |
usePost |
Constructor and Description |
---|
DohResolver(java.lang.String uriTemplate)
Creates a new DoH resolver that performs lookups with HTTP GET and the default timeout (5s).
|
DohResolver(java.lang.String uriTemplate,
int maxConcurrentRequests,
java.time.Duration idleConnectionTimeout)
Creates a new DoH resolver that performs lookups with HTTP GET and the default timeout (5s).
|
Modifier and Type | Method and Description |
---|---|
private void |
discardStream(java.io.InputStream es) |
private <T> java.util.concurrent.CompletableFuture<T> |
failedFuture(java.lang.Throwable e) |
java.util.concurrent.Executor |
getExecutor()
Deprecated.
not applicable if
sendAsync(Message, Executor) is used. |
private java.lang.Object |
getHttpClient(java.util.concurrent.Executor executor) |
java.time.Duration |
getTimeout()
Gets the amount of time to wait for a response before giving up.
|
java.lang.String |
getUriTemplate()
Gets the current URI used for resolving.
|
private java.lang.String |
getUrl(byte[] queryBytes) |
boolean |
isUsePost()
Returns
true if the HTTP method POST to resolve, false if GET is used. |
private Message |
prepareQuery(Message query) |
private DohResolver.SendAndGetMessageBytesResponse |
sendAndGetMessageBytes(java.lang.String url,
byte[] queryBytes,
long startTime) |
java.util.concurrent.CompletionStage<Message> |
sendAsync(Message query)
Asynchronously sends a message using the default
ForkJoinPool.commonPool() . |
java.util.concurrent.CompletionStage<Message> |
sendAsync(Message query,
java.util.concurrent.Executor executor)
Asynchronously sends a message.
|
private java.util.concurrent.CompletionStage<Message> |
sendAsync11(Message query,
java.util.concurrent.Executor executor) |
private java.util.concurrent.CompletionStage<Message> |
sendAsync11WithConcurrentRequestPermit(Message query,
java.util.concurrent.Executor executor,
long startTime,
java.lang.Object requestBuilder,
AsyncSemaphore.Permit initialRequestPermit,
boolean isInitialRequest,
AsyncSemaphore.Permit maxConcurrentRequestPermit) |
private java.util.concurrent.CompletionStage<Message> |
sendAsync11WithInitialRequestPermit(Message query,
java.util.concurrent.Executor executor,
long startTime,
java.lang.Object requestBuilder,
AsyncSemaphore.Permit initialRequestPermit) |
private java.util.concurrent.CompletionStage<Message> |
sendAsync8(Message query,
java.util.concurrent.Executor executor) |
void |
setEDNS(int version,
int payloadSize,
int flags,
java.util.List<EDNSOption> options)
Sets the EDNS information on outgoing messages.
|
void |
setExecutor(java.util.concurrent.Executor executor)
Deprecated.
|
void |
setIgnoreTruncation(boolean flag)
Not implemented.
|
void |
setPort(int port)
Not implemented.
|
void |
setTCP(boolean flag)
Not implemented.
|
void |
setTimeout(java.time.Duration timeout)
Sets the amount of time to wait for a response before giving up.
|
void |
setTSIGKey(TSIG key)
Specifies the TSIG key that messages will be signed with
|
void |
setUriTemplate(java.lang.String uriTemplate)
Sets the URI to use for resolving, e.g.
|
void |
setUsePost(boolean usePost)
Sets the HTTP method to use for resolving.
|
private <T> java.util.concurrent.CompletableFuture<T> |
timeoutFailedFuture(Message query,
java.lang.Throwable inner) |
java.lang.String |
toString() |
private void |
verifyTSIG(Message query,
Message response,
byte[] b,
TSIG tsig) |
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
send, sendAsync, setEDNS, setEDNS, setTimeout, setTimeout
private static final boolean USE_HTTP_CLIENT
private static final java.util.Map<java.util.concurrent.Executor,java.lang.Object> httpClients
private final javax.net.ssl.SSLSocketFactory sslSocketFactory
private static java.lang.Object defaultHttpRequestBuilder
private static java.lang.reflect.Method publisherOfByteArrayMethod
private static java.lang.reflect.Method requestBuilderTimeoutMethod
private static java.lang.reflect.Method requestBuilderCopyMethod
private static java.lang.reflect.Method requestBuilderUriMethod
private static java.lang.reflect.Method requestBuilderBuildMethod
private static java.lang.reflect.Method requestBuilderPostMethod
private static java.lang.reflect.Method httpClientNewBuilderMethod
private static java.lang.reflect.Method httpClientBuilderTimeoutMethod
private static java.lang.reflect.Method httpClientBuilderExecutorMethod
private static java.lang.reflect.Method httpClientBuilderBuildMethod
private static java.lang.reflect.Method httpClientSendAsyncMethod
private static java.lang.reflect.Method byteArrayBodyPublisherMethod
private static java.lang.reflect.Method httpResponseBodyMethod
private static java.lang.reflect.Method httpResponseStatusCodeMethod
private boolean usePost
private java.time.Duration timeout
private java.lang.String uriTemplate
private final java.time.Duration idleConnectionTimeout
private OPTRecord queryOPT
private TSIG tsig
private java.util.concurrent.Executor defaultExecutor
private final AsyncSemaphore maxConcurrentRequests
rfc7540#section-6.5.2 recommends a minimum of 100 streams for HTTP/2.
private final java.util.concurrent.atomic.AtomicLong lastRequest
private final AsyncSemaphore initialRequestLock
private static final java.lang.String APPLICATION_DNS_MESSAGE
public DohResolver(java.lang.String uriTemplate)
uriTemplate
- the URI to use for resolving, e.g. https://dns.google/dns-query
public DohResolver(java.lang.String uriTemplate, int maxConcurrentRequests, java.time.Duration idleConnectionTimeout)
uriTemplate
- the URI to use for resolving, e.g. https://dns.google/dns-query
maxConcurrentRequests
- Maximum concurrent HTTP/2 streams for Java 11+ or HTTP/1.1
connections for Java 8. On Java 8 this cannot exceed the system property http.maxConnections
.idleConnectionTimeout
- Max. idle time for HTTP/2 connections until a request is
serialized. Applies to Java 11+ only.private java.lang.Object getHttpClient(java.util.concurrent.Executor executor)
public void setPort(int port)
setUriTemplate(String)
if required.public void setTCP(boolean flag)
public void setIgnoreTruncation(boolean flag)
setIgnoreTruncation
in interface Resolver
flag
- Indicates whether truncated responses should be ignored.public void setEDNS(int version, int payloadSize, int flags, java.util.List<EDNSOption> options)
public void setTSIGKey(TSIG key)
Resolver
setTSIGKey
in interface Resolver
key
- The keypublic void setTimeout(java.time.Duration timeout)
Resolver
setTimeout
in interface Resolver
timeout
- The amount of time to wait.public java.time.Duration getTimeout()
Resolver
getTimeout
in interface Resolver
Resolver.setTimeout(Duration)
public java.util.concurrent.CompletionStage<Message> sendAsync(Message query)
Resolver
ForkJoinPool.commonPool()
.
The default implementation calls the deprecated Resolver.sendAsync(Message,
ResolverListener)
. Implementors must override at least one of the sendAsync
methods or
a stack overflow will occur.
public java.util.concurrent.CompletionStage<Message> sendAsync(Message query, java.util.concurrent.Executor executor)
Resolver
The default implementation calls the deprecated Resolver.sendAsync(Message,
ResolverListener)
. Implementors must override at least one of the sendAsync
methods or
a stack overflow will occur.
private java.util.concurrent.CompletionStage<Message> sendAsync8(Message query, java.util.concurrent.Executor executor)
private DohResolver.SendAndGetMessageBytesResponse sendAndGetMessageBytes(java.lang.String url, byte[] queryBytes, long startTime) throws java.io.IOException
java.io.IOException
private void discardStream(java.io.InputStream es) throws java.io.IOException
java.io.IOException
private java.util.concurrent.CompletionStage<Message> sendAsync11(Message query, java.util.concurrent.Executor executor)
private java.util.concurrent.CompletionStage<Message> sendAsync11WithInitialRequestPermit(Message query, java.util.concurrent.Executor executor, long startTime, java.lang.Object requestBuilder, AsyncSemaphore.Permit initialRequestPermit)
private java.util.concurrent.CompletionStage<Message> sendAsync11WithConcurrentRequestPermit(Message query, java.util.concurrent.Executor executor, long startTime, java.lang.Object requestBuilder, AsyncSemaphore.Permit initialRequestPermit, boolean isInitialRequest, AsyncSemaphore.Permit maxConcurrentRequestPermit)
private <T> java.util.concurrent.CompletableFuture<T> failedFuture(java.lang.Throwable e)
private <T> java.util.concurrent.CompletableFuture<T> timeoutFailedFuture(Message query, java.lang.Throwable inner)
private java.lang.String getUrl(byte[] queryBytes)
public boolean isUsePost()
true
if the HTTP method POST to resolve, false
if GET is used.public void setUsePost(boolean usePost)
usePost
- true
to use POST, false
to use GET (the default).public java.lang.String getUriTemplate()
public void setUriTemplate(java.lang.String uriTemplate)
https://dns.google/dns-query
@Deprecated public java.util.concurrent.Executor getExecutor()
sendAsync(Message, Executor)
is used.Executor
for request handling, defaults to ForkJoinPool.commonPool()
.@Deprecated public void setExecutor(java.util.concurrent.Executor executor)
sendAsync(Message, Executor)
.Executor
for request handling.executor
- The new Executor
, can be null
(which is equivalent to ForkJoinPool.commonPool()
).public java.lang.String toString()
toString
in class java.lang.Object