Added forwarding + caching for queries
This commit is contained in:
parent
cb4eb7fce4
commit
49a8743c4e
|
@ -1,19 +1,4 @@
|
|||
/*
|
||||
* Copyright 2018 dorkbox, llc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.network.dns.serverHandlers.wip;
|
||||
package org.handwerkszeug.dns.server;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
|
@ -22,14 +7,7 @@ import dorkbox.util.NamedThreadFactory;
|
|||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.PooledByteBufAllocator;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandler;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandler;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.ChannelPipeline;
|
||||
import io.netty.channel.EventLoopGroup;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.oio.OioEventLoopGroup;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
|
@ -39,11 +17,11 @@ import io.netty.util.internal.PlatformDependent;
|
|||
|
||||
@ChannelHandler.Sharable
|
||||
public
|
||||
class aaaDNSMessageDecoderandForwarder extends ChannelInboundHandlerAdapter {
|
||||
class DNSMessageDecoder extends ChannelInboundHandlerAdapter {
|
||||
|
||||
/**
|
||||
* This is what is called whenever a DNS packet is received. Currently only support UDP packets.
|
||||
*
|
||||
* <p>
|
||||
* Calls {@link ChannelHandlerContext#fireChannelRead(Object)} to forward
|
||||
* to the next {@link ChannelInboundHandler} in the {@link ChannelPipeline}.
|
||||
* <p>
|
||||
|
@ -52,7 +30,7 @@ class aaaDNSMessageDecoderandForwarder extends ChannelInboundHandlerAdapter {
|
|||
@Override
|
||||
public
|
||||
void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
if (msg instanceof DatagramPacket) {
|
||||
if (msg instanceof io.netty.channel.socket.DatagramPacket) {
|
||||
ByteBuf content = ((DatagramPacket) msg).content();
|
||||
|
||||
if (content.readableBytes() == 0) {
|
||||
|
@ -70,8 +48,10 @@ class aaaDNSMessageDecoderandForwarder extends ChannelInboundHandlerAdapter {
|
|||
|
||||
// setup the thread group to easily ID what the following threads belong to (and their spawned threads...)
|
||||
SecurityManager s = System.getSecurityManager();
|
||||
ThreadGroup nettyGroup = new ThreadGroup(s != null ? s.getThreadGroup() : Thread.currentThread().getThreadGroup(),
|
||||
"DnsClient (Netty)");
|
||||
ThreadGroup nettyGroup = new ThreadGroup(s != null
|
||||
? s.getThreadGroup()
|
||||
: Thread.currentThread()
|
||||
.getThreadGroup(), "DnsClient (Netty)");
|
||||
|
||||
EventLoopGroup group;
|
||||
if (PlatformDependent.isAndroid()) {
|
||||
|
@ -124,10 +104,6 @@ class aaaDNSMessageDecoderandForwarder extends ChannelInboundHandlerAdapter {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//
|
||||
// ClientBootstrap cb = new ClientBootstrap(this.clientChannelFactory);
|
||||
// cb.setOption("broadcast", "false");
|
|
@ -672,6 +672,14 @@ class DnsClient extends Shutdownable {
|
|||
throw new UnknownHostException(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the DNS resolver used by the client. This is for more advanced functionality
|
||||
*/
|
||||
public
|
||||
DnsNameResolver getResolver() {
|
||||
return resolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves a specific hostname record, of the specified type (PTR, MX, TXT, etc) with the default timeout of 5 seconds
|
||||
* <p/>
|
||||
|
|
|
@ -15,13 +15,14 @@
|
|||
*/
|
||||
package dorkbox.network;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import dorkbox.network.connection.EndPoint;
|
||||
import dorkbox.network.connection.Shutdownable;
|
||||
import dorkbox.network.dns.DnsQuestion;
|
||||
import dorkbox.network.dns.Name;
|
||||
import dorkbox.network.dns.constants.DnsClass;
|
||||
import dorkbox.network.dns.constants.DnsRecordType;
|
||||
import dorkbox.network.dns.records.ARecord;
|
||||
import dorkbox.network.dns.serverHandlers.DnsServerHandler;
|
||||
|
@ -83,7 +84,7 @@ class DnsServer extends Shutdownable {
|
|||
void main(String[] args) {
|
||||
DnsServer server = new DnsServer("localhost", 2053);
|
||||
|
||||
server.aRecord("google.com", DnsClass.IN, 10, "127.0.0.1");
|
||||
// server.aRecord("google.com", DnsClass.IN, 10, "127.0.0.1");
|
||||
|
||||
// server.bind(false);
|
||||
server.bind();
|
||||
|
@ -219,6 +220,12 @@ class DnsServer extends Shutdownable {
|
|||
.handler(dnsServerHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
void stopExtraActions() {
|
||||
dnsServerHandler.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Binds the server to the configured, underlying protocols.
|
||||
* <p/>
|
||||
|
@ -324,12 +331,11 @@ class DnsServer extends Shutdownable {
|
|||
Name name = DnsQuestion.createName(domainName, DnsRecordType.A);
|
||||
|
||||
int length = ipAddresses.length;
|
||||
ARecord[] records = new ARecord[length];
|
||||
ArrayList<ARecord> records = new ArrayList<ARecord>(length);
|
||||
|
||||
for (int i = 0; i < length; i++) {
|
||||
byte[] address = NetUtil.createByteArrayFromIpAddressString(ipAddresses[i]);
|
||||
|
||||
records[i] = new ARecord(name, dClass, ttl, address);
|
||||
records.add(new ARecord(name, dClass, ttl, address));
|
||||
}
|
||||
|
||||
dnsServerHandler.addARecord(name, records);
|
||||
|
|
|
@ -33,11 +33,23 @@ import dorkbox.network.dns.DnsResponse;
|
|||
import dorkbox.network.dns.clientHandlers.DatagramDnsQueryEncoder;
|
||||
import dorkbox.network.dns.clientHandlers.DatagramDnsResponseDecoder;
|
||||
import dorkbox.network.dns.constants.DnsRecordType;
|
||||
import dorkbox.network.dns.resolver.addressProvider.*;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DefaultDnsServerAddressStreamProvider;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DnsServerAddressStream;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DnsServerAddressStreamProvider;
|
||||
import dorkbox.network.dns.resolver.addressProvider.DnsServerAddresses;
|
||||
import dorkbox.network.dns.resolver.addressProvider.UnixResolverDnsServerAddressStreamProvider;
|
||||
import dorkbox.network.dns.resolver.cache.DnsCache;
|
||||
import dorkbox.network.dns.resolver.cache.DnsCacheEntry;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFactory;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.channel.ChannelInitializer;
|
||||
import io.netty.channel.ChannelOption;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.EventLoop;
|
||||
import io.netty.channel.FixedRecvByteBufAllocator;
|
||||
import io.netty.channel.socket.DatagramChannel;
|
||||
import io.netty.channel.socket.InternetProtocolFamily;
|
||||
import io.netty.resolver.HostsFileEntriesResolver;
|
||||
|
@ -468,7 +480,7 @@ class DnsNameResolver extends InetNameResolver {
|
|||
}
|
||||
}
|
||||
|
||||
private
|
||||
public
|
||||
InetAddress resolveHostsFileEntry(String hostname) {
|
||||
if (hostsFileEntriesResolver == null) {
|
||||
return null;
|
||||
|
|
|
@ -15,10 +15,14 @@
|
|||
*/
|
||||
package dorkbox.network.dns.serverHandlers;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import dorkbox.network.DnsClient;
|
||||
import dorkbox.network.dns.DnsEnvelope;
|
||||
import dorkbox.network.dns.DnsServerResponse;
|
||||
import dorkbox.network.dns.Name;
|
||||
|
@ -26,32 +30,34 @@ import dorkbox.network.dns.constants.DnsOpCode;
|
|||
import dorkbox.network.dns.constants.DnsRecordType;
|
||||
import dorkbox.network.dns.constants.DnsResponseCode;
|
||||
import dorkbox.network.dns.constants.DnsSection;
|
||||
import dorkbox.network.dns.constants.Flags;
|
||||
import dorkbox.network.dns.records.ARecord;
|
||||
import dorkbox.network.dns.records.DnsMessage;
|
||||
import dorkbox.network.dns.records.DnsRecord;
|
||||
import dorkbox.network.dns.records.Header;
|
||||
import dorkbox.network.dns.records.Update;
|
||||
import dorkbox.util.collections.IntMap;
|
||||
import dorkbox.network.dns.resolver.DnsNameResolver;
|
||||
import dorkbox.util.collections.LockFreeHashMap;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.util.concurrent.Future;
|
||||
import io.netty.util.concurrent.FutureListener;
|
||||
|
||||
public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
|
||||
public
|
||||
class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
private final Logger logger;
|
||||
private final LockFreeHashMap<Name, ARecord[]> aRecordMap;
|
||||
|
||||
|
||||
|
||||
private IntMap responses = new IntMap();
|
||||
// private final DnsClient dnsClient;
|
||||
private final LockFreeHashMap<Name, ArrayList<ARecord>> aRecordMap;
|
||||
private final DnsClient dnsClient;
|
||||
|
||||
public
|
||||
DnsDecisionHandler(final Logger logger) {
|
||||
this.logger = logger;
|
||||
|
||||
// dnsClient = new DnsClient();
|
||||
aRecordMap = new LockFreeHashMap<Name, ARecord[]>();
|
||||
dnsClient = new DnsClient();
|
||||
dnsClient.start();
|
||||
|
||||
aRecordMap = new LockFreeHashMap<Name, ArrayList<ARecord>>();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -61,7 +67,7 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
|
|||
* @param aRecords the A records (can be multiple) to return for the requested domain name
|
||||
*/
|
||||
public
|
||||
void addARecord(final Name domainName, final ARecord[] aRecords) {
|
||||
void addARecord(final Name domainName, final ArrayList<ARecord> aRecords) {
|
||||
aRecordMap.put(domainName, aRecords);
|
||||
}
|
||||
|
||||
|
@ -71,6 +77,13 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
|
|||
onChannelRead(context, (DnsEnvelope) message);
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void exceptionCaught(final ChannelHandlerContext context, final Throwable cause) throws Exception {
|
||||
logger.error("DecisionHandler#exceptionCaught", cause);
|
||||
super.exceptionCaught(context, cause);
|
||||
}
|
||||
|
||||
private
|
||||
void onChannelRead(final ChannelHandlerContext context, final DnsEnvelope dnsMessage) {
|
||||
int opcode = dnsMessage.getHeader()
|
||||
|
@ -98,113 +111,13 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
|
|||
return;
|
||||
|
||||
default:
|
||||
logger.error("Unknown DNS opcode {} from {}", opcode, context.channel().remoteAddress());
|
||||
logger.error("Unknown DNS opcode {} from {}",
|
||||
opcode,
|
||||
context.channel()
|
||||
.remoteAddress());
|
||||
}
|
||||
}
|
||||
|
||||
private
|
||||
void onQuery(final ChannelHandlerContext context, final DnsMessage dnsQuestion, final InetSocketAddress recipient) {
|
||||
// either I have an answer, or I don't (and have to forward to another DNS server
|
||||
// it might be more that 1 question...
|
||||
Header header = dnsQuestion.getHeader();
|
||||
int count = header.getCount(DnsSection.QUESTION);
|
||||
|
||||
// we don't support more than 1 question at a time.
|
||||
if (count == 1) {
|
||||
DnsServerResponse dnsResponse = new DnsServerResponse(dnsQuestion,
|
||||
(InetSocketAddress) context.channel().localAddress(),
|
||||
recipient);
|
||||
|
||||
// dnsResponse.getHeader().setRcode(DnsResponseCode.NXDOMAIN);
|
||||
|
||||
DnsRecord[] sectionArray = dnsQuestion.getSectionArray(DnsSection.QUESTION);
|
||||
DnsRecord dnsRecord = sectionArray[0];
|
||||
Name name = dnsRecord.getName();
|
||||
long ttl = dnsRecord.getTTL();
|
||||
int type = dnsRecord.getType();
|
||||
|
||||
|
||||
// what type of record? A, AAAA, MX, PTR, etc?
|
||||
if (DnsRecordType.A == type) {
|
||||
ARecord[] records = aRecordMap.get(name);
|
||||
|
||||
if (records != null) {
|
||||
dnsResponse.addRecord(dnsRecord, DnsSection.QUESTION);
|
||||
dnsResponse.getHeader()
|
||||
.setRcode(DnsResponseCode.NOERROR);
|
||||
|
||||
|
||||
for (int i = 0; i < records.length; i++) {
|
||||
ARecord record = records[i];
|
||||
|
||||
dnsResponse.addRecord(record, DnsSection.ANSWER);
|
||||
logger.debug("Writing A record response: {}", record.getAddress());
|
||||
}
|
||||
|
||||
context.channel()
|
||||
.write(dnsResponse);
|
||||
|
||||
return;
|
||||
} else {
|
||||
logger.debug("Sending DNS query to the forwarder...");
|
||||
// have to send this on to the forwarder
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
|
||||
// DNSMessage msg = new DNSMessage(buffer);
|
||||
// msg.header().id(this.original.header().id());
|
||||
// ChannelBuffer newone = ChannelBuffers.buffer(buffer.capacity());
|
||||
// msg.write(newone);
|
||||
// newone.resetReaderIndex();
|
||||
// this.originalChannel.write(newone, this.originalAddress)
|
||||
// .addListener(new ChannelFutureListener() {
|
||||
// @Override
|
||||
// public void operationComplete(ChannelFuture future)
|
||||
// throws Exception {
|
||||
// e.getChannel().close();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// boolean success = false;
|
||||
// try {
|
||||
// DnsMessage dnsMessage = new DnsMessage(dnsQuestion.getHeader()
|
||||
// .getID());
|
||||
//
|
||||
// dnsMessage.getHeader()
|
||||
// .setRcode(DnsResponseCode.NOERROR);
|
||||
//
|
||||
// // what type of record? A, AAAA, MX, PTR, etc?
|
||||
//
|
||||
// DnsRecord[] sectionArray = dnsMessage.getSectionArray(DnsSection.ANSWER);
|
||||
//
|
||||
// // if (code == DnsResponseCode.NOERROR) {
|
||||
// // return response.getSectionArray(DnsSection.ANSWER);
|
||||
// // }
|
||||
// //
|
||||
// // DnsOutput dnsOutput = new DnsOutput(buf);
|
||||
// // query.toWire(dnsOutput);
|
||||
// success = true;
|
||||
// } finally {
|
||||
// if (!success) {
|
||||
// // buf.release();
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
DnsRecord[] sectionArray = dnsQuestion.getSectionArray(DnsSection.QUESTION);
|
||||
DnsRecord dnsRecord = sectionArray[0];
|
||||
|
||||
System.err.println(dnsRecord);
|
||||
}
|
||||
|
||||
private
|
||||
void onIQuery(final ChannelHandlerContext context, final DnsMessage dnsQuestion, final InetSocketAddress recipient) {
|
||||
System.err.println("DECISION HANDLER READ");
|
||||
|
@ -217,6 +130,137 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
|
|||
System.err.println(dnsQuestion);
|
||||
}
|
||||
|
||||
private
|
||||
void onQuery(final ChannelHandlerContext context, final DnsMessage dnsQuestion, final InetSocketAddress recipient) {
|
||||
// either I have an answer, or I don't (and have to forward to another DNS server
|
||||
// it might be more than 1 question...
|
||||
Header header = dnsQuestion.getHeader();
|
||||
int count = header.getCount(DnsSection.QUESTION);
|
||||
|
||||
// we don't support more than 1 question at a time.
|
||||
if (count == 1) {
|
||||
DnsRecord[] sectionArray = dnsQuestion.getSectionArray(DnsSection.QUESTION);
|
||||
final DnsRecord dnsRecord = sectionArray[0];
|
||||
final Name name = dnsRecord.getName();
|
||||
final long ttl = dnsRecord.getTTL();
|
||||
final int type = dnsRecord.getType();
|
||||
|
||||
|
||||
// what type of record? A, AAAA, MX, PTR, etc?
|
||||
if (DnsRecordType.A == type) {
|
||||
DnsNameResolver resolver = dnsClient.getResolver();
|
||||
|
||||
String domainName = name.toString(true);
|
||||
|
||||
// check to see if we have it in our local hosts file
|
||||
final InetAddress inetAddress = resolver.resolveHostsFileEntry(domainName);
|
||||
if (inetAddress != null) {
|
||||
DnsServerResponse dnsResponse = new DnsServerResponse(dnsQuestion,
|
||||
(InetSocketAddress) context.channel()
|
||||
.localAddress(),
|
||||
recipient);
|
||||
|
||||
Header responseHeader = dnsResponse.getHeader();
|
||||
responseHeader.setFlag(Flags.QR);
|
||||
responseHeader.setRcode(DnsResponseCode.NOERROR);
|
||||
|
||||
dnsResponse.addRecord(dnsRecord, DnsSection.QUESTION);
|
||||
|
||||
ARecord aRecord = new ARecord(name, dnsRecord.getDClass(), ttl, inetAddress);
|
||||
dnsResponse.addRecord(aRecord, DnsSection.ANSWER);
|
||||
|
||||
context.channel()
|
||||
.write(dnsResponse);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// check our local cache
|
||||
ArrayList<ARecord> records = aRecordMap.get(name);
|
||||
if (records != null) {
|
||||
DnsServerResponse dnsResponse = new DnsServerResponse(dnsQuestion,
|
||||
(InetSocketAddress) context.channel()
|
||||
.localAddress(),
|
||||
recipient);
|
||||
|
||||
Header responseHeader = dnsResponse.getHeader();
|
||||
responseHeader.setFlag(Flags.QR);
|
||||
responseHeader.setRcode(DnsResponseCode.NOERROR);
|
||||
|
||||
dnsResponse.addRecord(dnsRecord, DnsSection.QUESTION);
|
||||
|
||||
for (ARecord record : records) {
|
||||
dnsResponse.addRecord(record, DnsSection.ANSWER);
|
||||
logger.debug("Writing A record response: {}", record.getAddress());
|
||||
}
|
||||
|
||||
context.channel()
|
||||
.write(dnsResponse);
|
||||
|
||||
return;
|
||||
}
|
||||
else {
|
||||
// have to send this on to the forwarder
|
||||
logger.debug("Sending DNS query to the forwarder...");
|
||||
|
||||
|
||||
// use "resolve", since it handles A/AAAA records + redirects correctly
|
||||
resolver.resolveAll(domainName)
|
||||
.addListener(new FutureListener<List<InetAddress>>() {
|
||||
@Override
|
||||
public
|
||||
void operationComplete(final Future<List<InetAddress>> future) throws Exception {
|
||||
List<InetAddress> resolvedAddresses = future.getNow();
|
||||
|
||||
DnsServerResponse dnsResponse = new DnsServerResponse(dnsQuestion,
|
||||
(InetSocketAddress) context.channel()
|
||||
.localAddress(),
|
||||
recipient);
|
||||
|
||||
Header responseHeader = dnsResponse.getHeader();
|
||||
responseHeader.setFlag(Flags.QR);
|
||||
|
||||
dnsResponse.addRecord(dnsRecord, DnsSection.QUESTION);
|
||||
|
||||
if (resolvedAddresses == null || resolvedAddresses.isEmpty()) {
|
||||
responseHeader.setRcode(DnsResponseCode.NXDOMAIN);
|
||||
}
|
||||
else {
|
||||
responseHeader.setRcode(DnsResponseCode.NOERROR);
|
||||
|
||||
ArrayList<ARecord> records = new ArrayList<ARecord>();
|
||||
|
||||
for (int i = 0; i < resolvedAddresses.size(); i++) {
|
||||
final InetAddress resolvedAddress = resolvedAddresses.get(i);
|
||||
|
||||
ARecord record = new ARecord(name, dnsRecord.getDClass(), ttl, resolvedAddress);
|
||||
records.add(record);
|
||||
dnsResponse.addRecord(record, DnsSection.ANSWER);
|
||||
}
|
||||
|
||||
|
||||
// we got here because there were no cached records in our record map -- so we save them!
|
||||
// duplicates are not an issue because they will always be the same answer
|
||||
aRecordMap.put(name, records);
|
||||
}
|
||||
|
||||
context.channel()
|
||||
.write(dnsResponse);
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
DnsRecord[] sectionArray = dnsQuestion.getSectionArray(DnsSection.QUESTION);
|
||||
DnsRecord dnsRecord = sectionArray[0];
|
||||
|
||||
System.err.println(dnsRecord);
|
||||
}
|
||||
|
||||
private
|
||||
void onStatus(final ChannelHandlerContext context, final DnsMessage dnsQuestion, final InetSocketAddress recipient) {
|
||||
System.err.println("DECISION HANDLER READ");
|
||||
|
@ -229,125 +273,8 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
|
|||
System.err.println(dnsUpdate);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// @Override
|
||||
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
|
||||
// final DNSMessage original = DNSMessage.class.cast(e.getMessage());
|
||||
//
|
||||
// ClientBootstrap cb = new ClientBootstrap(this.clientChannelFactory);
|
||||
// cb.setOption("broadcast", "false");
|
||||
// cb.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
// @Override
|
||||
// public ChannelPipeline getPipeline() throws Exception {
|
||||
// return Channels.pipeline(new ClientHanler(original, e
|
||||
// .getChannel(), e.getRemoteAddress()));
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// List<SocketAddress> newlist = new ArrayList<SocketAddress>(this.config.getForwarders());
|
||||
// sendRequest(e, original, cb, newlist);
|
||||
// }
|
||||
//
|
||||
// protected void sendRequest(final MessageEvent e, final DNSMessage original, final ClientBootstrap bootstrap, final List<SocketAddress> forwarders) {
|
||||
// if (0 < forwarders.size()) {
|
||||
// SocketAddress sa = forwarders.remove(0);
|
||||
// LOG.debug("send to {}", sa);
|
||||
//
|
||||
// ChannelFuture f = bootstrap.connect(sa);
|
||||
// ChannelBuffer newone = ChannelBuffers.buffer(512);
|
||||
// DNSMessage msg = new DNSMessage(original);
|
||||
// msg.write(newone);
|
||||
// newone.resetReaderIndex();
|
||||
// final Channel c = f.getChannel();
|
||||
//
|
||||
// if (LOG.isDebugEnabled()) {
|
||||
// LOG.debug(
|
||||
// "STATUS : [isOpen/isConnected/isWritable {}] {} {}",
|
||||
// new Object[] {
|
||||
// new boolean[] { c.isOpen(), c.isConnected(),
|
||||
// c.isWritable() }, c.getRemoteAddress(),
|
||||
// c.getClass() });
|
||||
// }
|
||||
//
|
||||
// c.write(newone, sa).addListener(new ChannelFutureListener() {
|
||||
// @Override
|
||||
// public void operationComplete(ChannelFuture future)
|
||||
// throws Exception {
|
||||
// LOG.debug("request complete isSuccess : {}",
|
||||
// future.isSuccess());
|
||||
// if (future.isSuccess() == false) {
|
||||
// if (0 < forwarders.size()) {
|
||||
// sendRequest(e, original, bootstrap, forwarders);
|
||||
// } else {
|
||||
// original.header().rcode(RCode.ServFail);
|
||||
// ChannelBuffer buffer = ChannelBuffers.buffer(512);
|
||||
// original.write(buffer);
|
||||
// // close inbound channel
|
||||
// e.getChannel().write(buffer)
|
||||
// .addListener(ChannelFutureListener.CLOSE);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // f.awaitUninterruptibly(30, TimeUnit.SECONDS);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public
|
||||
void exceptionCaught(final ChannelHandlerContext context, final Throwable cause) throws Exception {
|
||||
logger.error("DecisionHandler#exceptionCaught", cause);
|
||||
super.exceptionCaught(context, cause);
|
||||
void stop() {
|
||||
dnsClient.stop();
|
||||
}
|
||||
|
||||
|
||||
protected class ClientHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
// protected DNSMessage original;
|
||||
//
|
||||
// protected Channel originalChannel;
|
||||
//
|
||||
// protected SocketAddress originalAddress;
|
||||
//
|
||||
// public ClientHanler(DNSMessage msg, Channel c, SocketAddress sa) {
|
||||
// this.original = msg;
|
||||
// this.originalChannel = c;
|
||||
// this.originalAddress = sa;
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
|
||||
// LOG.debug("ClientHanler#messageReceived");
|
||||
// ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
|
||||
// DNSMessage msg = new DNSMessage(buffer);
|
||||
// msg.header().id(this.original.header().id());
|
||||
// ChannelBuffer newone = ChannelBuffers.buffer(buffer.capacity());
|
||||
// msg.write(newone);
|
||||
// newone.resetReaderIndex();
|
||||
// this.originalChannel.write(newone, this.originalAddress)
|
||||
// .addListener(new ChannelFutureListener() {
|
||||
// @Override
|
||||
// public void operationComplete(ChannelFuture future)
|
||||
// throws Exception {
|
||||
// e.getChannel().close();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
|
||||
@Override
|
||||
public
|
||||
void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
|
||||
logger.error("ClientHanler#exceptionCaught");
|
||||
logger.error(cause.getMessage(), cause);
|
||||
// e.getFuture()
|
||||
// .setFailure(t);
|
||||
ctx.channel().close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
package dorkbox.network.dns.serverHandlers;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import dorkbox.network.dns.Name;
|
||||
|
@ -29,6 +31,13 @@ class DnsServerHandler extends ChannelInboundHandlerAdapter {
|
|||
encoder = new DnsMessageEncoder(logger);
|
||||
}
|
||||
|
||||
|
||||
public
|
||||
void stop() {
|
||||
decisionHandler.stop();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a domain name query result, so clients that request the domain name will get the ipAddress
|
||||
*
|
||||
|
@ -36,7 +45,7 @@ class DnsServerHandler extends ChannelInboundHandlerAdapter {
|
|||
* @param @param aRecords the A records (can be multiple) to return for the requested domain name
|
||||
*/
|
||||
public
|
||||
void addARecord(final Name domainName, final ARecord[] aRecords) {
|
||||
void addARecord(final Name domainName, final ArrayList<ARecord> aRecords) {
|
||||
decisionHandler.addARecord(domainName, aRecords);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,56 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 dorkbox, llc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.network.dns.serverHandlers.wip;
|
||||
|
||||
import dorkbox.network.dns.DnsResponse;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
|
||||
public class DnsResponseHandler extends SimpleChannelInboundHandler<DnsResponse> {
|
||||
private Promise<Object> promise;
|
||||
|
||||
public DnsResponseHandler(Promise<Object> promise) {
|
||||
this.promise = promise;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, DnsResponse msg) throws Exception {
|
||||
System.err.println("YOP! " + msg);
|
||||
// DnsResponseCode errorCode = msg.header().responseCode();
|
||||
//
|
||||
// if (errorCode == DnsResponseCode.NOERROR) {
|
||||
// RecordDecoderFactory factory = RecordDecoderFactory.getFactory();
|
||||
//
|
||||
// List<DnsResource> resources = msg.answers();
|
||||
// List<Object> records = new ArrayList<>(resources.size());
|
||||
// for (DnsResource resource : resources) {
|
||||
// Object record = factory.decode(msg, resource);
|
||||
// records.add(record);
|
||||
// }
|
||||
// this.promise.setSuccess(records);
|
||||
// } else {
|
||||
// this.promise.setFailure(new DnsException(errorCode));
|
||||
// }
|
||||
// ctx.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
|
||||
this.promise.setFailure(cause);
|
||||
ctx.close();
|
||||
}
|
||||
}
|
|
@ -1,181 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 dorkbox, llc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.network.dns.serverHandlers.wip;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import dorkbox.network.dns.DnsEnvelope;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
|
||||
public class ForwardingHandler extends MessageToByteEncoder<DnsEnvelope> {
|
||||
|
||||
|
||||
private final int maxPayloadSize = 512;
|
||||
private final Logger logger;
|
||||
|
||||
public
|
||||
ForwardingHandler(final Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
// protected ServerConfiguration config;
|
||||
// protected ChannelFactory clientChannelFactory;
|
||||
|
||||
// public
|
||||
// ForwardingHandler(ServerConfiguration config,
|
||||
// ChannelFactory clientChannelFactory) {
|
||||
// this.config = config;
|
||||
// this.clientChannelFactory = clientChannelFactory;
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
protected
|
||||
void encode(final ChannelHandlerContext context, final DnsEnvelope message, final ByteBuf out) throws Exception {
|
||||
System.err.println("FORWARD HANDLER ENCODE");
|
||||
|
||||
// TODO: forward the message to ANOTHER dns server because we don't know what the awnser is
|
||||
|
||||
// try {
|
||||
// DnsOutput dnsOutput = new DnsOutput(out);
|
||||
// message.toWire(dnsOutput);
|
||||
//
|
||||
// //todo: need void promise
|
||||
// context.channel()
|
||||
// .writeAndFlush(new DatagramPacket(out, message.recipient(), message.sender()));
|
||||
// // .write(new DatagramPacket(out, message.recipient(), message.sender()));
|
||||
// } catch (Exception e) {
|
||||
// context.fireExceptionCaught(new IOException("Unable to write dns message: " + message, e));
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
// @Override
|
||||
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
|
||||
// final DNSMessage original = DNSMessage.class.cast(e.getMessage());
|
||||
//
|
||||
// ClientBootstrap cb = new ClientBootstrap(this.clientChannelFactory);
|
||||
// cb.setOption("broadcast", "false");
|
||||
// cb.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
// @Override
|
||||
// public ChannelPipeline getPipeline() throws Exception {
|
||||
// return Channels.pipeline(new ClientHandler(original, e.getChannel(), e.getRemoteAddress()));
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// List<SocketAddress> newlist = new ArrayList<SocketAddress>(this.config.getForwarders());
|
||||
// sendRequest(e, original, cb, newlist);
|
||||
// }
|
||||
//
|
||||
// protected void sendRequest(final MessageEvent e, final DNSMessage original, final ClientBootstrap bootstrap, final List<SocketAddress> forwarders) {
|
||||
// if (0 < forwarders.size()) {
|
||||
// SocketAddress sa = forwarders.remove(0);
|
||||
// LOG.debug("send to {}", sa);
|
||||
//
|
||||
// ChannelFuture f = bootstrap.connect(sa);
|
||||
// ChannelBuffer newone = ChannelBuffers.buffer(512);
|
||||
// DNSMessage msg = new DNSMessage(original);
|
||||
// msg.write(newone);
|
||||
// newone.resetReaderIndex();
|
||||
// final Channel c = f.getChannel();
|
||||
//
|
||||
// if (LOG.isDebugEnabled()) {
|
||||
// LOG.debug(
|
||||
// "STATUS : [isOpen/isConnected/isWritable {}] {} {}",
|
||||
// new Object[] {
|
||||
// new boolean[] { c.isOpen(), c.isConnected(),
|
||||
// c.isWritable() }, c.getRemoteAddress(),
|
||||
// c.getClass() });
|
||||
// }
|
||||
//
|
||||
// c.write(newone, sa).addListener(new ChannelFutureListener() {
|
||||
// @Override
|
||||
// public void operationComplete(ChannelFuture future) throws Exception {
|
||||
// LOG.debug("request complete isSuccess : {}", future.isSuccess());
|
||||
// if (future.isSuccess() == false) {
|
||||
// if (0 < forwarders.size()) {
|
||||
// sendRequest(e, original, bootstrap, forwarders);
|
||||
// } else {
|
||||
// original.header().rcode(RCode.ServFail);
|
||||
// ChannelBuffer buffer = ChannelBuffers.buffer(512);
|
||||
// original.write(buffer);
|
||||
// // close inbound channel
|
||||
// e.getChannel().write(buffer)
|
||||
// .addListener(ChannelFutureListener.CLOSE);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // f.awaitUninterruptibly(30, TimeUnit.SECONDS);
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public
|
||||
void exceptionCaught(final ChannelHandlerContext context, final Throwable cause) throws Exception {
|
||||
logger.error("ForwardingHandler#exceptionCaught", cause);
|
||||
super.exceptionCaught(context, cause);
|
||||
}
|
||||
|
||||
|
||||
protected class ClientHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
// protected DNSMessage original;
|
||||
//
|
||||
// protected Channel originalChannel;
|
||||
//
|
||||
// protected SocketAddress originalAddress;
|
||||
//
|
||||
// public ClientHanler(DNSMessage msg, Channel c, SocketAddress sa) {
|
||||
// this.original = msg;
|
||||
// this.originalChannel = c;
|
||||
// this.originalAddress = sa;
|
||||
// }
|
||||
// @Override
|
||||
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
|
||||
// LOG.debug("ClientHanler#messageReceived");
|
||||
// ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
|
||||
// DNSMessage msg = new DNSMessage(buffer);
|
||||
// msg.header().id(this.original.header().id());
|
||||
// ChannelBuffer newone = ChannelBuffers.buffer(buffer.capacity());
|
||||
// msg.write(newone);
|
||||
// newone.resetReaderIndex();
|
||||
// this.originalChannel.write(newone, this.originalAddress)
|
||||
// .addListener(new ChannelFutureListener() {
|
||||
// @Override
|
||||
// public void operationComplete(ChannelFuture future)
|
||||
// throws Exception {
|
||||
// e.getChannel().close();
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
|
||||
@Override
|
||||
public
|
||||
void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
|
||||
logger.error("ClientHandler#exceptionCaught");
|
||||
logger.error(cause.getMessage(), cause);
|
||||
// e.getFuture()
|
||||
// .setFailure(t);
|
||||
ctx.channel().close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Copyright 2018 dorkbox, llc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package dorkbox.network.dns.serverHandlers.wip;
|
||||
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelFutureListener;
|
||||
import io.netty.util.concurrent.Promise;
|
||||
|
||||
public class SuccessHandler implements ChannelFutureListener {
|
||||
private Promise<Object> promise;
|
||||
|
||||
public SuccessHandler(Promise<Object> promise) {
|
||||
this.promise = promise;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void operationComplete(ChannelFuture future) throws Exception {
|
||||
System.err.println("SUCCESS COMPLETE");
|
||||
if (future.isSuccess()) {
|
||||
future.channel().pipeline().addLast(new DnsResponseHandler(this.promise));
|
||||
} else {
|
||||
if (!future.isDone()) {
|
||||
this.promise.setFailure(future.cause());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user