From a032cd5802f5c0a5dda7e049a866f83c3e3645bf Mon Sep 17 00:00:00 2001 From: David Gerber Date: Sun, 17 Nov 2024 19:10:42 +0100 Subject: [PATCH] Fix UDP discovery to work with the new fingerprint size --- .../xeres/app/net/bdisc/ProtocolVersion.java | 3 +- .../app/net/bdisc/UdpDiscoveryProtocol.java | 33 ++++++++++++++++--- .../serialization/IdentifierSerializer.java | 18 ++++++++++ .../app/xrs/serialization/Serializer.java | 16 +++++++++ 4 files changed, 64 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/io/xeres/app/net/bdisc/ProtocolVersion.java b/app/src/main/java/io/xeres/app/net/bdisc/ProtocolVersion.java index e2f352c5a..c8dbe74d2 100644 --- a/app/src/main/java/io/xeres/app/net/bdisc/ProtocolVersion.java +++ b/app/src/main/java/io/xeres/app/net/bdisc/ProtocolVersion.java @@ -22,5 +22,6 @@ enum ProtocolVersion { VERSION_0, - VERSION_1 + VERSION_1, + VERSION_2 } diff --git a/app/src/main/java/io/xeres/app/net/bdisc/UdpDiscoveryProtocol.java b/app/src/main/java/io/xeres/app/net/bdisc/UdpDiscoveryProtocol.java index b77b5f5fb..8859a1cc0 100644 --- a/app/src/main/java/io/xeres/app/net/bdisc/UdpDiscoveryProtocol.java +++ b/app/src/main/java/io/xeres/app/net/bdisc/UdpDiscoveryProtocol.java @@ -30,8 +30,7 @@ import java.net.InetSocketAddress; import java.nio.ByteBuffer; -import static io.xeres.app.net.bdisc.ProtocolVersion.VERSION_0; -import static io.xeres.app.net.bdisc.ProtocolVersion.VERSION_1; +import static io.xeres.app.net.bdisc.ProtocolVersion.*; public final class UdpDiscoveryProtocol { @@ -66,7 +65,7 @@ public static UdpDiscoveryPeer parsePacket(ByteBuffer buffer, InetSocketAddress case MAGIC_HEADER_VERSIONED -> { var versionNum = buffer.get(); - if (versionNum > VERSION_1.ordinal()) + if (versionNum > VERSION_2.ordinal()) { log.warn("Unsupported protocol version: {}", versionNum); return null; @@ -116,7 +115,20 @@ public static UdpDiscoveryPeer parsePacket(ByteBuffer buffer, InetSocketAddress } var buf = Unpooled.wrappedBuffer(buffer); - peer.setFingerprint((ProfileFingerprint) Serializer.deserializeIdentifier(buf, ProfileFingerprint.class)); + if (protocolVersion != VERSION_2) + { + peer.setFingerprint((ProfileFingerprint) Serializer.deserializeIdentifierWithSize(buf, ProfileFingerprint.class, ProfileFingerprint.V4_LENGTH)); + } + else + { + var fingerPrintSize = buffer.get(); + switch (fingerPrintSize) + { + case 20 -> peer.setFingerprint((ProfileFingerprint) Serializer.deserializeIdentifierWithSize(buf, ProfileFingerprint.class, ProfileFingerprint.V4_LENGTH)); + case 32 -> peer.setFingerprint((ProfileFingerprint) Serializer.deserializeIdentifierWithSize(buf, ProfileFingerprint.class, ProfileFingerprint.LENGTH)); + default -> throw new IllegalArgumentException("Unknown fingerprint size:" + fingerPrintSize); + } + } peer.setLocationId((LocationId) Serializer.deserializeIdentifier(buf, LocationId.class)); peer.setLocalPort(Serializer.deserializeShort(buf)); peer.setProfileName(Serializer.deserializeString(buf)); @@ -129,7 +141,18 @@ public static ByteBuffer createPacket(int maxSize, Status status, int appId, int var buffer = ByteBuffer.allocate(maxSize); buffer.putInt(MAGIC_HEADER_VERSIONED); - buffer.put((byte) VERSION_1.ordinal()); // protocol version + if (fingerprint.getLength() == 32) + { + buffer.put((byte) VERSION_2.ordinal()); // protocol version + } + else if (fingerprint.getLength() == 20) + { + buffer.put((byte) VERSION_1.ordinal()); // protocol version + } + else + { + throw new IllegalArgumentException("Unknown fingerprint size:" + fingerprint.getLength()); + } buffer.put((byte) 0); buffer.put((byte) 0); buffer.put((byte) 0); diff --git a/app/src/main/java/io/xeres/app/xrs/serialization/IdentifierSerializer.java b/app/src/main/java/io/xeres/app/xrs/serialization/IdentifierSerializer.java index d86f08447..e8dd4556e 100644 --- a/app/src/main/java/io/xeres/app/xrs/serialization/IdentifierSerializer.java +++ b/app/src/main/java/io/xeres/app/xrs/serialization/IdentifierSerializer.java @@ -79,6 +79,24 @@ static Identifier deserialize(ByteBuf buf, Class identifierClass) } } + static Identifier deserializeWithSize(ByteBuf buf, Class identifierClass, int size) + { + try + { + //noinspection PrimitiveArrayArgumentToVarargsMethod + var identifier = (Identifier) identifierClass.getDeclaredConstructor(byte[].class).newInstance(ByteArraySerializer.deserialize(buf, size)); + if (Arrays.equals(identifier.getNullIdentifier(), identifier.getBytes())) + { + return null; + } + return identifier; + } + catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) + { + throw new IllegalStateException(e.getMessage()); + } + } + static int getIdentifierLength(Class identifierClass) { try diff --git a/app/src/main/java/io/xeres/app/xrs/serialization/Serializer.java b/app/src/main/java/io/xeres/app/xrs/serialization/Serializer.java index ee2fa44e5..45bd00746 100644 --- a/app/src/main/java/io/xeres/app/xrs/serialization/Serializer.java +++ b/app/src/main/java/io/xeres/app/xrs/serialization/Serializer.java @@ -22,6 +22,7 @@ import io.netty.buffer.ByteBuf; import io.xeres.app.database.model.gxs.GxsMetaAndData; import io.xeres.common.id.Identifier; +import io.xeres.common.id.ProfileFingerprint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -265,6 +266,21 @@ public static Identifier deserializeIdentifier(ByteBuf buf, Class identifierC return IdentifierSerializer.deserialize(buf, identifierClass); } + /** + * Deserializes an identifier while specifying its size. + *

+ * This is required for some identifier that can have a varying size, like {@link ProfileFingerprint}. + * + * @param buf the buffer + * @param identifierClass the class of the identifier + * @param size the size to deserialize + * @return the identifier + */ + public static Identifier deserializeIdentifierWithSize(ByteBuf buf, Class identifierClass, int size) + { + return IdentifierSerializer.deserializeWithSize(buf, identifierClass, size); + } + /** * Serializes a byte array. *