Bugfixes in BinaryStruct and some Tests for MDNS
This commit is contained in:
parent
64a9b4126c
commit
96e7d4489a
9 changed files with 320 additions and 117 deletions
|
|
@ -65,7 +65,6 @@ public class ByteUtil {
|
||||||
* @return a new byte containing a sub byte defined by the index and length
|
* @return a new byte containing a sub byte defined by the index and length
|
||||||
*/
|
*/
|
||||||
public static byte getBits(byte data, int index, int length){
|
public static byte getBits(byte data, int index, int length){
|
||||||
length--;
|
|
||||||
byte ret = (byte) (data & getBitMask(index, length));
|
byte ret = (byte) (data & getBitMask(index, length));
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -77,6 +76,7 @@ public class ByteUtil {
|
||||||
* @param length length of mask from index, valid values 1-8
|
* @param length length of mask from index, valid values 1-8
|
||||||
*/
|
*/
|
||||||
public static byte getBitMask(int index, int length) {
|
public static byte getBitMask(int index, int length) {
|
||||||
|
--length;
|
||||||
if(0 > index || index > 7)
|
if(0 > index || index > 7)
|
||||||
throw new IllegalArgumentException("Invalid index argument, allowed value is 0-7");
|
throw new IllegalArgumentException("Invalid index argument, allowed value is 0-7");
|
||||||
if(length < 0 && index-length < 0)
|
if(length < 0 && index-length < 0)
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ import zutil.parser.binary.BinaryStruct;
|
||||||
* Created by Ziver on 2016-02-09.
|
* Created by Ziver on 2016-02-09.
|
||||||
* Reference: http://tools.ietf.org/html/rfc1035
|
* Reference: http://tools.ietf.org/html/rfc1035
|
||||||
*/
|
*/
|
||||||
public class DNSPacket implements BinaryStruct {
|
public class DNSPacketHeader implements BinaryStruct {
|
||||||
public static final int OPCODE_QUERY = 0;
|
public static final int OPCODE_QUERY = 0;
|
||||||
public static final int OPCODE_IQUERY = 1;
|
public static final int OPCODE_IQUERY = 1;
|
||||||
public static final int OPCODE_STATUS = 2;
|
public static final int OPCODE_STATUS = 2;
|
||||||
|
|
@ -42,9 +42,33 @@ public class DNSPacket implements BinaryStruct {
|
||||||
public static final int RCODE_NOT_IMPLEMENTED = 4;
|
public static final int RCODE_NOT_IMPLEMENTED = 4;
|
||||||
public static final int RCODE_REFUSED = 5;
|
public static final int RCODE_REFUSED = 5;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Header section format
|
||||||
|
|
||||||
|
The header contains the following fields:
|
||||||
|
|
||||||
|
1 1 1 1 1 1
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| ID |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
|QR| Opcode |AA|TC|RD|RA| Z | RCODE |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| QDCOUNT |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| ANCOUNT |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| NSCOUNT |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| ARCOUNT |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
|
||||||
|
where:
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
@BinaryField(index=0, length=16)
|
@BinaryField(index=0, length=16)
|
||||||
int id;
|
public int id;
|
||||||
|
|
||||||
//////////////// FLAGS
|
//////////////// FLAGS
|
||||||
//@BinaryField(index=10, length=16)
|
//@BinaryField(index=10, length=16)
|
||||||
|
|
@ -54,7 +78,7 @@ public class DNSPacket implements BinaryStruct {
|
||||||
* query (0), or a response (1).
|
* query (0), or a response (1).
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=10, length=1)
|
@BinaryField(index=10, length=1)
|
||||||
boolean flagQueryResponse;
|
public boolean flagQueryResponse;
|
||||||
/**
|
/**
|
||||||
* A four bit field that specifies kind of query in this message.
|
* A four bit field that specifies kind of query in this message.
|
||||||
* <pre>
|
* <pre>
|
||||||
|
|
@ -64,21 +88,21 @@ public class DNSPacket implements BinaryStruct {
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=11, length=4)
|
@BinaryField(index=11, length=4)
|
||||||
int flagOperationCode;
|
public int flagOperationCode;
|
||||||
/**
|
/**
|
||||||
* This bit is valid in responses,
|
* This bit is valid in responses,
|
||||||
* and specifies that the responding name server is an
|
* and specifies that the responding name server is an
|
||||||
* authority for the domain name in question section.
|
* authority for the domain name in question section.
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=12, length=1)
|
@BinaryField(index=12, length=1)
|
||||||
boolean flagAuthoritativeAnswer;
|
public boolean flagAuthoritativeAnswer;
|
||||||
/**
|
/**
|
||||||
* specifies that this message was truncated
|
* specifies that this message was truncated
|
||||||
* due to length greater than that permitted on the
|
* due to length greater than that permitted on the
|
||||||
* transmission channel.
|
* transmission channel.
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=13, length=1)
|
@BinaryField(index=13, length=1)
|
||||||
boolean flagTruncation;
|
public boolean flagTruncation;
|
||||||
/**
|
/**
|
||||||
* this bit may be set in a query and
|
* this bit may be set in a query and
|
||||||
* is copied into the response. If RD is set, it directs
|
* is copied into the response. If RD is set, it directs
|
||||||
|
|
@ -86,20 +110,20 @@ public class DNSPacket implements BinaryStruct {
|
||||||
* Recursive query support is optional.
|
* Recursive query support is optional.
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=14, length=1)
|
@BinaryField(index=14, length=1)
|
||||||
boolean flagRecursionDesired;
|
public boolean flagRecursionDesired;
|
||||||
/**
|
/**
|
||||||
* this be is set or cleared in a
|
* this be is set or cleared in a
|
||||||
* response, and denotes whether recursive query support is
|
* response, and denotes whether recursive query support is
|
||||||
* available in the name server.
|
* available in the name server.
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=15, length=1)
|
@BinaryField(index=15, length=1)
|
||||||
boolean flagRecursionAvailable;
|
public boolean flagRecursionAvailable;
|
||||||
/**
|
/**
|
||||||
* Reserved for future use. Must be zero in all queries
|
* Reserved for future use. Must be zero in all queries
|
||||||
* and responses.
|
* and responses.
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=16, length=3)
|
@BinaryField(index=16, length=3)
|
||||||
private int z;
|
protected int z;
|
||||||
/**
|
/**
|
||||||
* this field is set as part of responses.
|
* this field is set as part of responses.
|
||||||
* The values have the following interpretation:
|
* The values have the following interpretation:
|
||||||
|
|
@ -123,7 +147,7 @@ public class DNSPacket implements BinaryStruct {
|
||||||
*</pre>
|
*</pre>
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=17, length=4)
|
@BinaryField(index=17, length=4)
|
||||||
int flagResponseCode;
|
public int flagResponseCode;
|
||||||
|
|
||||||
|
|
||||||
//////////////// COUNTS
|
//////////////// COUNTS
|
||||||
|
|
@ -132,115 +156,57 @@ public class DNSPacket implements BinaryStruct {
|
||||||
* Specifying the number of entries in the question section.
|
* Specifying the number of entries in the question section.
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=20, length=16)
|
@BinaryField(index=20, length=16)
|
||||||
int countQuestion;
|
public int countQuestion;
|
||||||
/**
|
/**
|
||||||
* Answer Record Count.
|
* Answer Record Count.
|
||||||
* specifying the number of resource records in
|
* specifying the number of resource records in
|
||||||
* the answer section.
|
* the answer section.
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=21, length=16)
|
@BinaryField(index=21, length=16)
|
||||||
int countAnswerRecord;
|
public int countAnswerRecord;
|
||||||
/**
|
/**
|
||||||
* Name Server (Authority Record) Count.
|
* Name Server (Authority Record) Count.
|
||||||
* Specifying the number of name server resource records
|
* Specifying the number of name server resource records
|
||||||
* in the authority records section.
|
* in the authority records section.
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=22, length=16)
|
@BinaryField(index=22, length=16)
|
||||||
int countNameServer;
|
public int countNameServer;
|
||||||
/**
|
/**
|
||||||
* Additional Record Count.
|
* Additional Record Count.
|
||||||
* Specifying the number of resource records in the
|
* Specifying the number of resource records in the
|
||||||
* additional records section
|
* additional records section
|
||||||
*/
|
*/
|
||||||
@BinaryField(index=23, length=16)
|
@BinaryField(index=23, length=16)
|
||||||
int countAdditionalRecord;
|
public int countAdditionalRecord;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Question section format
|
|
||||||
1 1 1 1 1 1
|
|
||||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
| |
|
|
||||||
/ QNAME /
|
|
||||||
/ /
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
| QTYPE |
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
| QCLASS |
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
|
|
||||||
where:
|
|
||||||
|
|
||||||
QNAME a domain name represented as a sequence of labels, where
|
|
||||||
each label consists of a length octet followed by that
|
|
||||||
number of octets. The domain name terminates with the
|
|
||||||
zero length octet for the null label of the root. Note
|
|
||||||
that this field may be an odd number of octets; no
|
|
||||||
padding is used.
|
|
||||||
|
|
||||||
QTYPE a two octet code which specifies the type of the query.
|
public void setDefaultQueryData() {
|
||||||
The values for this field include all codes valid for a
|
// Set all flags to zero
|
||||||
TYPE field, together with some more general codes which
|
flagQueryResponse = false;
|
||||||
can match more than one type of RR.
|
flagOperationCode = 0;
|
||||||
|
flagAuthoritativeAnswer = false;
|
||||||
|
flagTruncation = false;
|
||||||
|
flagRecursionDesired = false;
|
||||||
|
flagRecursionAvailable = false;
|
||||||
|
z = 0;
|
||||||
|
flagResponseCode = 0;
|
||||||
|
}
|
||||||
|
|
||||||
QCLASS a two octet code that specifies the class of the query.
|
public void setDefaultResponseData() {
|
||||||
For example, the QCLASS field is IN for the Internet.
|
flagQueryResponse = true;
|
||||||
*/
|
flagAuthoritativeAnswer = true;
|
||||||
|
|
||||||
/*
|
// Set the rest to zero
|
||||||
Resource record format
|
// TODO: all flags should not be zeroed
|
||||||
|
flagOperationCode = 0;
|
||||||
The answer, authority, and additional sections all share the same
|
flagTruncation = false;
|
||||||
format: a variable number of resource records, where the number of
|
flagRecursionDesired = false;
|
||||||
records is specified in the corresponding count field in the header.
|
flagRecursionAvailable = false;
|
||||||
Each resource record has the following format:
|
z = 0;
|
||||||
1 1 1 1 1 1
|
flagResponseCode = 0;
|
||||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
}
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
| |
|
|
||||||
/ /
|
|
||||||
/ NAME /
|
|
||||||
| |
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
| TYPE |
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
| CLASS |
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
| TTL |
|
|
||||||
| |
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
| RDLENGTH |
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
|
|
||||||
/ RDATA /
|
|
||||||
/ /
|
|
||||||
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
|
||||||
|
|
||||||
where:
|
|
||||||
|
|
||||||
NAME a domain name to which this resource record pertains.
|
|
||||||
|
|
||||||
TYPE two octets containing one of the RR type codes. This
|
|
||||||
field specifies the meaning of the data in the RDATA
|
|
||||||
field.
|
|
||||||
|
|
||||||
CLASS two octets which specify the class of the data in the
|
|
||||||
RDATA field.
|
|
||||||
|
|
||||||
TTL a 32 bit unsigned integer that specifies the time
|
|
||||||
interval (in seconds) that the resource record may be
|
|
||||||
cached before it should be discarded. Zero values are
|
|
||||||
interpreted to mean that the RR can only be used for the
|
|
||||||
transaction in progress, and should not be cached.
|
|
||||||
|
|
||||||
RDLENGTH an unsigned 16 bit integer that specifies the length in
|
|
||||||
octets of the RDATA field.
|
|
||||||
|
|
||||||
RDATA a variable length string of octets that describes the
|
|
||||||
resource. The format of this information varies
|
|
||||||
according to the TYPE and CLASS of the resource record.
|
|
||||||
For example, the if the TYPE is A and the CLASS is IN,
|
|
||||||
the RDATA field is a 4 octet ARPA Internet address.
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
69
src/zutil/net/dns/DNSPacketQuestion.java
Executable file
69
src/zutil/net/dns/DNSPacketQuestion.java
Executable file
|
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* 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.parser.binary.BinaryStruct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Ziver on 2016-02-09.
|
||||||
|
* Reference: http://tools.ietf.org/html/rfc1035
|
||||||
|
*/
|
||||||
|
public class DNSPacketQuestion implements BinaryStruct {
|
||||||
|
|
||||||
|
/*
|
||||||
|
Question section format
|
||||||
|
1 1 1 1 1 1
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| |
|
||||||
|
/ QNAME /
|
||||||
|
/ /
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| QTYPE |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| QCLASS |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
|
||||||
|
where:
|
||||||
|
|
||||||
|
QNAME a domain name represented as a sequence of labels, where
|
||||||
|
each label consists of a length octet followed by that
|
||||||
|
number of octets. The domain name terminates with the
|
||||||
|
zero length octet for the null label of the root. Note
|
||||||
|
that this field may be an odd number of octets; no
|
||||||
|
padding is used.
|
||||||
|
|
||||||
|
QTYPE a two octet code which specifies the type of the query.
|
||||||
|
The values for this field include all codes valid for a
|
||||||
|
TYPE field, together with some more general codes which
|
||||||
|
can match more than one type of RR.
|
||||||
|
|
||||||
|
QCLASS a two octet code that specifies the class of the query.
|
||||||
|
For example, the QCLASS field is IN for the Internet.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
88
src/zutil/net/dns/DNSPacketResource.java
Executable file
88
src/zutil/net/dns/DNSPacketResource.java
Executable file
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* 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.parser.binary.BinaryStruct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Ziver on 2016-02-09.
|
||||||
|
* Reference: http://tools.ietf.org/html/rfc1035
|
||||||
|
*/
|
||||||
|
public class DNSPacketResource implements BinaryStruct {
|
||||||
|
|
||||||
|
/*
|
||||||
|
The answer, authority, and additional sections all share the same
|
||||||
|
format: a variable number of resource records, where the number of
|
||||||
|
records is specified in the corresponding count field in the header.
|
||||||
|
Each resource record has the following format:
|
||||||
|
1 1 1 1 1 1
|
||||||
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| |
|
||||||
|
/ /
|
||||||
|
/ NAME /
|
||||||
|
| |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| TYPE |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| CLASS |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| TTL |
|
||||||
|
| |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
| RDLENGTH |
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--|
|
||||||
|
/ RDATA /
|
||||||
|
/ /
|
||||||
|
+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
|
||||||
|
|
||||||
|
where:
|
||||||
|
|
||||||
|
NAME a domain name to which this resource record pertains.
|
||||||
|
|
||||||
|
TYPE two octets containing one of the RR type codes. This
|
||||||
|
field specifies the meaning of the data in the RDATA
|
||||||
|
field.
|
||||||
|
|
||||||
|
CLASS two octets which specify the class of the data in the
|
||||||
|
RDATA field.
|
||||||
|
|
||||||
|
TTL a 32 bit unsigned integer that specifies the time
|
||||||
|
interval (in seconds) that the resource record may be
|
||||||
|
cached before it should be discarded. Zero values are
|
||||||
|
interpreted to mean that the RR can only be used for the
|
||||||
|
transaction in progress, and should not be cached.
|
||||||
|
|
||||||
|
RDLENGTH an unsigned 16 bit integer that specifies the length in
|
||||||
|
octets of the RDATA field.
|
||||||
|
|
||||||
|
RDATA a variable length string of octets that describes the
|
||||||
|
resource. The format of this information varies
|
||||||
|
according to the TYPE and CLASS of the resource record.
|
||||||
|
For example, the if the TYPE is A and the CLASS is IN,
|
||||||
|
the RDATA field is a 4 octet ARPA Internet address.
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -33,7 +33,6 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.DatagramPacket;
|
import java.net.DatagramPacket;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Ziver
|
* Created by Ziver
|
||||||
|
|
@ -49,29 +48,25 @@ public class MulticastDNSClient extends ThreadedUDPNetwork implements ThreadedUD
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void sendProbe() {
|
public void sendProbe() throws IOException {
|
||||||
try {
|
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
||||||
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
|
BinaryStructOutputStream out = new BinaryStructOutputStream(buffer);
|
||||||
BinaryStructOutputStream out = new BinaryStructOutputStream(buffer);
|
|
||||||
|
|
||||||
DNSPacket header = new DNSPacket();
|
DNSPacketHeader header = new DNSPacketHeader();
|
||||||
out.write(header);
|
out.write(header);
|
||||||
|
|
||||||
DatagramPacket packet = null;
|
DatagramPacket packet = null;
|
||||||
|
|
||||||
packet = new DatagramPacket(
|
packet = new DatagramPacket(
|
||||||
buffer.toByteArray(), buffer.size(),
|
buffer.toByteArray(), buffer.size(),
|
||||||
InetAddress.getByName( MDNS_MULTICAST_ADDR ),
|
InetAddress.getByName( MDNS_MULTICAST_ADDR ),
|
||||||
MDNS_MULTICAST_PORT );
|
MDNS_MULTICAST_PORT );
|
||||||
send(packet);
|
send(packet);
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) {
|
public void receivedPacket(DatagramPacket packet, ThreadedUDPNetwork network) {
|
||||||
DNSPacket header = new DNSPacket();
|
DNSPacketHeader header = new DNSPacketHeader();
|
||||||
BinaryStructInputStream.read(header, packet.getData());
|
BinaryStructInputStream.read(header, packet.getData());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
package zutil.parser.binary;
|
package zutil.parser.binary;
|
||||||
|
|
||||||
|
|
||||||
|
import java.io.InvalidClassException;
|
||||||
|
import java.io.InvalidObjectException;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import zutil.ByteUtil;
|
||||||
import zutil.converter.Converter;
|
import zutil.converter.Converter;
|
||||||
import zutil.parser.binary.BinaryStruct.BinaryField;
|
import zutil.parser.binary.BinaryStruct.BinaryField;
|
||||||
|
|
||||||
|
|
@ -24,7 +27,7 @@ public class BinaryFieldData implements Comparable<BinaryFieldData> {
|
||||||
protected static List<BinaryFieldData> getStructFieldList(Class<? extends BinaryStruct> clazz){
|
protected static List<BinaryFieldData> getStructFieldList(Class<? extends BinaryStruct> clazz){
|
||||||
if (!cache.containsKey(clazz)) {
|
if (!cache.containsKey(clazz)) {
|
||||||
ArrayList<BinaryFieldData> list = new ArrayList<>();
|
ArrayList<BinaryFieldData> list = new ArrayList<>();
|
||||||
for (Field field : clazz.getFields()) {
|
for (Field field : clazz.getDeclaredFields()) {
|
||||||
if (field.isAnnotationPresent(BinaryField.class))
|
if (field.isAnnotationPresent(BinaryField.class))
|
||||||
list.add(new BinaryFieldData(field));
|
list.add(new BinaryFieldData(field));
|
||||||
}
|
}
|
||||||
|
|
@ -56,15 +59,17 @@ public class BinaryFieldData implements Comparable<BinaryFieldData> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: variable length support
|
|
||||||
protected byte[] getValue(Object obj){
|
protected byte[] getValue(Object obj){
|
||||||
try {
|
try {
|
||||||
|
field.setAccessible(true);
|
||||||
if (field.getType() == Boolean.class || field.getType() == boolean.class)
|
if (field.getType() == Boolean.class || field.getType() == boolean.class)
|
||||||
return new byte[]{ (byte)(field.getBoolean(obj) ? 0x01 : 0x00) };
|
return new byte[]{ (byte)(field.getBoolean(obj) ? 0x01 : 0x00) };
|
||||||
else if (field.getType() == Integer.class || field.getType() == int.class)
|
else if (field.getType() == Integer.class || field.getType() == int.class)
|
||||||
return Converter.toBytes(field.getInt(obj));
|
return Converter.toBytes(field.getInt(obj));
|
||||||
else if (field.getType() == String.class)
|
else if (field.getType() == String.class)
|
||||||
return ((String)(field.get(obj))).getBytes();
|
return ((String)(field.get(obj))).getBytes();
|
||||||
|
else
|
||||||
|
throw new UnsupportedOperationException("Unsupported BinaryStruct field class: "+ field.getClass());
|
||||||
} catch (IllegalAccessException e){
|
} catch (IllegalAccessException e){
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,7 +76,7 @@ public class BinaryStructOutputStream {
|
||||||
byte[] data = field.getValue(struct);
|
byte[] data = field.getValue(struct);
|
||||||
|
|
||||||
int fieldBitLength = field.getBitLength();
|
int fieldBitLength = field.getBitLength();
|
||||||
for (int i=data.length-1; fieldBitLength>0; fieldBitLength-=8, --i) {
|
for (int i=(int)Math.ceil(fieldBitLength/8.0)-1; fieldBitLength>0; fieldBitLength-=8, --i) {
|
||||||
byte b = data[i];
|
byte b = data[i];
|
||||||
if (restBitLength == 0 && fieldBitLength >= 8)
|
if (restBitLength == 0 && fieldBitLength >= 8)
|
||||||
out.write(0xFF & b);
|
out.write(0xFF & b);
|
||||||
|
|
|
||||||
66
test/zutil/net/dns/DNSPacketTest.java
Executable file
66
test/zutil/net/dns/DNSPacketTest.java
Executable file
|
|
@ -0,0 +1,66 @@
|
||||||
|
/*
|
||||||
|
* 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 org.junit.Test;
|
||||||
|
import zutil.parser.binary.BinaryStructOutputStream;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Ziver
|
||||||
|
*/
|
||||||
|
public class DNSPacketTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void headerQueryTest() throws IOException {
|
||||||
|
DNSPacketHeader header = new DNSPacketHeader();
|
||||||
|
header.setDefaultQueryData();
|
||||||
|
header.countQuestion = 1;
|
||||||
|
|
||||||
|
byte[] data = BinaryStructOutputStream.serialize(header);
|
||||||
|
assertEquals("header length", 12, data.length);
|
||||||
|
assertEquals("Flag byte1", 0x00, data[2]);
|
||||||
|
assertEquals("Flag byte2", 0x00, data[3]);
|
||||||
|
assertEquals("Question count byte1", 0x00, data[4]);
|
||||||
|
assertEquals("Question count byte2", 0x01, data[5]);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void headerResponseTest() throws IOException {
|
||||||
|
DNSPacketHeader header = new DNSPacketHeader();
|
||||||
|
header.setDefaultResponseData();
|
||||||
|
header.countAnswerRecord = 1;
|
||||||
|
|
||||||
|
byte[] data = BinaryStructOutputStream.serialize(header);
|
||||||
|
assertEquals("header length", 12, data.length);
|
||||||
|
assertEquals("Flag byte1", (byte)0x84, data[2]);
|
||||||
|
assertEquals("Flag byte2", (byte)0x00, data[3]);
|
||||||
|
assertEquals("Answer count byte1", 0x00, data[6]);
|
||||||
|
assertEquals("Answer count byte2", 0x01, data[7]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -42,7 +42,7 @@ public class BinaryStructOutputStreamTest {
|
||||||
public void basicIntTest() throws IOException {
|
public void basicIntTest() throws IOException {
|
||||||
BinaryStruct struct = new BinaryStruct() {
|
BinaryStruct struct = new BinaryStruct() {
|
||||||
@BinaryField(index=1, length=32)
|
@BinaryField(index=1, length=32)
|
||||||
public int i1 = 1;
|
int i1 = 1;
|
||||||
@BinaryField(index=2, length=32)
|
@BinaryField(index=2, length=32)
|
||||||
public int i2 = 2;
|
public int i2 = 2;
|
||||||
};
|
};
|
||||||
|
|
@ -51,6 +51,20 @@ public class BinaryStructOutputStreamTest {
|
||||||
assertArrayEquals(new byte[]{0,0,0,1, 0,0,0,2}, data);
|
assertArrayEquals(new byte[]{0,0,0,1, 0,0,0,2}, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void shortIntTest() throws IOException {
|
||||||
|
BinaryStruct struct = new BinaryStruct() {
|
||||||
|
@BinaryField(index=1, length=16)
|
||||||
|
int i1 = 1;
|
||||||
|
@BinaryField(index=2, length=16)
|
||||||
|
int i2 = 2;
|
||||||
|
};
|
||||||
|
|
||||||
|
byte[] data = BinaryStructOutputStream.serialize(struct);
|
||||||
|
assertArrayEquals(new byte[]{0,1, 0,2}, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void basicBooleanTest() throws IOException {
|
public void basicBooleanTest() throws IOException {
|
||||||
BinaryStruct struct = new BinaryStruct() {
|
BinaryStruct struct = new BinaryStruct() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue