start work on sdt packets, starting with JOIN

This commit is contained in:
2024-12-05 23:01:45 -06:00
parent dc2986f1eb
commit 1fe051c1b4
3 changed files with 156 additions and 0 deletions
+58
View File
@@ -19,3 +19,61 @@ export type RootLayerPDU = {
header: string;
data: Uint8Array;
};
export enum SessionDataTransportVectors {
REL_WRAP = 1,
UNREL_WRAP,
CHANNEL_PARAMS,
JOIN,
JOIN_REFUSE,
JOIN_ACCEPT,
LEAVE,
LEAVING,
CONNECT,
CONNECT_ACCEPT,
CONNECT_REFUSE,
DISCONNECT,
DISCONNECTING,
ACK,
NAK,
GET_SESSIONS,
SESSIONS,
}
export enum TransportLayerAddressTypes {
SDT_ADDR_NULL = 0,
SDT_ADDR_IPV4,
SDT_ADDR_IPV6,
}
export type SDTChannelParams = {
expiry: number;
nakOutboundFlag: number;
nakHoldoff: number;
nakModulus: number;
nakMaxWait: number;
};
export type TransportLayerAddress = {
type: TransportLayerAddressTypes;
port?: number;
address?: string;
};
export type SDTJOINData = {
componentID: string;
memberID: number;
channelNumber: number;
reciprocalChannel: number;
totalSequenceNumber: number;
reliableSequenceNumber: number;
destinationAddress: TransportLayerAddress;
channelParameters: SDTChannelParams;
adhocExpiry: number;
};
export type SessionDataTransportPDU = {
vector: SessionDataTransportVectors;
// TODO(jwetzell): cleanup these types
data: SDTJOINData | Uint8Array;
};
+2
View File
@@ -1,4 +1,6 @@
import rlp from './rlp';
import sdt from './sdt';
export default {
rlp,
sdt,
};
+96
View File
@@ -0,0 +1,96 @@
import { SessionDataTransportPDU, SessionDataTransportVectors, TransportLayerAddress } from '../models';
import { toHex } from '../utils';
// TODO(jwetzell): work out flag inheritance, will need previous PDU
export function decode(bytes: Uint8Array): SessionDataTransportPDU {
const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
const flags = view.getUint8(0) >> 4;
const lengthFlag = ((flags >> 3) & 0x1) === 1;
const vectorFlag = ((flags >> 2) & 0x1) === 1;
if (!vectorFlag) {
throw new Error('SDT PDU must have a vector');
}
const dataFlag = (flags & 0x1) === 1;
if (!dataFlag) {
// TODO(jwetzell): idk know if this is true
throw new Error('SDT PDU must have data');
}
const lengthH = view.getUint8(0) & 0x0f;
let lengthOffset = 1;
const lengthL = view.getUint8(lengthOffset);
let length = (lengthH << 8) + lengthL;
console.log('length', length);
if (lengthFlag) {
lengthOffset += 1;
const lengthX = view.getUint8(lengthOffset);
length = (lengthH << 16) + (lengthL << 8) + lengthX;
}
let vectorOffset = lengthOffset + 1;
if (lengthFlag) {
vectorOffset += 1;
}
const vector = view.getUint8(vectorOffset);
const dataOffset = vectorOffset + 1;
// NOTE(jwetzell): flags/lengthH + lengthL + lengthX + vector
const dataLength = length - (1 + 1 + (lengthFlag ? 1 : 0) + 1);
const data = bytes.subarray(dataOffset, dataOffset + dataLength);
switch (vector) {
case SessionDataTransportVectors.JOIN:
const destinationAddress: TransportLayerAddress = {
type: view.getUint8(dataOffset + 30),
};
// TODO(jwetzell): handle IPv6, type === 2
if (destinationAddress.type === 1) {
// IPv4
destinationAddress.port = view.getUint16(dataOffset + 31);
destinationAddress.address = bytes.subarray(dataOffset + 33, dataOffset + 37).join('.');
}
const adhocExpiry = view.getUint8(dataOffset + 45);
const joinData = {
componentID: toHex(bytes.subarray(dataOffset, dataOffset + 16)),
memberID: view.getUint16(dataOffset + 16),
channelNumber: view.getUint16(dataOffset + 18),
reciprocalChannel: view.getUint16(dataOffset + 20),
totalSequenceNumber: view.getUint32(dataOffset + 22),
reliableSequenceNumber: view.getUint32(dataOffset + 26),
destinationAddress,
channelParameters: {
expiry: view.getUint8(dataOffset + 37),
nakOutboundFlag: view.getUint8(dataOffset + 38),
nakHoldoff: view.getUint16(dataOffset + 39),
nakModulus: view.getUint16(dataOffset + 41),
nakMaxWait: view.getUint16(dataOffset + 43),
},
adhocExpiry,
};
return {
vector,
data: joinData,
};
default:
console.error(`unhandled SDT vector: ${vector}`);
break;
}
return {
vector,
data,
};
}
export default {
decode,
};