Dns server working for single test query issued by command line

This commit is contained in:
nathan 2018-03-03 14:00:29 +01:00
parent 0460c35e2e
commit 3587933022
9 changed files with 237 additions and 76 deletions

View File

@ -0,0 +1,98 @@
/*
* 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;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import dorkbox.network.dns.records.DnsMessage;
import io.netty.channel.AddressedEnvelope;
import io.netty.util.internal.UnstableApi;
/**
* A {@link DnsServerResponse} implementation for UDP/IP.
*/
@UnstableApi
public
class DnsServerResponse extends DnsEnvelope {
/**
* Creates a new instance.
*
* @param localAddress the address of the sender
* @param remoteAddress the address of the recipient
*/
public
DnsServerResponse(final DnsMessage dnsQuestion, InetSocketAddress localAddress, InetSocketAddress remoteAddress) {
super(dnsQuestion.getHeader()
.getID(), localAddress, remoteAddress);
if (remoteAddress == null && localAddress == null) {
throw new NullPointerException("localAddress and remoteAddress");
}
}
@Override
public
int hashCode() {
int hashCode = super.hashCode();
if (sender() != null) {
hashCode = hashCode * 31 + sender().hashCode();
}
if (recipient() != null) {
hashCode = hashCode * 31 + recipient().hashCode();
}
return hashCode;
}
@Override
public
boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (!(obj instanceof AddressedEnvelope)) {
return false;
}
@SuppressWarnings("unchecked")
final AddressedEnvelope<?, SocketAddress> that = (AddressedEnvelope<?, SocketAddress>) obj;
if (sender() == null) {
if (that.sender() != null) {
return false;
}
}
else if (!sender().equals(that.sender())) {
return false;
}
if (recipient() == null) {
if (that.recipient() != null) {
return false;
}
}
else if (!recipient().equals(that.recipient())) {
return false;
}
return true;
}
}

View File

@ -22,16 +22,20 @@ import java.net.UnknownHostException;
import org.slf4j.Logger;
import dorkbox.network.dns.DnsEnvelope;
import dorkbox.network.dns.DnsServerResponse;
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.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 io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;
public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
@ -62,10 +66,9 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
public
void channelRead(ChannelHandlerContext context, Object message) throws Exception {
onChannelRead(context, (DnsEnvelope) message);
ReferenceCountUtil.release(message);
}
public
private
void onChannelRead(final ChannelHandlerContext context, final DnsEnvelope dnsMessage) {
int opcode = dnsMessage.getHeader()
.getOpcode();
@ -73,32 +76,26 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
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();
}
}
@ -111,12 +108,11 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
// 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);
DnsServerResponse dnsResponse = new DnsServerResponse(dnsQuestion,
(InetSocketAddress) context.channel().localAddress(),
recipient);
// dnsEnvelope.getHeader().setRcode(DnsResponseCode.NXDOMAIN);
// dnsResponse.getHeader().setRcode(DnsResponseCode.NXDOMAIN);
DnsRecord[] sectionArray = dnsQuestion.getSectionArray(DnsSection.QUESTION);
DnsRecord dnsRecord = sectionArray[0];
@ -127,22 +123,16 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
// // 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);
dnsResponse.addRecord(dnsRecord, DnsSection.QUESTION);
dnsResponse.addRecord(answerRecord, DnsSection.ANSWER);
dnsEnvelope.getHeader().setRcode(DnsResponseCode.NOERROR);
dnsResponse.getHeader().setRcode(DnsResponseCode.NOERROR);
System.err.println("write");
logger.debug("Writing A record response: {}", answerRecord.getAddress());
}
// 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));
.write(dnsResponse);
// ChannelBuffer buffer = (ChannelBuffer) e.getMessage();
@ -292,7 +282,7 @@ public class DnsDecisionHandler extends ChannelInboundHandlerAdapter {
@Override
public
void exceptionCaught(final ChannelHandlerContext context, final Throwable cause) throws Exception {
logger.error("ForwardingHandler#exceptionCaught", cause);
logger.error("DecisionHandler#exceptionCaught", cause);
super.exceptionCaught(context, cause);
}

View File

@ -43,10 +43,6 @@ class DnsMessageDecoder extends MessageToMessageDecoder<DatagramPacket> {
InetSocketAddress remoteAddress = packet.sender();
DnsEnvelope dnsEnvelope = new DnsEnvelope(buf, localAddress, remoteAddress);
dnsEnvelope.retain();
// send down the pipeline
out.add(dnsEnvelope);
success = true;
} finally {

View File

@ -1,25 +1,29 @@
package dorkbox.network.dns.serverHandlers;
import java.io.IOException;
import org.slf4j.Logger;
import dorkbox.network.dns.DnsOutput;
import dorkbox.network.dns.records.DnsMessage;
import dorkbox.network.dns.DnsServerResponse;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.socket.DatagramPacket;
import io.netty.handler.codec.MessageToByteEncoder;
/**
* An encoder which serializes a Java object into a {@link ByteBuf}.
* <p>
* Please note that the serialized form this encoder produces is not
* compatible with the standard {@link ObjectInputStream}. Please use
* {@link ObjectDecoder} or {@link ObjectDecoderInputStream} to ensure the
* interoperability with this encoder.
*
*/
@ChannelHandler.Sharable
public
class DnsMessageEncoder extends MessageToByteEncoder<DnsMessage> {
class DnsMessageEncoder extends MessageToByteEncoder<DnsServerResponse> {
private final Logger logger;
public
DnsMessageEncoder(final Logger logger) {
this.logger = logger;
}
// public
@ -54,23 +58,24 @@ class DnsMessageEncoder extends MessageToByteEncoder<DnsMessage> {
@Override
protected
void encode(final ChannelHandlerContext ctx, final DnsMessage msg, final ByteBuf out) throws Exception {
System.err.println("WRITING MESSAGE");
final DnsOutput outd = new DnsOutput(out);
msg.toWire(outd);
void encode(final ChannelHandlerContext context, final DnsServerResponse message, final ByteBuf out) throws Exception {
try {
DnsOutput dnsOutput = new DnsOutput(out);
out.retain();
message.toWire(dnsOutput);
DatagramPacket packet = new DatagramPacket(out, message.recipient(), message.sender());
context.channel()
.writeAndFlush(packet);
} catch (Exception e) {
context.fireExceptionCaught(new IOException("Unable to write dns message: " + message, e));
}
}
@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("DnsMessageEncoder#exceptionCaught", cause);
super.exceptionCaught(context, cause);
}
}

View File

@ -15,11 +15,16 @@ public
class DnsServerHandler extends ChannelInboundHandlerAdapter {
protected final DnsMessageDecoder decoder;
private final Logger logger;
private DnsDecisionHandler decisionHandler;
private DnsMessageEncoder encoder;
public
DnsServerHandler(final Logger logger) {
this.logger = logger;
decoder = new DnsMessageDecoder(logger);
decisionHandler = new DnsDecisionHandler(logger);
encoder = new DnsMessageEncoder(logger);
}
@Override
@ -49,12 +54,13 @@ class DnsServerHandler extends ChannelInboundHandlerAdapter {
///////////////////////
// DECODE (or upstream)
///////////////////////
pipeline.addLast("decoder", this.decoder);
pipeline.addLast("decoder", decoder);
pipeline.addLast("dnsDecision", decisionHandler);
// ENCODE (or downstream)
/////////////////////////
pipeline.addLast("dnsDecision", new DnsDecisionHandler(logger));
pipeline.addLast("fowarder", new ForwardingHandler(logger));
pipeline.addLast("encoder", encoder);
// pipeline.addLast("fowarder", new ForwardingHandler(logger));
// pipeline.addLast("fowarder", new ForwardingHandler(this.config, this.clientChannelFactory));
}
}

View File

@ -1,4 +1,19 @@
package dorkbox.network.dns.serverHandlers;
/*
* 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;

View File

@ -1,15 +1,26 @@
package dorkbox.network.dns.serverHandlers;
import java.io.IOException;
/*
* 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 dorkbox.network.dns.DnsOutput;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.DatagramPacket;
import io.netty.handler.codec.MessageToByteEncoder;
public class ForwardingHandler extends MessageToByteEncoder<DnsEnvelope> {
@ -39,16 +50,19 @@ public class ForwardingHandler extends MessageToByteEncoder<DnsEnvelope> {
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);
// TODO: forward the message to ANOTHER dns server because we don't know what the awnser is
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));
}
// 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));
// }
}

View File

@ -1,4 +1,19 @@
package dorkbox.network.dns.serverHandlers;
/*
* 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;

View File

@ -1,4 +1,19 @@
package dorkbox.network.dns.serverHandlers;
/*
* 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 java.net.InetSocketAddress;
@ -7,7 +22,14 @@ import dorkbox.util.NamedThreadFactory;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.*;
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.nio.NioEventLoopGroup;
import io.netty.channel.oio.OioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;