WIP DnsServer
This commit is contained in:
parent
5e729abb81
commit
4eae019189
|
@ -1,3 +1,18 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
@ -19,12 +34,16 @@ import io.netty.channel.epoll.EpollChannelOption;
|
|||
import io.netty.channel.epoll.EpollDatagramChannel;
|
||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||
import io.netty.channel.epoll.EpollServerSocketChannel;
|
||||
import io.netty.channel.kqueue.KQueueDatagramChannel;
|
||||
import io.netty.channel.kqueue.KQueueEventLoopGroup;
|
||||
import io.netty.channel.kqueue.KQueueServerSocketChannel;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.oio.OioEventLoopGroup;
|
||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||
import io.netty.channel.socket.oio.OioDatagramChannel;
|
||||
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
||||
import io.netty.channel.unix.UnixChannelOption;
|
||||
|
||||
/**
|
||||
* from: https://blog.cloudflare.com/how-the-consumer-product-safety-commission-is-inadvertently-behind-the-internets-largest-ddos-attacks/
|
||||
|
@ -56,6 +75,25 @@ class DnsServer extends Shutdownable {
|
|||
private final int udpPort;
|
||||
private final String hostName;
|
||||
|
||||
public static
|
||||
void main(String[] args) {
|
||||
DnsServer server = new DnsServer("localhost", 2053);
|
||||
// server.bind(false);
|
||||
server.bind();
|
||||
|
||||
|
||||
// DnsClient client = new DnsClient("localhost", 2053);
|
||||
// List<InetAddress> resolve = null;
|
||||
// try {
|
||||
// resolve = client.resolve("google.com");
|
||||
// } catch (UnknownHostException e) {
|
||||
// e.printStackTrace();
|
||||
// }
|
||||
// System.err.println("RESOLVED: " + resolve);
|
||||
// client.stop();
|
||||
// server.stop();
|
||||
}
|
||||
|
||||
|
||||
public
|
||||
DnsServer(String host, int port) {
|
||||
|
@ -87,6 +125,11 @@ class DnsServer extends Shutdownable {
|
|||
boss = new EpollEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||
worker = new EpollEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||
}
|
||||
else if (OS.isMacOsX()) {
|
||||
// KQueue network stack is MUCH faster (but only on macosx)
|
||||
boss = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||
worker = new KQueueEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||
}
|
||||
else {
|
||||
boss = new NioEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
||||
worker = new NioEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||
|
@ -109,6 +152,10 @@ class DnsServer extends Shutdownable {
|
|||
// JNI network stack is MUCH faster (but only on linux)
|
||||
tcpBootstrap.channel(EpollServerSocketChannel.class);
|
||||
}
|
||||
else if (OS.isMacOsX()) {
|
||||
// KQueue network stack is MUCH faster (but only on macosx)
|
||||
tcpBootstrap.channel(KQueueServerSocketChannel.class);
|
||||
}
|
||||
else {
|
||||
tcpBootstrap.channel(NioServerSocketChannel.class);
|
||||
}
|
||||
|
@ -122,7 +169,7 @@ class DnsServer extends Shutdownable {
|
|||
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
|
||||
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
||||
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(EndPoint.WRITE_BUFF_LOW, EndPoint.WRITE_BUFF_HIGH))
|
||||
.childHandler(new DnsServerHandler());
|
||||
.childHandler(new DnsServerHandler(logger));
|
||||
|
||||
// have to check options.host for null. we don't bind to 0.0.0.0, we bind to "null" to get the "any" address!
|
||||
if (hostName != null) {
|
||||
|
@ -147,6 +194,11 @@ class DnsServer extends Shutdownable {
|
|||
udpBootstrap.channel(EpollDatagramChannel.class)
|
||||
.option(EpollChannelOption.SO_REUSEPORT, true);
|
||||
}
|
||||
else if (OS.isMacOsX()) {
|
||||
// JNI network stack is MUCH faster (but only on macosx)
|
||||
udpBootstrap.channel(KQueueDatagramChannel.class)
|
||||
.option(UnixChannelOption.SO_REUSEPORT, true);
|
||||
}
|
||||
else {
|
||||
udpBootstrap.channel(NioDatagramChannel.class);
|
||||
}
|
||||
|
@ -157,7 +209,7 @@ class DnsServer extends Shutdownable {
|
|||
|
||||
// not binding to specific address, since it's driven by TCP, and that can be bound to a specific address
|
||||
.localAddress(udpPort) // if you bind to a specific interface, Linux will be unable to receive broadcast packets!
|
||||
.handler(new DnsServerHandler());
|
||||
.handler(new DnsServerHandler(logger));
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,6 +36,15 @@ class DnsEnvelope extends DnsMessage implements AddressedEnvelope<DnsEnvelope, I
|
|||
super();
|
||||
}
|
||||
|
||||
|
||||
public
|
||||
DnsEnvelope(final int id, final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) {
|
||||
super(id);
|
||||
|
||||
this.localAddress = localAddress;
|
||||
this.remoteAddress = remoteAddress;
|
||||
}
|
||||
|
||||
public
|
||||
DnsEnvelope(final ByteBuf buffer, final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IOException {
|
||||
super(buffer);
|
||||
|
|
|
@ -12,19 +12,11 @@ import dorkbox.network.dns.Compression;
|
|||
import dorkbox.network.dns.DnsInput;
|
||||
import dorkbox.network.dns.DnsOutput;
|
||||
import dorkbox.network.dns.Name;
|
||||
import dorkbox.network.dns.constants.DnsClass;
|
||||
import dorkbox.network.dns.constants.DnsOpCode;
|
||||
import dorkbox.network.dns.constants.DnsRecordType;
|
||||
import dorkbox.network.dns.constants.DnsSection;
|
||||
import dorkbox.network.dns.constants.Flags;
|
||||
import dorkbox.network.dns.constants.*;
|
||||
import dorkbox.network.dns.exceptions.WireParseException;
|
||||
import dorkbox.util.OS;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.util.AbstractReferenceCounted;
|
||||
import io.netty.util.ReferenceCounted;
|
||||
import io.netty.util.ResourceLeakDetector;
|
||||
import io.netty.util.ResourceLeakDetectorFactory;
|
||||
import io.netty.util.ResourceLeakTracker;
|
||||
import io.netty.util.*;
|
||||
|
||||
/**
|
||||
* A DNS DnsMessage. A message is the basic unit of communication between
|
||||
|
@ -658,7 +650,7 @@ class DnsMessage extends AbstractReferenceCounted implements Cloneable, Referenc
|
|||
return out.toByteArray();
|
||||
}
|
||||
|
||||
/* Returns true if the message could be rendered. */
|
||||
/** Returns true if the message could be rendered. */
|
||||
private
|
||||
boolean toWire(DnsOutput out, int maxLength) {
|
||||
if (maxLength < Header.LENGTH) {
|
||||
|
@ -749,7 +741,7 @@ class DnsMessage extends AbstractReferenceCounted implements Cloneable, Referenc
|
|||
return null;
|
||||
}
|
||||
|
||||
/* Returns the number of records not successfully rendered. */
|
||||
/** Returns the number of records not successfully rendered. */
|
||||
private
|
||||
int sectionToWire(DnsOutput out, int section, Compression c, int maxLength) {
|
||||
final Object records = sectionAt(section);
|
||||
|
@ -839,7 +831,6 @@ class DnsMessage extends AbstractReferenceCounted implements Cloneable, Referenc
|
|||
Object clone() {
|
||||
DnsMessage m = new DnsMessage();
|
||||
|
||||
|
||||
for (int i = 0; i < DnsSection.TOTAL_SECTION_COUNT; i++) {
|
||||
final Object records = sectionAt(i);
|
||||
if (records == null) {
|
||||
|
@ -864,6 +855,7 @@ class DnsMessage extends AbstractReferenceCounted implements Cloneable, Referenc
|
|||
/**
|
||||
* Converts the DnsMessage to a String.
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
String toString() {
|
||||
String NL = OS.LINE_SEPARATOR;
|
||||
|
@ -949,8 +941,7 @@ class DnsMessage extends AbstractReferenceCounted implements Cloneable, Referenc
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the message. Only valid if the message has been
|
||||
* converted to or from wire format.
|
||||
* Returns the size of the message. Only valid if the message has been converted to or from wire format.
|
||||
*/
|
||||
public
|
||||
int numBytes() {
|
||||
|
|
|
@ -43,5 +43,4 @@ class EmptyRecord extends DnsRecord {
|
|||
@Override
|
||||
void rdataFromString(Tokenizer st, Name origin) throws IOException {
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ class RRset implements Serializable {
|
|||
* rrs contains both normal and RRSIG records, with the RRSIG records
|
||||
* at the end.
|
||||
*/
|
||||
private List rrs;
|
||||
private List resourceRecords;
|
||||
private short nsigs;
|
||||
private short position;
|
||||
|
||||
|
@ -48,7 +48,7 @@ class RRset implements Serializable {
|
|||
*/
|
||||
public
|
||||
RRset() {
|
||||
rrs = new ArrayList(1);
|
||||
resourceRecords = new ArrayList(1);
|
||||
nsigs = 0;
|
||||
position = 0;
|
||||
}
|
||||
|
@ -57,14 +57,14 @@ class RRset implements Serializable {
|
|||
void safeAddRR(DnsRecord r) {
|
||||
if (!(r instanceof RRSIGRecord)) {
|
||||
if (nsigs == 0) {
|
||||
rrs.add(r);
|
||||
resourceRecords.add(r);
|
||||
}
|
||||
else {
|
||||
rrs.add(rrs.size() - nsigs, r);
|
||||
resourceRecords.add(resourceRecords.size() - nsigs, r);
|
||||
}
|
||||
}
|
||||
else {
|
||||
rrs.add(r);
|
||||
resourceRecords.add(r);
|
||||
nsigs++;
|
||||
}
|
||||
}
|
||||
|
@ -75,7 +75,7 @@ class RRset implements Serializable {
|
|||
public
|
||||
RRset(RRset rrset) {
|
||||
synchronized (rrset) {
|
||||
rrs = (List) ((ArrayList) rrset.rrs).clone();
|
||||
resourceRecords = (List) ((ArrayList) rrset.resourceRecords).clone();
|
||||
nsigs = rrset.nsigs;
|
||||
position = rrset.position;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ class RRset implements Serializable {
|
|||
*/
|
||||
public synchronized
|
||||
void addRR(DnsRecord r) {
|
||||
if (rrs.size() == 0) {
|
||||
if (resourceRecords.size() == 0) {
|
||||
safeAddRR(r);
|
||||
return;
|
||||
}
|
||||
|
@ -101,16 +101,16 @@ class RRset implements Serializable {
|
|||
r.setTTL(first.getTTL());
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < rrs.size(); i++) {
|
||||
DnsRecord tmp = (DnsRecord) rrs.get(i);
|
||||
for (int i = 0; i < resourceRecords.size(); i++) {
|
||||
DnsRecord tmp = (DnsRecord) resourceRecords.get(i);
|
||||
tmp = tmp.cloneRecord();
|
||||
tmp.setTTL(r.getTTL());
|
||||
rrs.set(i, tmp);
|
||||
resourceRecords.set(i, tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!rrs.contains(r)) {
|
||||
if (!resourceRecords.contains(r)) {
|
||||
safeAddRR(r);
|
||||
}
|
||||
}
|
||||
|
@ -122,10 +122,10 @@ class RRset implements Serializable {
|
|||
*/
|
||||
public synchronized
|
||||
DnsRecord first() {
|
||||
if (rrs.size() == 0) {
|
||||
if (resourceRecords.size() == 0) {
|
||||
throw new IllegalStateException("rrset is empty");
|
||||
}
|
||||
return (DnsRecord) rrs.get(0);
|
||||
return (DnsRecord) resourceRecords.get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -133,7 +133,7 @@ class RRset implements Serializable {
|
|||
*/
|
||||
public synchronized
|
||||
void deleteRR(DnsRecord r) {
|
||||
if (rrs.remove(r) && (r instanceof RRSIGRecord)) {
|
||||
if (resourceRecords.remove(r) && (r instanceof RRSIGRecord)) {
|
||||
nsigs--;
|
||||
}
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ class RRset implements Serializable {
|
|||
*/
|
||||
public synchronized
|
||||
void clear() {
|
||||
rrs.clear();
|
||||
resourceRecords.clear();
|
||||
position = 0;
|
||||
nsigs = 0;
|
||||
}
|
||||
|
@ -163,7 +163,7 @@ class RRset implements Serializable {
|
|||
Iterator iterator(boolean data, boolean cycle) {
|
||||
int size, start, total;
|
||||
|
||||
total = rrs.size();
|
||||
total = resourceRecords.size();
|
||||
|
||||
if (data) {
|
||||
size = total - nsigs;
|
||||
|
@ -192,13 +192,13 @@ class RRset implements Serializable {
|
|||
|
||||
List list = new ArrayList(size);
|
||||
if (data) {
|
||||
list.addAll(rrs.subList(start, size));
|
||||
list.addAll(resourceRecords.subList(start, size));
|
||||
if (start != 0) {
|
||||
list.addAll(rrs.subList(0, start));
|
||||
list.addAll(resourceRecords.subList(0, start));
|
||||
}
|
||||
}
|
||||
else {
|
||||
list.addAll(rrs.subList(start, total));
|
||||
list.addAll(resourceRecords.subList(start, total));
|
||||
}
|
||||
|
||||
return list.iterator();
|
||||
|
@ -226,15 +226,16 @@ class RRset implements Serializable {
|
|||
*/
|
||||
public synchronized
|
||||
int size() {
|
||||
return rrs.size() - nsigs;
|
||||
return resourceRecords.size() - nsigs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the RRset to a String
|
||||
*/
|
||||
@Override
|
||||
public
|
||||
String toString() {
|
||||
if (rrs.size() == 0) {
|
||||
if (resourceRecords.size() == 0) {
|
||||
return ("{empty}");
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
|
344
src/dorkbox/network/dns/serverHandlers/DnsDecisionHandler.java
Normal file
344
src/dorkbox/network/dns/serverHandlers/DnsDecisionHandler.java
Normal file
|
@ -0,0 +1,344 @@
|
|||
/*
|
||||
* 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;
|
||||
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.UnknownHostException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import dorkbox.network.dns.DnsEnvelope;
|
||||
import dorkbox.network.dns.Name;
|
||||
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.records.*;
|
||||
import dorkbox.util.collections.IntMap;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.util.ReferenceCountUtil;
|
||||
|
||||
public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
|
||||
|
||||
|
||||
private final Logger logger;
|
||||
private IntMap responses = new IntMap();
|
||||
// private final DnsClient dnsClient;
|
||||
private final InetAddress localHost;
|
||||
|
||||
public
|
||||
DnsDecisionHandler(final Logger logger) {
|
||||
this.logger = logger;
|
||||
|
||||
// dnsClient = new DnsClient();
|
||||
|
||||
InetAddress local;
|
||||
try {
|
||||
local = InetAddress.getLocalHost();
|
||||
} catch (UnknownHostException e) {
|
||||
e.printStackTrace();
|
||||
local = null;
|
||||
}
|
||||
|
||||
localHost = local;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void channelRead(ChannelHandlerContext context, Object message) throws Exception {
|
||||
onChannelRead(context, (DnsEnvelope) message);
|
||||
ReferenceCountUtil.release(message);
|
||||
}
|
||||
|
||||
public
|
||||
void onChannelRead(final ChannelHandlerContext context, final DnsEnvelope dnsMessage) {
|
||||
int opcode = dnsMessage.getHeader()
|
||||
.getOpcode();
|
||||
|
||||
switch (opcode) {
|
||||
case DnsOpCode.QUERY:
|
||||
onQuery(context, dnsMessage, dnsMessage.recipient());
|
||||
dnsMessage.release();
|
||||
return;
|
||||
|
||||
case DnsOpCode.IQUERY:
|
||||
onIQuery(context, dnsMessage, dnsMessage.recipient());
|
||||
dnsMessage.release();
|
||||
return;
|
||||
|
||||
case DnsOpCode.NOTIFY:
|
||||
onNotify(context, dnsMessage, dnsMessage.recipient());
|
||||
dnsMessage.release();
|
||||
return;
|
||||
|
||||
case DnsOpCode.STATUS:
|
||||
onStatus(context, dnsMessage, dnsMessage.recipient());
|
||||
dnsMessage.release();
|
||||
return;
|
||||
|
||||
case DnsOpCode.UPDATE:
|
||||
onUpdate(context, (Update) (DnsMessage) dnsMessage, dnsMessage.recipient());
|
||||
dnsMessage.release();
|
||||
return;
|
||||
|
||||
default:
|
||||
logger.error("Unknown DNS opcode {} from {}", opcode, context.channel().remoteAddress());
|
||||
dnsMessage.release();
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
DnsEnvelope dnsEnvelope = new DnsEnvelope(dnsQuestion.getHeader()
|
||||
.getID(),
|
||||
(InetSocketAddress) context.channel().localAddress(),
|
||||
recipient);
|
||||
|
||||
// dnsEnvelope.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 answerRecord = new ARecord(name, dnsRecord.getDClass(), 10, localHost);
|
||||
dnsEnvelope.addRecord(dnsRecord, DnsSection.QUESTION);
|
||||
dnsEnvelope.addRecord(answerRecord, DnsSection.ANSWER);
|
||||
|
||||
dnsEnvelope.getHeader().setRcode(DnsResponseCode.NOERROR);
|
||||
|
||||
System.err.println("write");
|
||||
}
|
||||
|
||||
// dnsEnvelope.retain();
|
||||
// NOTE: I suspect this must be a "client" that writes back. there are errors if not.
|
||||
context.channel()
|
||||
.writeAndFlush(dnsEnvelope);
|
||||
|
||||
|
||||
// out.add(new DatagramPacket(buf, recipient, null));
|
||||
|
||||
|
||||
|
||||
// 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");
|
||||
System.err.println(dnsQuestion);
|
||||
}
|
||||
|
||||
private
|
||||
void onNotify(final ChannelHandlerContext context, final DnsMessage dnsQuestion, final InetSocketAddress recipient) {
|
||||
System.err.println("DECISION HANDLER READ");
|
||||
System.err.println(dnsQuestion);
|
||||
}
|
||||
|
||||
private
|
||||
void onStatus(final ChannelHandlerContext context, final DnsMessage dnsQuestion, final InetSocketAddress recipient) {
|
||||
System.err.println("DECISION HANDLER READ");
|
||||
System.err.println(dnsQuestion);
|
||||
}
|
||||
|
||||
private
|
||||
void onUpdate(final ChannelHandlerContext context, final Update dnsUpdate, final InetSocketAddress recipient) {
|
||||
System.err.println("DECISION HANDLER READ");
|
||||
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("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("ClientHanler#exceptionCaught");
|
||||
logger.error(cause.getMessage(), cause);
|
||||
// e.getFuture()
|
||||
// .setFailure(t);
|
||||
ctx.channel().close();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,41 +1,53 @@
|
|||
package dorkbox.network.dns.serverHandlers;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
import dorkbox.network.dns.records.DnsMessage;
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import dorkbox.network.dns.DnsEnvelope;
|
||||
import dorkbox.network.dns.exceptions.WireParseException;
|
||||
import dorkbox.network.dns.records.Header;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||
|
||||
|
||||
public
|
||||
class DnsMessageDecoder extends MessageToMessageDecoder<DatagramPacket> {
|
||||
private final Logger logger;
|
||||
|
||||
DnsMessageDecoder(final Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
@Override
|
||||
public
|
||||
void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
|
||||
// Channel channel = context.channel();
|
||||
|
||||
System.err.println("POW! ");
|
||||
cause.printStackTrace();
|
||||
// this.logger.error("Unexpected exception while trying to send/receive data on Client remote (network) channel. ({})" +
|
||||
// System.getProperty("line.separator"), channel.remoteAddress(), cause);
|
||||
// if (channel.isOpen()) {
|
||||
// channel.close();
|
||||
// }
|
||||
void exceptionCaught(final ChannelHandlerContext context, final Throwable cause) throws Exception {
|
||||
logger.error("DnsMessageDecoder#exceptionCaught", cause);
|
||||
super.exceptionCaught(context, cause);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected
|
||||
void decode(ChannelHandlerContext ctx, DatagramPacket packet, List<Object> out) throws Exception {
|
||||
System.err.println("READING MESSAGE");
|
||||
void decode(ChannelHandlerContext context, DatagramPacket packet, List<Object> out) throws Exception {
|
||||
final ByteBuf buf = packet.content();
|
||||
|
||||
// Check that the response is long enough.
|
||||
if (buf.readableBytes() < Header.LENGTH) {
|
||||
throw new WireParseException("invalid DNS header - " + "too short");
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
DnsMessage dnsMessage = new DnsMessage(buf);
|
||||
dnsMessage.retain();
|
||||
out.add(dnsMessage);
|
||||
InetSocketAddress localAddress = packet.recipient();
|
||||
InetSocketAddress remoteAddress = packet.sender();
|
||||
|
||||
DnsEnvelope dnsEnvelope = new DnsEnvelope(buf, localAddress, remoteAddress);
|
||||
dnsEnvelope.retain();
|
||||
|
||||
|
||||
// send down the pipeline
|
||||
out.add(dnsEnvelope);
|
||||
success = true;
|
||||
} finally {
|
||||
if (!success) {
|
||||
|
|
|
@ -13,12 +13,13 @@ import io.netty.channel.ChannelPipeline;
|
|||
*/
|
||||
public
|
||||
class DnsServerHandler extends ChannelInboundHandlerAdapter {
|
||||
private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(DnsServerHandler.class);
|
||||
|
||||
protected final DnsMessageDecoder decoder = new DnsMessageDecoder();
|
||||
protected final DnsMessageDecoder decoder;
|
||||
private final Logger logger;
|
||||
|
||||
public
|
||||
DnsServerHandler() {
|
||||
DnsServerHandler(final Logger logger) {
|
||||
this.logger = logger;
|
||||
decoder = new DnsMessageDecoder(logger);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -30,7 +31,7 @@ class DnsServerHandler extends ChannelInboundHandlerAdapter {
|
|||
context.fireChannelRegistered();
|
||||
success = true;
|
||||
} catch (Throwable t) {
|
||||
LOG.error("Failed to initialize a channel. Closing: {}", context.channel(), t);
|
||||
logger.error("Failed to initialize a channel. Closing: {}", context.channel(), t);
|
||||
} finally {
|
||||
if (!success) {
|
||||
context.close();
|
||||
|
@ -52,7 +53,8 @@ class DnsServerHandler extends ChannelInboundHandlerAdapter {
|
|||
|
||||
// ENCODE (or downstream)
|
||||
/////////////////////////
|
||||
pipeline.addLast("fowarder", new ForwardingHandler());
|
||||
pipeline.addLast("dnsDecision", new DnsDecisionHandler(logger));
|
||||
pipeline.addLast("fowarder", new ForwardingHandler(logger));
|
||||
// pipeline.addLast("fowarder", new ForwardingHandler(this.config, this.clientChannelFactory));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,27 @@
|
|||
package dorkbox.network.dns.serverHandlers;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import dorkbox.network.dns.DnsEnvelope;
|
||||
import dorkbox.network.dns.DnsOutput;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
||||
import io.netty.channel.ChannelOutboundHandlerAdapter;
|
||||
import io.netty.channel.socket.DatagramPacket;
|
||||
import io.netty.handler.codec.MessageToByteEncoder;
|
||||
|
||||
public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
||||
public class ForwardingHandler extends MessageToByteEncoder<DnsEnvelope> {
|
||||
|
||||
static final Logger LOG = LoggerFactory.getLogger(ForwardingHandler.class);
|
||||
|
||||
private final int maxPayloadSize = 512;
|
||||
private final Logger logger;
|
||||
|
||||
public
|
||||
ForwardingHandler(final Logger logger) {
|
||||
this.logger = logger;
|
||||
}
|
||||
|
||||
// protected ServerConfiguration config;
|
||||
// protected ChannelFactory clientChannelFactory;
|
||||
|
@ -21,18 +33,27 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
|||
// this.clientChannelFactory = clientChannelFactory;
|
||||
// }
|
||||
|
||||
|
||||
@Override
|
||||
public
|
||||
void read(final ChannelHandlerContext ctx) throws Exception {
|
||||
System.err.println("FORWARD HANDLER READ");
|
||||
super.read(ctx);
|
||||
protected
|
||||
void encode(final ChannelHandlerContext context, final DnsEnvelope message, final ByteBuf out) throws Exception {
|
||||
System.err.println("FORWARD HANDLER ENCODE");
|
||||
|
||||
try {
|
||||
DnsOutput dnsOutput = new DnsOutput(out);
|
||||
message.toWire(dnsOutput);
|
||||
|
||||
context.channel()
|
||||
.writeAndFlush(new DatagramPacket(out, message.recipient(), null));
|
||||
// .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 {
|
||||
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
|
||||
// final DNSMessage original = DNSMessage.class.cast(e.getMessage());
|
||||
//
|
||||
// ClientBootstrap cb = new ClientBootstrap(this.clientChannelFactory);
|
||||
|
@ -40,13 +61,11 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
|||
// cb.setPipelineFactory(new ChannelPipelineFactory() {
|
||||
// @Override
|
||||
// public ChannelPipeline getPipeline() throws Exception {
|
||||
// return Channels.pipeline(new ClientHanler(original, e
|
||||
// .getChannel(), e.getRemoteAddress()));
|
||||
// return Channels.pipeline(new ClientHandler(original, e.getChannel(), e.getRemoteAddress()));
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// List<SocketAddress> newlist = new ArrayList<SocketAddress>(
|
||||
// this.config.getForwarders());
|
||||
// List<SocketAddress> newlist = new ArrayList<SocketAddress>(this.config.getForwarders());
|
||||
// sendRequest(e, original, cb, newlist);
|
||||
// }
|
||||
//
|
||||
|
@ -73,10 +92,8 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
|||
//
|
||||
// c.write(newone, sa).addListener(new ChannelFutureListener() {
|
||||
// @Override
|
||||
// public void operationComplete(ChannelFuture future)
|
||||
// throws Exception {
|
||||
// LOG.debug("request complete isSuccess : {}",
|
||||
// future.isSuccess());
|
||||
// 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);
|
||||
|
@ -98,9 +115,9 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
|||
|
||||
@Override
|
||||
public
|
||||
void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
|
||||
LOG.error("ForwardingHandler#exceptionCaught");
|
||||
LOG.error(cause.getMessage(), cause);
|
||||
void exceptionCaught(final ChannelHandlerContext context, final Throwable cause) throws Exception {
|
||||
logger.error("ForwardingHandler#exceptionCaught", cause);
|
||||
super.exceptionCaught(context, cause);
|
||||
}
|
||||
|
||||
|
||||
|
@ -117,13 +134,6 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
|||
// this.originalChannel = c;
|
||||
// this.originalAddress = sa;
|
||||
// }
|
||||
//
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// @Override
|
||||
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
|
||||
// LOG.debug("ClientHanler#messageReceived");
|
||||
|
@ -147,8 +157,8 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
|||
@Override
|
||||
public
|
||||
void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
|
||||
LOG.error("ClientHanler#exceptionCaught");
|
||||
LOG.error(cause.getMessage(), cause);
|
||||
logger.error("ClientHandler#exceptionCaught");
|
||||
logger.error(cause.getMessage(), cause);
|
||||
// e.getFuture()
|
||||
// .setFailure(t);
|
||||
ctx.channel().close();
|
||||
|
|
|
@ -7,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;
|
||||
|
@ -24,7 +17,7 @@ import io.netty.util.internal.PlatformDependent;
|
|||
|
||||
@ChannelHandler.Sharable
|
||||
public
|
||||
class DNSMessageDecoder extends ChannelInboundHandlerAdapter {
|
||||
class aaaDNSMessageDecoderandForwarder extends ChannelInboundHandlerAdapter {
|
||||
|
||||
/**
|
||||
* This is what is called whenever a DNS packet is received. Currently only support UDP packets.
|
Loading…
Reference in New Issue
Block a user