Added forwarding + caching for queries

This commit is contained in:
nathan 2018-03-03 23:49:51 +01:00
parent cb4eb7fce4
commit 49a8743c4e
9 changed files with 214 additions and 553 deletions

View File

@ -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");

View File

@ -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/>

View File

@ -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);

View File

@ -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;

View File

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

View File

@ -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);
}

View File

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

View File

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

View File

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