Skip to content

Commit 15aee8e

Browse files
committed
feat: 🎸 add encoding for puback
1 parent ac43901 commit 15aee8e

File tree

5 files changed

+135
-2
lines changed

5 files changed

+135
-2
lines changed

‎src/packets/__tests__/connect.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {PROPERTY} from '../../../es6/enums';
1+
import {PROPERTY} from '../../enums';
22
import {PACKET_TYPE} from '../../enums';
33
import {PacketConnect} from '../connect';
44
import {MqttDecoder} from '../../MqttDecoder';
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import {PACKET_TYPE, PROPERTY} from '../../enums';
2+
import {PacketPuback} from '../puback';
3+
import {MqttDecoder} from '../../MqttDecoder';
4+
5+
test('can create a packet', () => {
6+
const packet = PacketPuback.create(0, 0, {});
7+
expect(packet.b >> 4).toBe(PACKET_TYPE.PUBACK);
8+
expect(packet.l).toBe(0);
9+
expect(packet.i).toBe(0);
10+
expect(packet.c).toBe(0);
11+
expect(packet.p).toEqual({});
12+
});
13+
14+
test('can serialize basic packet MQTT 5.0', () => {
15+
const packet = PacketPuback.create(0, 0, {});
16+
expect(packet instanceof PacketPuback).toBe(true);
17+
const buf = packet.toBuffer(5);
18+
expect(buf).toEqual(Buffer.from([
19+
0x40, // Header
20+
0x04, // Remaining length
21+
0x00, 0x00, // Packet Identifier
22+
0x00, // Reason code
23+
0x00 // Properties
24+
]));
25+
});
26+
27+
test('can serialize basic packet MQTT 3.1.1', () => {
28+
const packet = PacketPuback.create(0, 0, {});
29+
expect(packet instanceof PacketPuback).toBe(true);
30+
const buf = packet.toBuffer(3);
31+
expect(buf).toEqual(Buffer.from([
32+
0x40, // Header
33+
0x02, // Remaining length
34+
0x00, 0x00, // Packet Identifier
35+
]));
36+
});
37+
38+
test('can serialize packet and deserialize it back', () => {
39+
const packet1 = PacketPuback.create(1, 2, {});
40+
const decoder = new MqttDecoder();
41+
decoder.version = 5;
42+
decoder.push(packet1.toBuffer(5));
43+
const packet2 = decoder.parse()! as PacketPuback;
44+
expect(packet2).toEqual(packet1);
45+
expect(packet2.i).toEqual(1);
46+
expect(packet2.c).toEqual(2);
47+
expect(packet2.p).toEqual({});
48+
});
49+
50+
test('can serialize packet and deserialize it with props', () => {
51+
const packet1 = PacketPuback.create(1, 2, {
52+
[PROPERTY.UserProperty]: [
53+
['a', 'b'],
54+
],
55+
});
56+
const decoder = new MqttDecoder();
57+
decoder.version = 5;
58+
decoder.push(packet1.toBuffer(5));
59+
const packet2 = decoder.parse()! as PacketPuback;
60+
expect(packet2).toEqual(packet1);
61+
expect(packet2.i).toEqual(1);
62+
expect(packet2.c).toEqual(2);
63+
expect(packet2.p).toEqual({
64+
[PROPERTY.UserProperty]: [
65+
['a', 'b'],
66+
],
67+
});
68+
});
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import {PacketPubackData} from '.';
2+
import {genProps} from '../../util/genProps/v7';
3+
4+
export const encodePuback = (packet: PacketPubackData, version: number): Buffer => {
5+
const {b, i, c, p} = packet;
6+
const isV5 = version === 5;
7+
const reasonCodeLength = isV5 ? 1 : 0;
8+
const props = isV5 ? genProps(p) : null;
9+
const propsLength = props ? props.length : 0;
10+
const remainingLength: number = packet.l = 2 + reasonCodeLength + propsLength;
11+
const remainingLengthSize = remainingLength < 128 ? 1 : remainingLength < 16_384 ? 2 : remainingLength < 2_097_152 ? 3 : 4;
12+
const bufferLength = 1 + remainingLengthSize + remainingLength;
13+
const buf = Buffer.allocUnsafe(bufferLength);
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.writeUInt16BE(i, offset);
41+
offset += 2;
42+
43+
if (isV5) {
44+
buf.writeUInt8(c, offset);
45+
offset += 1;
46+
props!.copy(buf, offset);
47+
}
48+
49+
return buf;
50+
}

‎src/packets/puback/index.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
import { PACKET_TYPE } from '../../enums';
12
import {Packet, PacketHeaderData} from '../../packet';
23
import {BufferLike, Properties} from '../../types';
34
import {parseProps} from '../../util/parse';
5+
import {encodePuback} from './encodePuback';
46

57
export interface PacketPubackData extends PacketHeaderData {
68
/** Packet Identifier. */
@@ -12,6 +14,15 @@ export interface PacketPubackData extends PacketHeaderData {
1214
}
1315

1416
export class PacketPuback extends Packet implements PacketPubackData {
17+
/**
18+
* @param i Packet Identifier
19+
* @param c Reason Code
20+
* @param p Properties
21+
*/
22+
static create(i: number, c: number, p: Properties) {
23+
return new PacketPuback(PACKET_TYPE.PUBACK << 4, 0, i, c, p);
24+
}
25+
1526
constructor(
1627
b: number,
1728
l: number,
@@ -21,6 +32,10 @@ export class PacketPuback extends Packet implements PacketPubackData {
2132
) {
2233
super(b, l);
2334
}
35+
36+
public toBuffer(version: number) {
37+
return encodePuback(this, version);
38+
}
2439
}
2540

2641
export const parsePuback = (b: number, l: number, data: BufferLike, version: number): PacketPuback => {

‎src/packets/publish/encodePublish/__tests__/encodePublish.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {PacketPublish} from '../..';
2-
import {PROPERTY} from '../../../../../es6/enums';
2+
import {PROPERTY} from '../../../../enums';
33
import {MqttDecoder} from '../../../../MqttDecoder';
44
import {encodePublish as v1} from '../v1';
55
import {encodePublish as v2} from '../v2';

0 commit comments

Comments
 (0)