134 lines
3.6 KiB
Java
Executable File
134 lines
3.6 KiB
Java
Executable File
package org.handwerkszeug.dns.aaaa;
|
|
|
|
import java.io.File;
|
|
import java.net.MalformedURLException;
|
|
import java.net.SocketAddress;
|
|
import java.net.URL;
|
|
import java.util.concurrent.ExecutorService;
|
|
import java.util.concurrent.Executors;
|
|
|
|
import org.handwerkszeug.dns.Markers;
|
|
import org.handwerkszeug.dns.conf.ServerConfiguration;
|
|
import org.handwerkszeug.dns.conf.ServerConfigurationImpl;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
import io.netty.channel.ChannelFactory;
|
|
import io.netty.channel.group.ChannelGroup;
|
|
import io.netty.channel.group.DefaultChannelGroup;
|
|
import werkzeugkasten.common.util.Disposable;
|
|
import werkzeugkasten.common.util.Initializable;
|
|
|
|
public class DNSServer implements Initializable, Disposable {
|
|
|
|
protected static Logger LOG = LoggerFactory.getLogger(DNSServer.class);
|
|
|
|
protected ServerConfiguration config;
|
|
protected ChannelFactory serverChannelFactory;
|
|
protected ChannelFactory clientChannelFactory;
|
|
protected ConnectionlessBootstrap bootstrap;
|
|
protected ChannelGroup group;
|
|
|
|
public static void main(String[] args) throws Exception {
|
|
ServerConfiguration conf = parseArgs(args);
|
|
final DNSServer server = new DNSServer(conf);
|
|
server.initialize();
|
|
Runtime.getRuntime().addShutdownHook(new Thread() {
|
|
@Override
|
|
public void run() {
|
|
server.dispose();
|
|
}
|
|
});
|
|
|
|
server.process();
|
|
}
|
|
|
|
public static ServerConfiguration parseArgs(String[] args) throws Exception {
|
|
ServerConfigurationImpl config = new ServerConfigurationImpl();
|
|
|
|
URL from = null;
|
|
if ((args != null) && (0 < args.length)) {
|
|
from = readFrom(args[0]);
|
|
}
|
|
|
|
if (from == null) {
|
|
from = readFrom("named.yml");
|
|
}
|
|
|
|
if (from == null) {
|
|
LOG.info("read named.default.yml from ClassLoader");
|
|
ClassLoader cl = Thread.currentThread().getContextClassLoader();
|
|
from = cl.getResource("named.default.yml");
|
|
}
|
|
|
|
if (from == null) {
|
|
throw new IllegalStateException("configuration file is not found.");
|
|
}
|
|
config.load(from);
|
|
return config;
|
|
}
|
|
|
|
public static URL readFrom(String path) throws MalformedURLException {
|
|
File f = new File(path);
|
|
LOG.info("read from {}", f.getAbsolutePath());
|
|
if (f.exists()) {
|
|
if (f.canRead()) {
|
|
return f.toURI().toURL();
|
|
} else {
|
|
LOG.info("{} cannot read", f.getAbsolutePath());
|
|
}
|
|
} else {
|
|
LOG.info("{} is not exists", f.getAbsolutePath());
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public DNSServer(ServerConfiguration config) {
|
|
this.config = config;
|
|
}
|
|
|
|
@Override
|
|
public void initialize() {
|
|
LOG.debug(Markers.LIFECYCLE, "initialize server");
|
|
ExecutorService executor = Executors.newFixedThreadPool(this.config.getThreadPoolSize());
|
|
|
|
// TODO need TCP?
|
|
this.clientChannelFactory = new NioDatagramChannelFactory(executor);
|
|
|
|
// TODO TCP and/or UDP
|
|
this.serverChannelFactory = new NioDatagramChannelFactory(executor);
|
|
|
|
ChannelPipelineFactory pipelineFactory = new DNSServerPipelineFactory(this.config, this.clientChannelFactory);
|
|
|
|
this.bootstrap = new ConnectionlessBootstrap(this.serverChannelFactory);
|
|
this.bootstrap.setPipelineFactory(pipelineFactory);
|
|
|
|
this.group = new DefaultChannelGroup();
|
|
}
|
|
|
|
public void process() {
|
|
for (SocketAddress sa : this.config.getBindingHosts()) {
|
|
LOG.info(Markers.BOUNDARY, "binding {}", sa);
|
|
this.group.add(this.bootstrap.bind(sa));
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void dispose() {
|
|
try {
|
|
this.group.close().awaitUninterruptibly();
|
|
} finally {
|
|
dispose(this.clientChannelFactory);
|
|
dispose(this.serverChannelFactory);
|
|
}
|
|
}
|
|
|
|
protected void dispose(ExternalResourceReleasable releasable) {
|
|
try {
|
|
releasable.releaseExternalResources();
|
|
} catch (Exception e) {
|
|
LOG.error(e.getLocalizedMessage(), e);
|
|
}
|
|
}
|
|
}
|