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;
|
package dorkbox.network;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
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.EpollDatagramChannel;
|
||||||
import io.netty.channel.epoll.EpollEventLoopGroup;
|
import io.netty.channel.epoll.EpollEventLoopGroup;
|
||||||
import io.netty.channel.epoll.EpollServerSocketChannel;
|
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.nio.NioEventLoopGroup;
|
||||||
import io.netty.channel.oio.OioEventLoopGroup;
|
import io.netty.channel.oio.OioEventLoopGroup;
|
||||||
import io.netty.channel.socket.nio.NioDatagramChannel;
|
import io.netty.channel.socket.nio.NioDatagramChannel;
|
||||||
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
import io.netty.channel.socket.nio.NioServerSocketChannel;
|
||||||
import io.netty.channel.socket.oio.OioDatagramChannel;
|
import io.netty.channel.socket.oio.OioDatagramChannel;
|
||||||
import io.netty.channel.socket.oio.OioServerSocketChannel;
|
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/
|
* 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 int udpPort;
|
||||||
private final String hostName;
|
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
|
public
|
||||||
DnsServer(String host, int port) {
|
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));
|
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));
|
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 {
|
else {
|
||||||
boss = new NioEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName + "-boss", threadGroup));
|
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));
|
worker = new NioEventLoopGroup(EndPoint.DEFAULT_THREAD_POOL_SIZE, new NamedThreadFactory(threadName, threadGroup));
|
||||||
|
@ -101,63 +144,72 @@ class DnsServer extends Shutdownable {
|
||||||
udpBootstrap = new Bootstrap();
|
udpBootstrap = new Bootstrap();
|
||||||
|
|
||||||
|
|
||||||
if (OS.isAndroid()) {
|
if (OS.isAndroid()) {
|
||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
tcpBootstrap.channel(OioServerSocketChannel.class);
|
tcpBootstrap.channel(OioServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
tcpBootstrap.channel(EpollServerSocketChannel.class);
|
tcpBootstrap.channel(EpollServerSocketChannel.class);
|
||||||
}
|
}
|
||||||
else {
|
else if (OS.isMacOsX()) {
|
||||||
tcpBootstrap.channel(NioServerSocketChannel.class);
|
// KQueue network stack is MUCH faster (but only on macosx)
|
||||||
}
|
tcpBootstrap.channel(KQueueServerSocketChannel.class);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
tcpBootstrap.channel(NioServerSocketChannel.class);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: If we use netty for an HTTP server,
|
// TODO: If we use netty for an HTTP server,
|
||||||
// Beside the usual ChannelOptions the Native Transport allows to enable TCP_CORK which may come in handy if you implement a HTTP Server.
|
// Beside the usual ChannelOptions the Native Transport allows to enable TCP_CORK which may come in handy if you implement a HTTP Server.
|
||||||
|
|
||||||
tcpBootstrap.group(boss, worker)
|
tcpBootstrap.group(boss, worker)
|
||||||
.option(ChannelOption.SO_BACKLOG, backlogConnectionCount)
|
.option(ChannelOption.SO_BACKLOG, backlogConnectionCount)
|
||||||
.option(ChannelOption.SO_REUSEADDR, true)
|
.option(ChannelOption.SO_REUSEADDR, true)
|
||||||
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
|
.childOption(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
|
||||||
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
.childOption(ChannelOption.SO_KEEPALIVE, true)
|
||||||
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(EndPoint.WRITE_BUFF_LOW, EndPoint.WRITE_BUFF_HIGH))
|
.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!
|
// 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) {
|
if (hostName != null) {
|
||||||
tcpBootstrap.localAddress(hostName, tcpPort);
|
tcpBootstrap.localAddress(hostName, tcpPort);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
tcpBootstrap.localAddress(tcpPort);
|
tcpBootstrap.localAddress(tcpPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// android screws up on this!!
|
// android screws up on this!!
|
||||||
tcpBootstrap.option(ChannelOption.TCP_NODELAY, !OS.isAndroid())
|
tcpBootstrap.option(ChannelOption.TCP_NODELAY, !OS.isAndroid())
|
||||||
.childOption(ChannelOption.TCP_NODELAY, !OS.isAndroid());
|
.childOption(ChannelOption.TCP_NODELAY, !OS.isAndroid());
|
||||||
|
|
||||||
|
|
||||||
if (OS.isAndroid()) {
|
if (OS.isAndroid()) {
|
||||||
// android ONLY supports OIO (not NIO)
|
// android ONLY supports OIO (not NIO)
|
||||||
udpBootstrap.channel(OioDatagramChannel.class);
|
udpBootstrap.channel(OioDatagramChannel.class);
|
||||||
}
|
}
|
||||||
else if (OS.isLinux()) {
|
else if (OS.isLinux()) {
|
||||||
// JNI network stack is MUCH faster (but only on linux)
|
// JNI network stack is MUCH faster (but only on linux)
|
||||||
udpBootstrap.channel(EpollDatagramChannel.class)
|
udpBootstrap.channel(EpollDatagramChannel.class)
|
||||||
.option(EpollChannelOption.SO_REUSEPORT, true);
|
.option(EpollChannelOption.SO_REUSEPORT, true);
|
||||||
}
|
}
|
||||||
else {
|
else if (OS.isMacOsX()) {
|
||||||
udpBootstrap.channel(NioDatagramChannel.class);
|
// JNI network stack is MUCH faster (but only on macosx)
|
||||||
}
|
udpBootstrap.channel(KQueueDatagramChannel.class)
|
||||||
|
.option(UnixChannelOption.SO_REUSEPORT, true);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
udpBootstrap.channel(NioDatagramChannel.class);
|
||||||
|
}
|
||||||
|
|
||||||
udpBootstrap.group(worker)
|
udpBootstrap.group(worker)
|
||||||
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
|
.option(ChannelOption.ALLOCATOR, PooledByteBufAllocator.DEFAULT)
|
||||||
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(EndPoint.WRITE_BUFF_LOW, EndPoint.WRITE_BUFF_HIGH))
|
.option(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(EndPoint.WRITE_BUFF_LOW, EndPoint.WRITE_BUFF_HIGH))
|
||||||
|
|
||||||
// not binding to specific address, since it's driven by TCP, and that can be bound to a specific address
|
// 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!
|
.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();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public
|
||||||
|
DnsEnvelope(final int id, final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) {
|
||||||
|
super(id);
|
||||||
|
|
||||||
|
this.localAddress = localAddress;
|
||||||
|
this.remoteAddress = remoteAddress;
|
||||||
|
}
|
||||||
|
|
||||||
public
|
public
|
||||||
DnsEnvelope(final ByteBuf buffer, final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IOException {
|
DnsEnvelope(final ByteBuf buffer, final InetSocketAddress localAddress, final InetSocketAddress remoteAddress) throws IOException {
|
||||||
super(buffer);
|
super(buffer);
|
||||||
|
|
|
@ -12,19 +12,11 @@ import dorkbox.network.dns.Compression;
|
||||||
import dorkbox.network.dns.DnsInput;
|
import dorkbox.network.dns.DnsInput;
|
||||||
import dorkbox.network.dns.DnsOutput;
|
import dorkbox.network.dns.DnsOutput;
|
||||||
import dorkbox.network.dns.Name;
|
import dorkbox.network.dns.Name;
|
||||||
import dorkbox.network.dns.constants.DnsClass;
|
import dorkbox.network.dns.constants.*;
|
||||||
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.exceptions.WireParseException;
|
import dorkbox.network.dns.exceptions.WireParseException;
|
||||||
import dorkbox.util.OS;
|
import dorkbox.util.OS;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.util.AbstractReferenceCounted;
|
import io.netty.util.*;
|
||||||
import io.netty.util.ReferenceCounted;
|
|
||||||
import io.netty.util.ResourceLeakDetector;
|
|
||||||
import io.netty.util.ResourceLeakDetectorFactory;
|
|
||||||
import io.netty.util.ResourceLeakTracker;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A DNS DnsMessage. A message is the basic unit of communication between
|
* 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();
|
return out.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns true if the message could be rendered. */
|
/** Returns true if the message could be rendered. */
|
||||||
private
|
private
|
||||||
boolean toWire(DnsOutput out, int maxLength) {
|
boolean toWire(DnsOutput out, int maxLength) {
|
||||||
if (maxLength < Header.LENGTH) {
|
if (maxLength < Header.LENGTH) {
|
||||||
|
@ -749,7 +741,7 @@ class DnsMessage extends AbstractReferenceCounted implements Cloneable, Referenc
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Returns the number of records not successfully rendered. */
|
/** Returns the number of records not successfully rendered. */
|
||||||
private
|
private
|
||||||
int sectionToWire(DnsOutput out, int section, Compression c, int maxLength) {
|
int sectionToWire(DnsOutput out, int section, Compression c, int maxLength) {
|
||||||
final Object records = sectionAt(section);
|
final Object records = sectionAt(section);
|
||||||
|
@ -839,7 +831,6 @@ class DnsMessage extends AbstractReferenceCounted implements Cloneable, Referenc
|
||||||
Object clone() {
|
Object clone() {
|
||||||
DnsMessage m = new DnsMessage();
|
DnsMessage m = new DnsMessage();
|
||||||
|
|
||||||
|
|
||||||
for (int i = 0; i < DnsSection.TOTAL_SECTION_COUNT; i++) {
|
for (int i = 0; i < DnsSection.TOTAL_SECTION_COUNT; i++) {
|
||||||
final Object records = sectionAt(i);
|
final Object records = sectionAt(i);
|
||||||
if (records == null) {
|
if (records == null) {
|
||||||
|
@ -864,6 +855,7 @@ class DnsMessage extends AbstractReferenceCounted implements Cloneable, Referenc
|
||||||
/**
|
/**
|
||||||
* Converts the DnsMessage to a String.
|
* Converts the DnsMessage to a String.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public
|
public
|
||||||
String toString() {
|
String toString() {
|
||||||
String NL = OS.LINE_SEPARATOR;
|
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
|
* Returns the size of the message. Only valid if the message has been converted to or from wire format.
|
||||||
* converted to or from wire format.
|
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
int numBytes() {
|
int numBytes() {
|
||||||
|
|
|
@ -43,5 +43,4 @@ class EmptyRecord extends DnsRecord {
|
||||||
@Override
|
@Override
|
||||||
void rdataFromString(Tokenizer st, Name origin) throws IOException {
|
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
|
* rrs contains both normal and RRSIG records, with the RRSIG records
|
||||||
* at the end.
|
* at the end.
|
||||||
*/
|
*/
|
||||||
private List rrs;
|
private List resourceRecords;
|
||||||
private short nsigs;
|
private short nsigs;
|
||||||
private short position;
|
private short position;
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ class RRset implements Serializable {
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
RRset() {
|
RRset() {
|
||||||
rrs = new ArrayList(1);
|
resourceRecords = new ArrayList(1);
|
||||||
nsigs = 0;
|
nsigs = 0;
|
||||||
position = 0;
|
position = 0;
|
||||||
}
|
}
|
||||||
|
@ -57,14 +57,14 @@ class RRset implements Serializable {
|
||||||
void safeAddRR(DnsRecord r) {
|
void safeAddRR(DnsRecord r) {
|
||||||
if (!(r instanceof RRSIGRecord)) {
|
if (!(r instanceof RRSIGRecord)) {
|
||||||
if (nsigs == 0) {
|
if (nsigs == 0) {
|
||||||
rrs.add(r);
|
resourceRecords.add(r);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rrs.add(rrs.size() - nsigs, r);
|
resourceRecords.add(resourceRecords.size() - nsigs, r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rrs.add(r);
|
resourceRecords.add(r);
|
||||||
nsigs++;
|
nsigs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ class RRset implements Serializable {
|
||||||
public
|
public
|
||||||
RRset(RRset rrset) {
|
RRset(RRset rrset) {
|
||||||
synchronized (rrset) {
|
synchronized (rrset) {
|
||||||
rrs = (List) ((ArrayList) rrset.rrs).clone();
|
resourceRecords = (List) ((ArrayList) rrset.resourceRecords).clone();
|
||||||
nsigs = rrset.nsigs;
|
nsigs = rrset.nsigs;
|
||||||
position = rrset.position;
|
position = rrset.position;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ class RRset implements Serializable {
|
||||||
*/
|
*/
|
||||||
public synchronized
|
public synchronized
|
||||||
void addRR(DnsRecord r) {
|
void addRR(DnsRecord r) {
|
||||||
if (rrs.size() == 0) {
|
if (resourceRecords.size() == 0) {
|
||||||
safeAddRR(r);
|
safeAddRR(r);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -101,16 +101,16 @@ class RRset implements Serializable {
|
||||||
r.setTTL(first.getTTL());
|
r.setTTL(first.getTTL());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
for (int i = 0; i < rrs.size(); i++) {
|
for (int i = 0; i < resourceRecords.size(); i++) {
|
||||||
DnsRecord tmp = (DnsRecord) rrs.get(i);
|
DnsRecord tmp = (DnsRecord) resourceRecords.get(i);
|
||||||
tmp = tmp.cloneRecord();
|
tmp = tmp.cloneRecord();
|
||||||
tmp.setTTL(r.getTTL());
|
tmp.setTTL(r.getTTL());
|
||||||
rrs.set(i, tmp);
|
resourceRecords.set(i, tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rrs.contains(r)) {
|
if (!resourceRecords.contains(r)) {
|
||||||
safeAddRR(r);
|
safeAddRR(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -122,10 +122,10 @@ class RRset implements Serializable {
|
||||||
*/
|
*/
|
||||||
public synchronized
|
public synchronized
|
||||||
DnsRecord first() {
|
DnsRecord first() {
|
||||||
if (rrs.size() == 0) {
|
if (resourceRecords.size() == 0) {
|
||||||
throw new IllegalStateException("rrset is empty");
|
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
|
public synchronized
|
||||||
void deleteRR(DnsRecord r) {
|
void deleteRR(DnsRecord r) {
|
||||||
if (rrs.remove(r) && (r instanceof RRSIGRecord)) {
|
if (resourceRecords.remove(r) && (r instanceof RRSIGRecord)) {
|
||||||
nsigs--;
|
nsigs--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +143,7 @@ class RRset implements Serializable {
|
||||||
*/
|
*/
|
||||||
public synchronized
|
public synchronized
|
||||||
void clear() {
|
void clear() {
|
||||||
rrs.clear();
|
resourceRecords.clear();
|
||||||
position = 0;
|
position = 0;
|
||||||
nsigs = 0;
|
nsigs = 0;
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,7 @@ class RRset implements Serializable {
|
||||||
Iterator iterator(boolean data, boolean cycle) {
|
Iterator iterator(boolean data, boolean cycle) {
|
||||||
int size, start, total;
|
int size, start, total;
|
||||||
|
|
||||||
total = rrs.size();
|
total = resourceRecords.size();
|
||||||
|
|
||||||
if (data) {
|
if (data) {
|
||||||
size = total - nsigs;
|
size = total - nsigs;
|
||||||
|
@ -192,13 +192,13 @@ class RRset implements Serializable {
|
||||||
|
|
||||||
List list = new ArrayList(size);
|
List list = new ArrayList(size);
|
||||||
if (data) {
|
if (data) {
|
||||||
list.addAll(rrs.subList(start, size));
|
list.addAll(resourceRecords.subList(start, size));
|
||||||
if (start != 0) {
|
if (start != 0) {
|
||||||
list.addAll(rrs.subList(0, start));
|
list.addAll(resourceRecords.subList(0, start));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
list.addAll(rrs.subList(start, total));
|
list.addAll(resourceRecords.subList(start, total));
|
||||||
}
|
}
|
||||||
|
|
||||||
return list.iterator();
|
return list.iterator();
|
||||||
|
@ -226,15 +226,16 @@ class RRset implements Serializable {
|
||||||
*/
|
*/
|
||||||
public synchronized
|
public synchronized
|
||||||
int size() {
|
int size() {
|
||||||
return rrs.size() - nsigs;
|
return resourceRecords.size() - nsigs;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the RRset to a String
|
* Converts the RRset to a String
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public
|
public
|
||||||
String toString() {
|
String toString() {
|
||||||
if (rrs.size() == 0) {
|
if (resourceRecords.size() == 0) {
|
||||||
return ("{empty}");
|
return ("{empty}");
|
||||||
}
|
}
|
||||||
StringBuilder sb = new StringBuilder();
|
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,46 +1,58 @@
|
||||||
package dorkbox.network.dns.serverHandlers;
|
package dorkbox.network.dns.serverHandlers;
|
||||||
|
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.util.List;
|
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.buffer.ByteBuf;
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import io.netty.channel.socket.DatagramPacket;
|
import io.netty.channel.socket.DatagramPacket;
|
||||||
import io.netty.handler.codec.MessageToMessageDecoder;
|
import io.netty.handler.codec.MessageToMessageDecoder;
|
||||||
|
|
||||||
|
|
||||||
public
|
|
||||||
class DnsMessageDecoder extends MessageToMessageDecoder<DatagramPacket> {
|
class DnsMessageDecoder extends MessageToMessageDecoder<DatagramPacket> {
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
DnsMessageDecoder(final Logger logger) {
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void exceptionCaught(ChannelHandlerContext context, Throwable cause) throws Exception {
|
void exceptionCaught(final ChannelHandlerContext context, final Throwable cause) throws Exception {
|
||||||
// Channel channel = context.channel();
|
logger.error("DnsMessageDecoder#exceptionCaught", cause);
|
||||||
|
super.exceptionCaught(context, cause);
|
||||||
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();
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected
|
protected
|
||||||
void decode(ChannelHandlerContext ctx, DatagramPacket packet, List<Object> out) throws Exception {
|
void decode(ChannelHandlerContext context, DatagramPacket packet, List<Object> out) throws Exception {
|
||||||
System.err.println("READING MESSAGE");
|
|
||||||
final ByteBuf buf = packet.content();
|
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;
|
boolean success = false;
|
||||||
try {
|
try {
|
||||||
DnsMessage dnsMessage = new DnsMessage(buf);
|
InetSocketAddress localAddress = packet.recipient();
|
||||||
dnsMessage.retain();
|
InetSocketAddress remoteAddress = packet.sender();
|
||||||
out.add(dnsMessage);
|
|
||||||
|
DnsEnvelope dnsEnvelope = new DnsEnvelope(buf, localAddress, remoteAddress);
|
||||||
|
dnsEnvelope.retain();
|
||||||
|
|
||||||
|
|
||||||
|
// send down the pipeline
|
||||||
|
out.add(dnsEnvelope);
|
||||||
success = true;
|
success = true;
|
||||||
} finally {
|
} finally {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
buf.release();
|
buf.release();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,12 +13,13 @@ import io.netty.channel.ChannelPipeline;
|
||||||
*/
|
*/
|
||||||
public
|
public
|
||||||
class DnsServerHandler extends ChannelInboundHandlerAdapter {
|
class DnsServerHandler extends ChannelInboundHandlerAdapter {
|
||||||
private static final Logger LOG = org.slf4j.LoggerFactory.getLogger(DnsServerHandler.class);
|
protected final DnsMessageDecoder decoder;
|
||||||
|
private final Logger logger;
|
||||||
protected final DnsMessageDecoder decoder = new DnsMessageDecoder();
|
|
||||||
|
|
||||||
public
|
public
|
||||||
DnsServerHandler() {
|
DnsServerHandler(final Logger logger) {
|
||||||
|
this.logger = logger;
|
||||||
|
decoder = new DnsMessageDecoder(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -30,7 +31,7 @@ class DnsServerHandler extends ChannelInboundHandlerAdapter {
|
||||||
context.fireChannelRegistered();
|
context.fireChannelRegistered();
|
||||||
success = true;
|
success = true;
|
||||||
} catch (Throwable t) {
|
} 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 {
|
} finally {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
context.close();
|
context.close();
|
||||||
|
@ -52,7 +53,8 @@ class DnsServerHandler extends ChannelInboundHandlerAdapter {
|
||||||
|
|
||||||
// ENCODE (or downstream)
|
// 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));
|
// pipeline.addLast("fowarder", new ForwardingHandler(this.config, this.clientChannelFactory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,29 @@
|
||||||
package dorkbox.network.dns.serverHandlers;
|
package dorkbox.network.dns.serverHandlers;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import java.io.IOException;
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
|
|
||||||
|
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.ChannelHandlerContext;
|
||||||
import io.netty.channel.ChannelInboundHandlerAdapter;
|
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);
|
|
||||||
|
|
||||||
// protected ServerConfiguration config;
|
private final int maxPayloadSize = 512;
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
public
|
||||||
|
ForwardingHandler(final Logger logger) {
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
// protected ServerConfiguration config;
|
||||||
// protected ChannelFactory clientChannelFactory;
|
// protected ChannelFactory clientChannelFactory;
|
||||||
|
|
||||||
// public
|
// public
|
||||||
|
@ -21,18 +33,27 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
||||||
// this.clientChannelFactory = clientChannelFactory;
|
// this.clientChannelFactory = clientChannelFactory;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public
|
protected
|
||||||
void read(final ChannelHandlerContext ctx) throws Exception {
|
void encode(final ChannelHandlerContext context, final DnsEnvelope message, final ByteBuf out) throws Exception {
|
||||||
System.err.println("FORWARD HANDLER READ");
|
System.err.println("FORWARD HANDLER ENCODE");
|
||||||
super.read(ctx);
|
|
||||||
|
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
|
// @Override
|
||||||
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e)
|
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
|
||||||
// throws Exception {
|
|
||||||
// final DNSMessage original = DNSMessage.class.cast(e.getMessage());
|
// final DNSMessage original = DNSMessage.class.cast(e.getMessage());
|
||||||
//
|
//
|
||||||
// ClientBootstrap cb = new ClientBootstrap(this.clientChannelFactory);
|
// ClientBootstrap cb = new ClientBootstrap(this.clientChannelFactory);
|
||||||
|
@ -40,13 +61,11 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
||||||
// cb.setPipelineFactory(new ChannelPipelineFactory() {
|
// cb.setPipelineFactory(new ChannelPipelineFactory() {
|
||||||
// @Override
|
// @Override
|
||||||
// public ChannelPipeline getPipeline() throws Exception {
|
// public ChannelPipeline getPipeline() throws Exception {
|
||||||
// return Channels.pipeline(new ClientHanler(original, e
|
// return Channels.pipeline(new ClientHandler(original, e.getChannel(), e.getRemoteAddress()));
|
||||||
// .getChannel(), e.getRemoteAddress()));
|
|
||||||
// }
|
// }
|
||||||
// });
|
// });
|
||||||
//
|
//
|
||||||
// List<SocketAddress> newlist = new ArrayList<SocketAddress>(
|
// List<SocketAddress> newlist = new ArrayList<SocketAddress>(this.config.getForwarders());
|
||||||
// this.config.getForwarders());
|
|
||||||
// sendRequest(e, original, cb, newlist);
|
// sendRequest(e, original, cb, newlist);
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
@ -73,10 +92,8 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
||||||
//
|
//
|
||||||
// c.write(newone, sa).addListener(new ChannelFutureListener() {
|
// c.write(newone, sa).addListener(new ChannelFutureListener() {
|
||||||
// @Override
|
// @Override
|
||||||
// public void operationComplete(ChannelFuture future)
|
// public void operationComplete(ChannelFuture future) throws Exception {
|
||||||
// throws Exception {
|
// LOG.debug("request complete isSuccess : {}", future.isSuccess());
|
||||||
// LOG.debug("request complete isSuccess : {}",
|
|
||||||
// future.isSuccess());
|
|
||||||
// if (future.isSuccess() == false) {
|
// if (future.isSuccess() == false) {
|
||||||
// if (0 < forwarders.size()) {
|
// if (0 < forwarders.size()) {
|
||||||
// sendRequest(e, original, bootstrap, forwarders);
|
// sendRequest(e, original, bootstrap, forwarders);
|
||||||
|
@ -98,9 +115,9 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
|
void exceptionCaught(final ChannelHandlerContext context, final Throwable cause) throws Exception {
|
||||||
LOG.error("ForwardingHandler#exceptionCaught");
|
logger.error("ForwardingHandler#exceptionCaught", cause);
|
||||||
LOG.error(cause.getMessage(), cause);
|
super.exceptionCaught(context, cause);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -117,13 +134,6 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
||||||
// this.originalChannel = c;
|
// this.originalChannel = c;
|
||||||
// this.originalAddress = sa;
|
// this.originalAddress = sa;
|
||||||
// }
|
// }
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// @Override
|
// @Override
|
||||||
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
|
// public void messageReceived(ChannelHandlerContext ctx, final MessageEvent e) throws Exception {
|
||||||
// LOG.debug("ClientHanler#messageReceived");
|
// LOG.debug("ClientHanler#messageReceived");
|
||||||
|
@ -147,8 +157,8 @@ public class ForwardingHandler extends ChannelOutboundHandlerAdapter {
|
||||||
@Override
|
@Override
|
||||||
public
|
public
|
||||||
void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
|
void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
|
||||||
LOG.error("ClientHanler#exceptionCaught");
|
logger.error("ClientHandler#exceptionCaught");
|
||||||
LOG.error(cause.getMessage(), cause);
|
logger.error(cause.getMessage(), cause);
|
||||||
// e.getFuture()
|
// e.getFuture()
|
||||||
// .setFailure(t);
|
// .setFailure(t);
|
||||||
ctx.channel().close();
|
ctx.channel().close();
|
||||||
|
|
|
@ -7,14 +7,7 @@ import dorkbox.util.NamedThreadFactory;
|
||||||
import io.netty.bootstrap.Bootstrap;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import io.netty.buffer.ByteBuf;
|
import io.netty.buffer.ByteBuf;
|
||||||
import io.netty.buffer.PooledByteBufAllocator;
|
import io.netty.buffer.PooledByteBufAllocator;
|
||||||
import io.netty.channel.ChannelFuture;
|
import io.netty.channel.*;
|
||||||
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.nio.NioEventLoopGroup;
|
import io.netty.channel.nio.NioEventLoopGroup;
|
||||||
import io.netty.channel.oio.OioEventLoopGroup;
|
import io.netty.channel.oio.OioEventLoopGroup;
|
||||||
import io.netty.channel.socket.DatagramPacket;
|
import io.netty.channel.socket.DatagramPacket;
|
||||||
|
@ -24,7 +17,7 @@ import io.netty.util.internal.PlatformDependent;
|
||||||
|
|
||||||
@ChannelHandler.Sharable
|
@ChannelHandler.Sharable
|
||||||
public
|
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.
|
* This is what is called whenever a DNS packet is received. Currently only support UDP packets.
|
Loading…
Reference in New Issue
Block a user