Skip to content

Commit

Permalink
feat: 🎸 add encoding for auth packet
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed Oct 6, 2020
1 parent 82ac1c7 commit c6bd03f
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 27 deletions.
49 changes: 49 additions & 0 deletions src/packets/__tests__/auth.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import {PACKET_TYPE, PROPERTY} from '../../enums';
import {PacketAuth} from '../auth';
import {MqttDecoder} from '../../MqttDecoder';

test('can create a packet', () => {
const packet = PacketAuth.create(12, {});
expect(packet.b >> 4).toBe(PACKET_TYPE.AUTH);
expect(packet.l).toBe(0);
expect(packet.c).toBe(12);
expect(packet.p).toEqual({});
});

test('can serialize basic packet MQTT 5.0', () => {
const packet = PacketAuth.create(3, {});
expect(packet instanceof PacketAuth).toBe(true);
const buf = packet.toBuffer();
expect(buf).toEqual(Buffer.from([
PACKET_TYPE.AUTH << 4, // Header
0x01, // Remaining length
0x03, // Reason code
]));
});

test('can serialize packet and deserialize it back with props', () => {
const packet1 = PacketAuth.create(1, {
[PROPERTY.UserProperty]: ['test', 'test'],
});
const decoder = new MqttDecoder();
decoder.version = 5;
decoder.push(packet1.toBuffer());
const packet2 = decoder.parse()! as PacketAuth;
expect(packet2).toEqual(packet1);
expect(packet2.c).toEqual(1);
expect(packet2.p).toEqual({
[PROPERTY.UserProperty]: ['test', 'test'],
});
});

test('can serialize packet and deserialize it back without props', () => {
const packet1 = PacketAuth.create(5, {});
const decoder = new MqttDecoder();
decoder.version = 5;
const buf = packet1.toBuffer();
decoder.push(buf);
const packet2 = decoder.parse()! as PacketAuth;
expect(packet2).toEqual(packet1);
expect(packet2.c).toEqual(5);
expect(packet2.p).toEqual({});
});
27 changes: 0 additions & 27 deletions src/packets/auth.ts

This file was deleted.

44 changes: 44 additions & 0 deletions src/packets/auth/encodeAuth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {PacketAuthData} from '.';
import {genProps} from '../../util/genProps';

export const encodeDisconnect = (packet: PacketAuthData): Buffer => {
const {b, c, p} = packet;
const props = genProps(p);
const propsLength = props.length;
const remainingLength: number = 1 + propsLength;
const remainingLengthSize = remainingLength < 128 ? 1 : remainingLength < 16_384 ? 2 : remainingLength < 2_097_152 ? 3 : 4;
const bufferLength = 1 + remainingLengthSize + remainingLength;
const buf = Buffer.allocUnsafe(bufferLength);

packet.l = remainingLength;

buf.writeUInt8(b, 0);

let offset = 1;

switch (remainingLengthSize) {
case 1:
buf.writeUInt8(remainingLength, 1);
offset = 2;
break;
case 2:
buf.writeUInt16LE(((remainingLength & 0b011111110000000) << 1) | (0b10000000 | (remainingLength & 0b01111111)), 1);
offset = 3;
break;
case 3:
buf.writeUInt16LE(((0b100000000000000 | (remainingLength & 0b011111110000000)) << 1) | (0b10000000 | (remainingLength & 0b01111111)), 1);
buf.writeUInt8((remainingLength >> 14) & 0b01111111, 3);
offset = 4;
break;
case 4:
buf.writeUInt32LE((((((remainingLength >> 21) & 0b01111111) << 8) | (0b10000000 | ((remainingLength >> 14) & 0b01111111))) << 16) |
((0b100000000000000 | (remainingLength & 0b011111110000000)) << 1) | (0b10000000 | (remainingLength & 0b01111111)), 1);
offset = 5;
break;
}

buf.writeUInt8(c, offset);
props!.copy(buf, offset + 1);

return buf;
}
42 changes: 42 additions & 0 deletions src/packets/auth/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import {PACKET_TYPE} from '../../enums';
import {Packet, PacketHeaderData} from '../../packet';
import {BufferLike, Properties} from '../../types';
import {parseProps} from '../../util/parseProps';
import {encodeDisconnect} from '../disconnect/encodeDisconnect';

export interface PacketAuthData extends PacketHeaderData {
/** Authenticate Reason Code. */
c: number;
/** Properties. */
p: Properties;
}

export class PacketAuth extends Packet implements PacketAuthData {
/**
* @param c Authenticate Reason Code
* @param p Properties
*/
static create(c: number, p: Properties): PacketAuth {
return new PacketAuth(PACKET_TYPE.AUTH << 4, 0, c, p);
}

constructor(
b: number,
l: number,
public c: number,
public p: Properties,
) {
super(b, l);
}

public toBuffer(): Buffer {
return encodeDisconnect(this, 5);
}
}

export const parseAuth = (b: number, l: number, buf: BufferLike, version: number): PacketAuth => {
const c: number = buf.readUInt8(0);
let p: Properties = {};
if (l > 1) [p] = parseProps(buf, 1);
return new PacketAuth(b, l, c, p);
};

0 comments on commit c6bd03f

Please sign in to comment.