Skip to content

Commit c6bd03f

Browse files
committed
feat: 🎸 add encoding for auth packet
1 parent 82ac1c7 commit c6bd03f

File tree

4 files changed

+135
-27
lines changed

4 files changed

+135
-27
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import {PACKET_TYPE, PROPERTY} from '../../enums';
2+
import {PacketAuth} from '../auth';
3+
import {MqttDecoder} from '../../MqttDecoder';
4+
5+
test('can create a packet', () => {
6+
const packet = PacketAuth.create(12, {});
7+
expect(packet.b >> 4).toBe(PACKET_TYPE.AUTH);
8+
expect(packet.l).toBe(0);
9+
expect(packet.c).toBe(12);
10+
expect(packet.p).toEqual({});
11+
});
12+
13+
test('can serialize basic packet MQTT 5.0', () => {
14+
const packet = PacketAuth.create(3, {});
15+
expect(packet instanceof PacketAuth).toBe(true);
16+
const buf = packet.toBuffer();
17+
expect(buf).toEqual(Buffer.from([
18+
PACKET_TYPE.AUTH << 4, // Header
19+
0x01, // Remaining length
20+
0x03, // Reason code
21+
]));
22+
});
23+
24+
test('can serialize packet and deserialize it back with props', () => {
25+
const packet1 = PacketAuth.create(1, {
26+
[PROPERTY.UserProperty]: ['test', 'test'],
27+
});
28+
const decoder = new MqttDecoder();
29+
decoder.version = 5;
30+
decoder.push(packet1.toBuffer());
31+
const packet2 = decoder.parse()! as PacketAuth;
32+
expect(packet2).toEqual(packet1);
33+
expect(packet2.c).toEqual(1);
34+
expect(packet2.p).toEqual({
35+
[PROPERTY.UserProperty]: ['test', 'test'],
36+
});
37+
});
38+
39+
test('can serialize packet and deserialize it back without props', () => {
40+
const packet1 = PacketAuth.create(5, {});
41+
const decoder = new MqttDecoder();
42+
decoder.version = 5;
43+
const buf = packet1.toBuffer();
44+
decoder.push(buf);
45+
const packet2 = decoder.parse()! as PacketAuth;
46+
expect(packet2).toEqual(packet1);
47+
expect(packet2.c).toEqual(5);
48+
expect(packet2.p).toEqual({});
49+
});

‎src/packets/auth.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

‎src/packets/auth/encodeAuth.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import {PacketAuthData} from '.';
2+
import {genProps} from '../../util/genProps';
3+
4+
export const encodeDisconnect = (packet: PacketAuthData): Buffer => {
5+
const {b, c, p} = packet;
6+
const props = genProps(p);
7+
const propsLength = props.length;
8+
const remainingLength: number = 1 + propsLength;
9+
const remainingLengthSize = remainingLength < 128 ? 1 : remainingLength < 16_384 ? 2 : remainingLength < 2_097_152 ? 3 : 4;
10+
const bufferLength = 1 + remainingLengthSize + remainingLength;
11+
const buf = Buffer.allocUnsafe(bufferLength);
12+
13+
packet.l = remainingLength;
14+
15+
buf.writeUInt8(b, 0);
16+
17+
let offset = 1;
18+
19+
switch (remainingLengthSize) {
20+
case 1:
21+
buf.writeUInt8(remainingLength, 1);
22+
offset = 2;
23+
break;
24+
case 2:
25+
buf.writeUInt16LE(((remainingLength & 0b011111110000000) << 1) | (0b10000000 | (remainingLength & 0b01111111)), 1);
26+
offset = 3;
27+
break;
28+
case 3:
29+
buf.writeUInt16LE(((0b100000000000000 | (remainingLength & 0b011111110000000)) << 1) | (0b10000000 | (remainingLength & 0b01111111)), 1);
30+
buf.writeUInt8((remainingLength >> 14) & 0b01111111, 3);
31+
offset = 4;
32+
break;
33+
case 4:
34+
buf.writeUInt32LE((((((remainingLength >> 21) & 0b01111111) << 8) | (0b10000000 | ((remainingLength >> 14) & 0b01111111))) << 16) |
35+
((0b100000000000000 | (remainingLength & 0b011111110000000)) << 1) | (0b10000000 | (remainingLength & 0b01111111)), 1);
36+
offset = 5;
37+
break;
38+
}
39+
40+
buf.writeUInt8(c, offset);
41+
props!.copy(buf, offset + 1);
42+
43+
return buf;
44+
}

‎src/packets/auth/index.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import {PACKET_TYPE} from '../../enums';
2+
import {Packet, PacketHeaderData} from '../../packet';
3+
import {BufferLike, Properties} from '../../types';
4+
import {parseProps} from '../../util/parseProps';
5+
import {encodeDisconnect} from '../disconnect/encodeDisconnect';
6+
7+
export interface PacketAuthData extends PacketHeaderData {
8+
/** Authenticate Reason Code. */
9+
c: number;
10+
/** Properties. */
11+
p: Properties;
12+
}
13+
14+
export class PacketAuth extends Packet implements PacketAuthData {
15+
/**
16+
* @param c Authenticate Reason Code
17+
* @param p Properties
18+
*/
19+
static create(c: number, p: Properties): PacketAuth {
20+
return new PacketAuth(PACKET_TYPE.AUTH << 4, 0, c, p);
21+
}
22+
23+
constructor(
24+
b: number,
25+
l: number,
26+
public c: number,
27+
public p: Properties,
28+
) {
29+
super(b, l);
30+
}
31+
32+
public toBuffer(): Buffer {
33+
return encodeDisconnect(this, 5);
34+
}
35+
}
36+
37+
export const parseAuth = (b: number, l: number, buf: BufferLike, version: number): PacketAuth => {
38+
const c: number = buf.readUInt8(0);
39+
let p: Properties = {};
40+
if (l > 1) [p] = parseProps(buf, 1);
41+
return new PacketAuth(b, l, c, p);
42+
};

0 commit comments

Comments
 (0)