import { PacketType } from "./PacketType.ts"; import { Decoder, hasEmptyFlags, isEmptyBuf } from "./decoder.ts"; import type { CodecOpts } from "./types.ts"; import type { ProtocolLevelNoV5 } from "./protocolLevels.ts"; import type { DisconnectProperties } from "./Properties.ts"; import { Encoder } from "./encoder.ts"; import { ReasonCode } from "./ReasonCode.ts"; export type DisconnectPacketv4 = { type: PacketType; protocolLevel: ProtocolLevelNoV5; }; export type DisconnectPacketv5 = { type: PacketType; protocolLevel: 5; reasonCode: ReasonCode; properties?: DisconnectProperties; }; /** * DisconnectPacket is the final control packet sent from the client to the server. * It indicates that the client is disconnecting cleanly. */ export type DisconnectPacket = DisconnectPacketv4 | DisconnectPacketv5; const DISCONNECT_PACKET = new Uint8Array([PacketType.disconnect << 4, 0]); export function encode( packet: DisconnectPacket, codecOpts: CodecOpts, ): Uint8Array { if (packet.protocolLevel !== 5) { return DISCONNECT_PACKET; } const reasonCode = packet.reasonCode || ReasonCode.normalDisconnection; const encoder = new Encoder(packet.type); // see MQTT v5 3.14.2.1 // if remaining length is less than 1 the value of 0x00 (normal disconnect) is used. if ( reasonCode === ReasonCode.normalDisconnection && Object.keys(packet.properties || {}).length === 0 ) { return encoder.done(0); } encoder .seReasonCode(reasonCode); if (packet.properties) { encoder.setProperties( packet.properties, packet.type, codecOpts.maxOutgoingPacketSize, ); } return encoder.done(0); } export function decode( buffer: Uint8Array, flags: number, codecOpts: CodecOpts, packetType: PacketType, ): DisconnectPacket { hasEmptyFlags(flags); if (codecOpts.protocolLevel !== 5) { isEmptyBuf(buffer); return { type: PacketType.disconnect, protocolLevel: codecOpts.protocolLevel, }; } const decoder = new Decoder(packetType, buffer); if (decoder.atEnd()) { return { type: PacketType.disconnect, protocolLevel: 5, reasonCode: 0, }; } const reasonCode = decoder.geReasonCode(); const properties = decoder.getProperties(PacketType.disconnect); decoder.done(); return { type: PacketType.disconnect, protocolLevel: 5, reasonCode, properties, }; }