/*
* 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();
}
}