Files
node-metaverse/lib/classes/Packet.ts

165 lines
5.3 KiB
TypeScript
Raw Normal View History

import type { MessageBase } from './MessageBase';
import { Zerocoder } from './Zerocoder';
2017-11-26 01:14:02 +00:00
import * as MessageClass from './MessageClasses';
import { nameFromID } from './MessageClasses';
import { MessageFlags } from '../enums/MessageFlags';
import { PacketFlags } from '../enums/PacketFlags';
import type { DecodeFlags } from '../enums/DecodeFlags';
2017-11-24 01:00:56 +00:00
2017-11-26 01:14:02 +00:00
export class Packet
2017-11-24 01:00:56 +00:00
{
public packetFlags: PacketFlags = 0 as PacketFlags;
public sequenceNumber = 0;
public extraHeader: Buffer = Buffer.allocUnsafe(0);
public message: MessageBase;
public getSize(): number
2017-11-26 01:14:02 +00:00
{
let idSize = 4;
if (this.message.messageFlags & MessageFlags.FrequencyHigh)
{
idSize = 1;
}
else if (this.message.messageFlags & MessageFlags.FrequencyMedium)
{
idSize = 2;
}
return 1 + 4 + 1 + this.extraHeader.length + idSize + this.message.getSize();
}
public writeToBuffer(buf: Buffer, pos: number, options?: DecodeFlags): Buffer
2017-11-26 01:14:02 +00:00
{
if (options === undefined)
{
2023-11-09 18:06:49 +00:00
options = 0 as DecodeFlags;
}
2023-11-09 18:06:49 +00:00
if (this.message.messageFlags & MessageFlags.Zerocoded && !((options ?? 0) & 1))
2017-11-26 01:14:02 +00:00
{
this.packetFlags = this.packetFlags | PacketFlags.Zerocoded;
}
buf.writeUInt8(this.packetFlags, pos++);
buf.writeUInt32BE(this.sequenceNumber, pos);
pos = pos + 4;
buf.writeUInt8(this.extraHeader.length, pos++);
if (this.extraHeader.length > 0)
{
this.extraHeader.copy(buf, pos);
2017-11-26 01:14:02 +00:00
pos += this.extraHeader.length;
}
const bodyStart = pos;
if (this.message.messageFlags & MessageFlags.FrequencyHigh)
{
buf.writeUInt8(this.message.id, pos++);
}
else if (this.message.messageFlags & MessageFlags.FrequencyMedium)
{
buf.writeUInt16BE(this.message.id, pos);
pos += 2;
}
else
{
buf.writeUInt32BE(this.message.id, pos);
pos += 4;
}
const expectedLength = this.message.getSize();
const actualLength = this.message.writeToBuffer(buf, pos);
if (actualLength !== expectedLength)
{
console.error('WARNING: Bytes written does not match expected message data length')
}
pos += actualLength;
if (pos < buf.length)
{
console.error('WARNING: BUFFER UNDERFLOW: Finished writing but we are not at the end of the buffer (Written: ' + pos + ' bytes, expected ' + buf.length);
2017-11-26 01:14:02 +00:00
}
if (this.packetFlags & PacketFlags.Zerocoded)
{
buf = Zerocoder.Encode(buf, bodyStart, pos);
}
return buf;
}
public readFromBuffer(buf: Buffer, pos: number, ackReceived: (sequenceID: number) => void, sendAck: (sequenceID: number) => void): number
2017-11-26 01:14:02 +00:00
{
this.packetFlags = buf.readUInt8(pos++);
this.sequenceNumber = buf.readUInt32BE(pos);
if (this.packetFlags & PacketFlags.Reliable)
{
sendAck(this.sequenceNumber);
}
pos = pos + 4;
const extraBytes = buf.readUInt8(pos++);
if (extraBytes > 0)
{
this.extraHeader = buf.subarray(pos, pos + extraBytes);
2017-11-26 01:14:02 +00:00
pos += extraBytes;
}
else
{
this.extraHeader = Buffer.allocUnsafe(0);
}
let appendedAcks = 0;
if (this.packetFlags & PacketFlags.Ack)
{
appendedAcks = buf.readUInt8(buf.length - 1);
}
2017-11-26 01:14:02 +00:00
if (this.packetFlags & PacketFlags.Zerocoded)
{
// Annoyingly, the AppendedAcks aren't zerocoded so we need to stop decode early
let tail = 0;
if (this.packetFlags & PacketFlags.Ack)
{
// Final byte in the packet contains the number of Acks
tail = 1;
if (appendedAcks > 0)
{
tail += appendedAcks * 4;
}
}
buf = Zerocoder.Decode(buf, pos, buf.length - 1, tail);
2017-11-26 01:14:02 +00:00
}
let messageID = buf.readUInt8(pos);
if (messageID === 0xFF)
{
messageID = buf.readUInt16BE(pos);
if (messageID === 0xFFFF)
{
messageID = buf.readUInt32BE(pos);
pos += 4;
}
else
{
pos += 2;
}
}
else
{
pos++;
}
this.message = new (MessageClass as any)[nameFromID(messageID)]() as MessageBase;
2017-11-26 01:14:02 +00:00
2018-10-10 10:36:12 +01:00
pos += this.message.readFromBuffer(buf, pos);
2017-11-26 01:14:02 +00:00
if (this.packetFlags & PacketFlags.Ack)
{
for (let i = 0; i < appendedAcks; i++)
2017-11-26 01:14:02 +00:00
{
const ackID = buf.readUInt32BE(pos);
2017-11-26 01:14:02 +00:00
ackReceived(ackID);
pos += 4;
}
// Account for the final byte
pos++;
}
if (pos < buf.length)
{
console.error('WARNING: Finished reading ' + nameFromID(messageID) + ' but we\'re not at the end of the packet (' + pos + ' < ' + buf.length + ', seq ' + this.sequenceNumber + ')');
2017-11-26 01:14:02 +00:00
}
return pos;
2017-11-26 01:14:02 +00:00
}
2017-11-24 01:00:56 +00:00
}