UNPKG

@seriousme/opifex

Version:

MQTT client & server for Deno & NodeJS

79 lines (71 loc) 2.58 kB
import type { PacketId, QoS, TopicFilter, TPacketType } from "./types.ts"; import { PacketType } from "./PacketType.ts"; import { BitMask } from "./BitMask.ts"; import { Encoder } from "./encoder.ts"; import { booleanFlag, Decoder, DecoderError } from "./decoder.ts"; /** * SubscribePacket is sent from client to server to subscribe to topics */ export type SubscribePacket = { type: TPacketType; id: PacketId; subscriptions: Subscription[]; }; /** * The topic to subscribe to and the associated QoS */ export type Subscription = { topicFilter: TopicFilter; qos: QoS; }; export const subscribe: { encode(packet: SubscribePacket): { flags: number; bytes: number[] }; decode(buffer: Uint8Array, flags: number): SubscribePacket; } = { encode(packet: SubscribePacket): { flags: number; bytes: number[] } { // Bits 3,2,1 and 0 of the fixed header of the SUBSCRIBE Control Packet are reserved and // MUST be set to 0,0,1 and 0 respectively. The Server MUST treat any other value as // malformed and close the Network Connection [MQTT-3.8.1-1]. const flags = 0b0010; const encoder = new Encoder(); encoder.setInt16(packet.id); for (const sub of packet.subscriptions) { encoder.setTopic(sub.topicFilter); encoder.setByte(sub.qos); } return { flags, bytes: encoder.done() }; }, decode(buffer: Uint8Array, flags: number): SubscribePacket { // Bits 3,2,1 and 0 of the fixed header of the SUBSCRIBE Control Packet are reserved and // MUST be set to 0,0,1 and 0 respectively. The Server MUST treat any other value as // malformed and close the Network Connection [MQTT-3.8.1-1]. if (!booleanFlag(flags, BitMask.bit1)) { throw new DecoderError("Invalid header"); } const decoder = new Decoder(buffer); const id = decoder.getInt16(); const subscriptions: Subscription[] = []; // The payload of a SUBSCRIBE packet MUST contain at least one Topic Filter / QoS pair. // A SUBSCRIBE packet with no payload is a protocol violation [MQTT-3.8.3-3]. do { const topicFilter = decoder.getTopicFilter(); const qos = decoder.getByte(); if (qos !== 0 && qos !== 1 && qos !== 2) { throw new DecoderError("Invalid qos"); } if (qos > 0 && id === 0) { throw new DecoderError("Invalid packet identifier"); } subscriptions.push({ topicFilter: topicFilter, qos, }); } while (!decoder.atEnd()); decoder.done(); return { type: PacketType.subscribe, id, subscriptions, }; }, };