package net.windwards.dnsfrontend;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.databind.ObjectMapper;
import net.sf.ehcache.CacheManager;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.config.CacheConfiguration;
import net.windwards.dnsfrontend.api.AbstractTaskKeeper;
import net.windwards.dnsfrontend.api.Configuration;
import net.windwards.dnsfrontend.api.ConfigurationException;
import net.windwards.dnsfrontend.frontend.ResolveTaskFactory;
import net.windwards.dnsfrontend.frontend.ResolverEngine;
import net.windwards.dnsfrontend.frontend.TaskKeeperImpl;
import net.windwards.dnsfrontend.frontend.UDPServer;
import net.windwards.options.Option;
import net.windwards.options.OptionParser;
import org.apache.log4j.ConsoleAppender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.PatternLayout;
import org.apache.log4j.WriterAppender;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.concurrent.LinkedBlockingQueue;
public class DNSFrontend {
@Option
protected File config = new File("./dns-frontend.conf");
@Option
protected File logfile = new File("./dns-frontend.log");
@Option
protected Short port = null;
@Option
protected boolean debug = false;
private UDPServer server;
private AbstractTaskKeeper keeper;
private ResolverEngine engine;
public Configuration loadConfiguration(Reader stream) throws IOException {
JsonFactory factory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(factory);
return mapper.readValue(stream, ConfigurationImpl.class);
}
protected void setupLogging() {
Logger root = Logger.getRootLogger();
WriterAppender appender;
if (this.debug) {
appender = new ConsoleAppender();
appender.setThreshold(Level.ALL);
} else {
FileAppender replacement = new FileAppender();
replacement.setFile(this.logfile.getAbsolutePath());
replacement.setAppend(true);
replacement.setThreshold(Level.INFO);
appender = replacement;
}
root.removeAllAppenders();
root.addAppender(appender);
appender.setName("dns-frontend");
appender.setLayout(new PatternLayout("%d %-5p %t [%c{1}] %m%n"));
appender.activateOptions();
}
protected Ehcache attachCache() {
CacheManager.getInstance().addCacheIfAbsent("da_cache");
Ehcache cache = CacheManager.getInstance().getCache("da_cache");
CacheConfiguration conf = cache.getCacheConfiguration();
conf.setTimeToLiveSeconds(30);
return cache;
}
public void setup(Configuration configuration) throws IOException, ConfigurationException {
configuration.initialize();
this.setupLogging();
Ehcache cache = this.attachCache();
LinkedBlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
this.engine = new ResolverEngine();
this.engine.setInboundQueue(queue);
this.keeper = new TaskKeeperImpl(cache);
if(configuration.getBackendTimeout() != 0)
this.keeper.setExpireTime(configuration.getBackendTimeout());
if(configuration.getNegativeExpiry() != 0)
this.keeper.setNegativeExpiry(configuration.getNegativeExpiry());
ResolveTaskFactory factory = new ResolveTaskFactory(cache, this.keeper, configuration);
this.keeper.setBackendRepository(factory);
this.server = new UDPServer(queue);
this.server.port = this.port != null ? this.port : configuration.getPort();
this.server.setResolveTaskFactory(factory);
}
public void start() {
this.keeper.start();
this.engine.start();
this.server.start();
}
public void stop() {
this.server.shutdown();
this.engine.stop();
this.keeper.stop();
}
public static void main(String... args) throws Exception {
DNSFrontend frontend = new DNSFrontend();
OptionParser<DNSFrontend> parser = new OptionParser<DNSFrontend>(frontend);
parser.parse(args);
Reader stream = new FileReader(frontend.config);
Configuration configuration = frontend.loadConfiguration(stream);
frontend.setup(configuration);
frontend.start();
}
}