Fixed DNS packet parsing

This commit is contained in:
Ziver Koc 2023-03-19 21:04:22 +01:00
parent d80b6a69e5
commit 2cd514df9b
3 changed files with 49 additions and 6 deletions

View file

@ -31,8 +31,9 @@ import java.io.OutputStream;
/**
* An Interface defining a custom field parser and writer.
* <p>
* A new instance of the serializer will be instantiated for every time serialization is required.
* {@link BinaryStructInputStream} and {@link BinaryStructOutputStream} objects.
* One singleton instance of the serializer will be cached for the lifetime of the
* {@link BinaryStructInputStream} and {@link BinaryStructOutputStream} objects,
* this can be disabled by calling the {@link BinaryStructInputStream#enableSerializerCache(boolean)}.
* <p>
* NOTE: Partial octet serializing not supported.
*/

View file

@ -30,7 +30,9 @@ import zutil.io.PositionalInputStream;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A stream class that parses a byte stream into binary struct objects.
@ -46,9 +48,13 @@ public class BinaryStructInputStream extends InputStream{
private byte data;
private int dataBitIndex = -1;
private Map<Class, BinaryFieldSerializer> serializerCache;
public BinaryStructInputStream(InputStream in) {
this.in = in;
enableSerializerCache(true);
}
@ -78,11 +84,22 @@ public class BinaryStructInputStream extends InputStream{
*/
public int read(BinaryStruct struct) throws IOException {
List<BinaryFieldData> structDataList = BinaryFieldData.getStructFieldList(struct.getClass());
PositionalInputStream positionalInputStream = new PositionalInputStream(in);
PositionalInputStream positionalInputStream = (in instanceof PositionalInputStream ? (PositionalInputStream) in : new PositionalInputStream(in));
long startPos = positionalInputStream.getPosition();
for (BinaryFieldData field : structDataList) {
if (field.hasSerializer()) {
BinaryFieldSerializer serializer = field.getSerializer();
// Handle serializer cache
BinaryFieldSerializer serializer = (serializerCache != null ? serializerCache.get(field.getSerializerClass()) : null);
if (serializer == null) {
serializer = field.getSerializer();
if (serializerCache != null)
serializerCache.put(serializer.getClass(), serializer);
}
// Read in field through serializer
Object value = serializer.read(positionalInputStream, field, struct);
field.setValue(struct, value);
@ -108,7 +125,7 @@ public class BinaryStructInputStream extends InputStream{
}
}
return (int) positionalInputStream.getPosition();
return (int) (positionalInputStream.getPosition() - startPos);
}
@Override
@ -150,6 +167,31 @@ public class BinaryStructInputStream extends InputStream{
}
/**
* Enable or disable the caching of serializer objects. If disabled then
* a new instance of the serializer will be created every time it is needed.
* <p>
* By default, caching is enabled.
*
* @param enabled set true to enable caching or false to disable.
*/
public void enableSerializerCache(boolean enabled) {
if (enabled) {
serializerCache = new HashMap<>();
} else {
serializerCache = null;
}
}
/**
* Method will clear all cached instances of serializer objects.
*/
public void clearSerializerCache() {
if (serializerCache != null) {
serializerCache.clear();
}
}
protected static int shiftLeftBy(int bitIndex, int bitLength) {
return (8 - ((7-bitIndex) + bitLength) % 8) % 8;
}

View file

@ -437,7 +437,7 @@ Multicast Domain Name System (query)
DnsPacketQuestion question2 = packet.getQuestions().get(1);
assertEquals("qNAME", "_homekit._tcp.local", question2.name);
//assertEquals("qNAME", "_homekit.<28>", question2.name); // TODO: Fix support for string pointers
//assertEquals("qNAME", "_homekit.<28>", question2.name);
assertEquals("type", DnsConstants.TYPE.PTR, question2.type);
assertEquals("clazz", DnsConstants.CLASS.IN, question2.clazz);