Refactored Dns classes and added initial implementation of a MDNS Server

This commit is contained in:
Ziver Koc 2017-02-03 17:01:46 +01:00
parent e8491617c6
commit e50027906d
12 changed files with 201 additions and 56 deletions

View file

@ -24,6 +24,8 @@
package zutil.net.dns;
import zutil.net.dns.packet.DnsPacket;
public interface DnsResolutionListener {
void receivedResponse(DnsPacket packet);
}

View file

@ -0,0 +1,16 @@
package zutil.net.dns;
import java.net.InetAddress;
import java.util.HashMap;
/**
* This class contains data about a service that
* can be looked up through DNS and MDNS.
*/
public class DnsService {
private String name;
private String dns;
private InetAddress host;
private HashMap properties;
}

View file

@ -26,6 +26,9 @@ package zutil.net.dns;
import zutil.io.MultiPrintStream;
import zutil.log.LogUtil;
import zutil.net.dns.packet.DnsConstants;
import zutil.net.dns.packet.DnsPacket;
import zutil.net.dns.packet.DnsPacketQuestion;
import zutil.net.threaded.ThreadedUDPNetwork;
import zutil.net.threaded.ThreadedUDPNetworkThread;
import zutil.parser.binary.BinaryStructInputStream;
@ -40,9 +43,12 @@ import java.util.HashSet;
import java.util.logging.Level;
import java.util.logging.Logger;
import static zutil.net.dns.MulticastDnsServer.MDNS_MULTICAST_ADDR;
import static zutil.net.dns.MulticastDnsServer.MDNS_MULTICAST_PORT;
/**
* This class implements a MDNS Client. MDNS is a version
* of the DNS protocol but used a Zeroconf application.
* of the DNS protocol but supports Zeroconf.
*
* @see <a href="http://tools.ietf.org/html/rfc1035">DNS Spec (rfc1035)</a>
* @see <a href="https://tools.ietf.org/html/rfc6763">DNS-SD Spec (rfc6763)</a>
@ -51,9 +57,6 @@ import java.util.logging.Logger;
public class MulticastDnsClient extends ThreadedUDPNetwork implements ThreadedUDPNetworkThread{
private static final Logger logger = LogUtil.getLogger();
private static final String MDNS_MULTICAST_ADDR = "224.0.0.251";
private static final int MDNS_MULTICAST_PORT = 5353;
private HashSet<Integer> activeProbes;
private DnsResolutionListener listener;

View file

@ -0,0 +1,119 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015 Ziver Koc
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package zutil.net.dns;
import zutil.log.LogUtil;
import zutil.net.dns.packet.DnsPacket;
import zutil.net.dns.packet.DnsPacketQuestion;
import zutil.net.dns.packet.DnsPacketResource;
import zutil.net.threaded.ThreadedUDPNetwork;
import zutil.net.threaded.ThreadedUDPNetworkThread;
import zutil.parser.binary.BinaryStructInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.DatagramPacket;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* This class implements a MDNS Server. MDNS is a version
* of the DNS protocol but supports Zeroconf.
*
* @see <a href="http://tools.ietf.org/html/rfc1035">DNS Spec (rfc1035)</a>
* @see <a href="https://tools.ietf.org/html/rfc6763">DNS-SD Spec (rfc6763)</a>
* @author Ziver
*/
public class MulticastDnsServer extends ThreadedUDPNetwork implements ThreadedUDPNetworkThread{
private static final Logger logger = LogUtil.getLogger();
protected static final String MDNS_MULTICAST_ADDR = "224.0.0.251";
protected static final int MDNS_MULTICAST_PORT = 5353;
private HashMap<String,ArrayList> entries = new HashMap<>();
public MulticastDnsServer() throws IOException {
super(MDNS_MULTICAST_ADDR, MDNS_MULTICAST_PORT);
setThread( this );
}
/**
* Add a domain name specific data that will be returned to a requesting client
*
* @param name is the domain name to add the entry under
* @param type {@link zutil.net.dns.packet.DnsConstants.TYPE}
* @param clazz {@link zutil.net.dns.packet.DnsConstants.CLASS}
* @param data
*/
public void addEntry(String name, int type, int clazz, String data){
DnsPacketResource resource = new DnsPacketResource();
resource.name = name;
resource.type = type;
resource.clazz = clazz;
//resource.ttl = 10; ???
resource.length = data.length();
resource.data = data;
addEntry(resource);
}
private void addEntry(DnsPacketResource resource) {
if ( ! entries.containsKey(resource.name))
entries.put(resource.name, new ArrayList());
entries.get(resource.name).add(resource);
}
@Override
public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) {
try {
ByteArrayInputStream buffer = new ByteArrayInputStream(packet.getData(),
packet.getOffset(), packet.getLength());
BinaryStructInputStream in = new BinaryStructInputStream(buffer);
DnsPacket dnsPacket = DnsPacket.read(in);
// Just handle queries and no responses
if ( ! dnsPacket.getHeader().flagQueryResponse){
for (DnsPacketQuestion question : dnsPacket.getQuestions()){
if (entries.containsKey(question.name)){
// Respond with entries
}
}
}
} catch (IOException e){
logger.log(Level.WARNING, null, e);
}
}
}

