/* * Copyright (c) 2011-2013 The original author or authors * ------------------------------------------------------ * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * and Apache License v2.0 which accompanies this distribution. * * The Eclipse Public License is available at * http://www.eclipse.org/legal/epl-v10.html * * The Apache License v2.0 is available at * http://www.opensource.org/licenses/apache2.0.php * * You may elect to redistribute this code under either of these licenses. */ package io.vertx.core.impl; import io.netty.resolver.AddressResolverGroup; import io.vertx.core.AsyncResult; import io.vertx.core.Future; import io.vertx.core.Handler; import io.vertx.core.Vertx; import io.vertx.core.dns.AddressResolverOptions; import io.vertx.core.impl.launcher.commands.ExecUtils; import io.vertx.core.spi.resolver.ResolverProvider; import java.io.File; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.file.Files; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * @author <a href="mailto:julien@julienviet.com">Julien Viet</a> */ public class AddressResolver { private static Pattern resolvOption(String regex) { return Pattern.compile("^[ \\t\\f]*options[^\n]+" + regex + "(?=$|\\s)", Pattern.MULTILINE); } private static final Pattern NDOTS_OPTIONS_PATTERN = resolvOption("ndots:[ \\t\\f]*(\\d)+"); private static final Pattern ROTATE_OPTIONS_PATTERN = resolvOption("rotate"); public static final int DEFAULT_NDOTS_RESOLV_OPTION; public static final boolean DEFAULT_ROTATE_RESOLV_OPTION; static { int ndots = 1; boolean rotate = false; if (ExecUtils.isLinux()) { File f = new File("/etc/resolv.conf"); if (f.exists() && f.isFile()) { try { String conf = new String(Files.readAllBytes(f.toPath())); int ndotsOption = parseNdotsOptionFromResolvConf(conf); if (ndotsOption != -1) { ndots = ndotsOption; } rotate = parseRotateOptionFromResolvConf(conf); } catch (Throwable ignore) { } } } DEFAULT_NDOTS_RESOLV_OPTION = ndots; DEFAULT_ROTATE_RESOLV_OPTION = rotate; } private final Vertx vertx; private final AddressResolverGroup<InetSocketAddress> resolverGroup; private final ResolverProvider provider; public AddressResolver(Vertx vertx, AddressResolverOptions options) { this.provider = ResolverProvider.factory(vertx, options); this.resolverGroup = provider.resolver(options); this.vertx = vertx; } public void resolveHostname(String hostname, Handler<AsyncResult<InetAddress>> resultHandler) { ContextInternal callback = (ContextInternal) vertx.getOrCreateContext(); io.netty.resolver.AddressResolver<InetSocketAddress> resolver = resolverGroup.getResolver(callback.nettyEventLoop()); io.netty.util.concurrent.Future<InetSocketAddress> fut = resolver.resolve(InetSocketAddress.createUnresolved(hostname, 0)); fut.addListener(a -> { callback.runOnContext(v -> { if (a.isSuccess()) { InetSocketAddress address = fut.getNow(); resultHandler.handle(Future.succeededFuture(address.getAddress())); } else { resultHandler.handle(Future.failedFuture(a.cause())); } }); }); } AddressResolverGroup<InetSocketAddress> nettyAddressResolverGroup() { return resolverGroup; } public void close(Handler<Void> doneHandler) { provider.close(doneHandler); } public static int parseNdotsOptionFromResolvConf(String s) { int ndots = -1; Matcher matcher = NDOTS_OPTIONS_PATTERN.matcher(s); while (matcher.find()) { ndots = Integer.parseInt(matcher.group(1)); } return ndots; } public static boolean parseRotateOptionFromResolvConf(String s) { Matcher matcher = ROTATE_OPTIONS_PATTERN.matcher(s); return matcher.find(); } }