From 5d94ba88ee3c83a920e080eaa0913a48b3eb00c1 Mon Sep 17 00:00:00 2001 From: liamcottle Date: Sun, 9 Mar 2025 17:15:12 +1300 Subject: [PATCH] parse packet types --- examples/parse_packet.js | 1 + src/advert.js | 71 +++++++++++++++++++++++++++++++++------- src/packet.js | 43 ++++++++++++++++++++++++ 3 files changed, 104 insertions(+), 11 deletions(-) diff --git a/examples/parse_packet.js b/examples/parse_packet.js index d4569b9..04750f3 100644 --- a/examples/parse_packet.js +++ b/examples/parse_packet.js @@ -4,3 +4,4 @@ const bytes = Buffer.from("0200B401DF6528CC9778A56F36FE9399A5CF6B0C7EDE", "hex") const packet = Packet.fromBytes(bytes); console.log(packet); +console.log(packet.parsePayload()); \ No newline at end of file diff --git a/src/advert.js b/src/advert.js index bc03568..f4c1525 100644 --- a/src/advert.js +++ b/src/advert.js @@ -1,15 +1,51 @@ import {ed25519} from "@noble/curves/ed25519"; import BufferReader from "./buffer_reader.js"; import BufferWriter from "./buffer_writer.js"; -import Packet from "./packet.js"; class Advert { + static ADV_TYPE_NONE = 0; + static ADV_TYPE_CHAT = 1; + static ADV_TYPE_REPEATER = 2; + static ADV_TYPE_ROOM = 3; + + static ADV_LATLON_MASK = 0x10; + static ADV_BATTERY_MASK = 0x20; + static ADV_TEMPERATURE_MASK = 0x40; + static ADV_NAME_MASK = 0x80; + constructor(publicKey, timestamp, signature, appData) { this.publicKey = publicKey; this.timestamp = timestamp; this.signature = signature; this.appData = appData; + this.parsed = this.parseAppData(); + } + + static fromBytes(bytes) { + + // read bytes + const bufferReader = new BufferReader(bytes); + const publicKey = bufferReader.readBytes(32); + const timestamp = bufferReader.readUInt32LE(); + const signature = bufferReader.readBytes(64); + const appData = bufferReader.readRemainingBytes(); + + return new Advert(publicKey, timestamp, signature, appData); + + } + + getFlags() { + return this.appData[0]; + } + + getTypeString() { + const flags = this.getFlags(); + if(flags & Advert.ADV_TYPE_NONE) return "ADV_TYPE_NONE"; + if(flags & Advert.ADV_TYPE_CHAT) return "ADV_TYPE_CHAT"; + if(flags & Advert.ADV_TYPE_REPEATER) return "ADV_TYPE_REPEATER"; + if(flags & Advert.ADV_TYPE_ROOM) return "ADV_TYPE_ROOM"; + return null; } isVerified() { @@ -25,19 +61,32 @@ class Advert { } - static fromPacketBytes(bytes) { + parseAppData() { - // parse packet from bytes - const packet = Packet.fromBytes(bytes); + // read app data + const bufferReader = new BufferReader(this.appData); + const flags = bufferReader.readByte(); - // read packet payload - const bufferReader = new BufferReader(packet.payload); - const publicKey = bufferReader.readBytes(32); - const timestamp = bufferReader.readUInt32LE(); - const signature = bufferReader.readBytes(64); - const appData = bufferReader.readRemainingBytes(); + // parse lat lon + var lat = null; + var lon = null; + if(flags & Advert.ADV_LATLON_MASK){ + lat = bufferReader.readInt32LE(); + lon = bufferReader.readInt32LE(); + } - return new Advert(publicKey, timestamp, signature, appData); + // parse name (remainder of app data) + var name = null; + if(flags & Advert.ADV_NAME_MASK){ + name = bufferReader.readString(); + } + + return { + type: this.getTypeString(), + lat: lat, + lon: lon, + name: name, + }; } diff --git a/src/packet.js b/src/packet.js index 3de8b2b..d7f6753 100644 --- a/src/packet.js +++ b/src/packet.js @@ -1,4 +1,5 @@ import BufferReader from "./buffer_reader.js"; +import Advert from "./advert.js"; class Packet { @@ -103,6 +104,48 @@ class Packet { return this.header === 0xFF; } + parsePayload() { + switch(this.getPayloadType()){ + case Packet.PAYLOAD_TYPE_REQ: return this.parsePayloadTypeReq(); + case Packet.PAYLOAD_TYPE_ACK: return this.parsePayloadTypeAck(); + case Packet.PAYLOAD_TYPE_ADVERT: return this.parsePayloadTypeAdvert(); + default: return null; + } + } + + parsePayloadTypeReq() { + + // parse bytes + const bufferReader = new BufferReader(this.payload); + const dest = bufferReader.readByte(); + const src = bufferReader.readByte(); + const encrypted = bufferReader.readRemainingBytes(); + + // convert to hex + const destHex = dest.toString(16); + const srcHex = src.toString(16); + const encryptedHex = Buffer.from(encrypted).toString("hex"); + + return { + src: srcHex, + dest: destHex, + encrypted: encryptedHex, + }; + + } + + parsePayloadTypeAck() { + return { + ack_code: Buffer.from(this.payload).toString("hex"), + }; + } + + parsePayloadTypeAdvert() { + return { + advert: Advert.fromBytes(this.payload), + }; + } + } export default Packet;