1 /* 2 * Copyright 2015 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc.internal; 18 19 import com.google.common.base.Preconditions; 20 import com.google.common.base.Stopwatch; 21 import io.grpc.InternalServiceProviders; 22 import io.grpc.NameResolver; 23 import io.grpc.NameResolverProvider; 24 import java.net.InetSocketAddress; 25 import java.net.SocketAddress; 26 import java.net.URI; 27 import java.util.Collection; 28 import java.util.Collections; 29 30 /** 31 * A provider for {@link DnsNameResolver}. 32 * 33 * <p>It resolves a target URI whose scheme is {@code "dns"}. The (optional) authority of the target 34 * URI is reserved for the address of alternative DNS server (not implemented yet). The path of the 35 * target URI, excluding the leading slash {@code '/'}, is treated as the host name and the optional 36 * port to be resolved by DNS. Example target URIs: 37 * 38 * <ul> 39 * <li>{@code "dns:///foo.googleapis.com:8080"} (using default DNS)</li> 40 * <li>{@code "dns://8.8.8.8/foo.googleapis.com:8080"} (using alternative DNS (not implemented 41 * yet))</li> 42 * <li>{@code "dns:///foo.googleapis.com"} (without port)</li> 43 * </ul> 44 */ 45 public final class DnsNameResolverProvider extends NameResolverProvider { 46 47 private static final String SCHEME = "dns"; 48 49 @Override newNameResolver(URI targetUri, NameResolver.Args args)50 public NameResolver newNameResolver(URI targetUri, NameResolver.Args args) { 51 if (SCHEME.equals(targetUri.getScheme())) { 52 String targetPath = Preconditions.checkNotNull(targetUri.getPath(), "targetPath"); 53 Preconditions.checkArgument(targetPath.startsWith("/"), 54 "the path component (%s) of the target (%s) must start with '/'", targetPath, targetUri); 55 String name = targetPath.substring(1); 56 return new RetryingNameResolver( 57 new DnsNameResolver( 58 targetUri.getAuthority(), 59 name, 60 args, 61 GrpcUtil.SHARED_CHANNEL_EXECUTOR, 62 Stopwatch.createUnstarted(), 63 InternalServiceProviders.isAndroid(getClass().getClassLoader())), 64 new BackoffPolicyRetryScheduler( 65 new ExponentialBackoffPolicy.Provider(), 66 args.getScheduledExecutorService(), 67 args.getSynchronizationContext()), 68 args.getSynchronizationContext()); 69 } else { 70 return null; 71 } 72 } 73 74 @Override getDefaultScheme()75 public String getDefaultScheme() { 76 return SCHEME; 77 } 78 79 @Override isAvailable()80 protected boolean isAvailable() { 81 return true; 82 } 83 84 @Override priority()85 public int priority() { 86 return 5; 87 } 88 89 @Override getProducedSocketAddressTypes()90 protected Collection<Class<? extends SocketAddress>> getProducedSocketAddressTypes() { 91 return Collections.singleton(InetSocketAddress.class); 92 } 93 } 94