View file

@ -1,4 +1,4 @@
package zutil.net.dns;
package zutil.net.dns.packet;
/**
*

View file

@ -1,4 +1,4 @@
package zutil.net.dns;
package zutil.net.dns.packet;
import zutil.parser.binary.BinaryStructInputStream;
import zutil.parser.binary.BinaryStructOutputStream;

View file

@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
package zutil.net.dns;
package zutil.net.dns.packet;
import zutil.parser.binary.BinaryStruct;

View file

@ -22,16 +22,10 @@
* THE SOFTWARE.
*/
package zutil.net.dns;
package zutil.net.dns.packet;
import zutil.parser.binary.BinaryFieldData;
import zutil.parser.binary.BinaryFieldSerializer;
import zutil.parser.binary.BinaryStruct;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* @see <a href="http://tools.ietf.org/html/rfc1035">DNS Spec (rfc1035)</a>
* @author Ziver
@ -96,44 +90,4 @@ public class DnsPacketQuestion implements BinaryStruct {
}
public static class FQDNStringSerializer implements BinaryFieldSerializer<String> {
public String read(InputStream in, BinaryFieldData field) throws IOException {
StringBuilder str = new StringBuilder();
int c = in.read();
// Is this a pointer
if ((c & 0b1100_0000) == 0b1100_0000 ){
int offset = (c & 0b0011_1111) << 8;
offset |= in.read() & 0b1111_1111;
str.append(offset);
}
// Normal Domain String
else {
while (c > 0) {
for (int i = 0; i < c; ++i) {
str.append((char) in.read());
}
c = in.read();
if (c > 0)
str.append('.');
}
}
return str.toString();
}
public void write(OutputStream out, String domain, BinaryFieldData field) throws IOException {
if (domain != null){
String[] labels = domain.split("\\.");
for (String label : labels) {
out.write(label.length());
out.write(label.getBytes());
}
}
out.write(0);
}
}
}

View file

@ -22,7 +22,7 @@
* THE SOFTWARE.
*/
package zutil.net.dns;
package zutil.net.dns.packet;
import zutil.parser.binary.BinaryStruct;
@ -65,7 +65,7 @@ public class DnsPacketResource implements BinaryStruct {
/**
* a domain name to which this resource record pertains.
*/
@CustomBinaryField(index=10, serializer=DnsPacketQuestion.FQDNStringSerializer.class)
@CustomBinaryField(index=10, serializer=FQDNStringSerializer.class)
public String name;
/**

View file

@ -0,0 +1,49 @@
package zutil.net.dns.packet;
import zutil.parser.binary.BinaryFieldData;
import zutil.parser.binary.BinaryFieldSerializer;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* A serializer class that can read and write a DNS FQDN in binary format.
*/
public class FQDNStringSerializer implements BinaryFieldSerializer<String> {
public String read(InputStream in, BinaryFieldData field) throws IOException {
StringBuilder str = new StringBuilder();
int c = in.read();
// Is this a pointer
if ((c & 0b1100_0000) == 0b1100_0000) {
int offset = (c & 0b0011_1111) << 8;
offset |= in.read() & 0b1111_1111;
str.append(offset);
}
// Normal Domain String
else {
while (c > 0) {
for (int i = 0; i < c; ++i) {
str.append((char) in.read());
}
c = in.read();
if (c > 0)
str.append('.');
}
}
return str.toString();
}
public void write(OutputStream out, String domain, BinaryFieldData field) throws IOException {
if (domain != null) {
String[] labels = domain.split("\\.");
for (String label : labels) {
out.write(label.length());
out.write(label.getBytes());
}
}
out.write(0);
}
}

View file

@ -26,6 +26,7 @@ package zutil.net.dns;
import org.junit.Test;
import zutil.converter.Converter;
import zutil.net.dns.packet.*;
import zutil.parser.binary.BinaryStructInputStream;
import zutil.parser.binary.BinaryStructOutputStream;

View file

@ -3,6 +3,7 @@ package zutil.net.dns;
import zutil.io.MultiPrintStream;
import zutil.log.CompactLogFormatter;
import zutil.log.LogUtil;
import zutil.net.dns.packet.DnsPacket;
import java.io.IOException;
import java.util.logging.Level;