import type { CodecOpts } from "./types.ts"; import type { ProtocolLevelNoV5 } from "./protocolLevels.ts"; import { PacketType } from "./PacketType.ts"; import { BitMask } from "./BitMask.ts"; import { Encoder } from "./encoder.ts"; import { booleanFlag, Decoder, DecoderError, hasEmptyFlags, } from "./decoder.ts"; import { AuthenticationResultByNumber } from "./AuthenticationResult.ts"; import type { AuthenticationResult } from "./AuthenticationResult.ts"; import type { ReasonCode } from "./ReasonCode.ts"; import type { ConnackProperties } from "./Properties.ts"; export type ConnackPacketV4 = { type: PacketType; protocolLevel: ProtocolLevelNoV5; sessionPresent: boolean; returnCode: AuthenticationResult; }; export type ConnackPacketV5 = { type: PacketType; protocolLevel: 5; sessionPresent: boolean; reasonCode: ReasonCode; properties?: ConnackProperties; }; /** * ConnackPacket is sent from the server to the client in response to a connect packet. * It indicates that the connect is accepted. */ export type ConnackPacket = ConnackPacketV4 | ConnackPacketV5; export function encode( packet: ConnackPacket, codecOpts: CodecOpts, ): Uint8Array { if (packet.protocolLevel !== 5) { return new Uint8Array([ packet.type << 4, 2, packet.sessionPresent ? 1 : 0, packet.returnCode || 0, ]); } const encoder = new Encoder(packet.type); encoder .setByte(packet.sessionPresent ? 1 : 0) .seReasonCode(packet.reasonCode || 0) .setProperties( packet.properties || {}, packet.type, codecOpts.maxOutgoingPacketSize, ); return encoder.done(0); } export function decode( buffer: Uint8Array, flags: number, codecOpts: CodecOpts, packetType: PacketType, ): ConnackPacket { const decoder = new Decoder(packetType, buffer); hasEmptyFlags(flags); const ackflags = decoder.getByte(); if (ackflags > 1) { throw new DecoderError("Invalid Connect Acknowledge flags"); } const sessionPresent = booleanFlag(ackflags, BitMask.bit0); if (codecOpts.protocolLevel !== 5) { const returnCode = decoder.getByte() as AuthenticationResult; decoder.done(); if (!AuthenticationResultByNumber[returnCode]) { throw new DecoderError("Invalid return code"); } return { type: PacketType.connack, protocolLevel: codecOpts.protocolLevel, sessionPresent, returnCode, }; } const reasonCode = decoder.geReasonCode(); const properties = decoder.getProperties(PacketType.connack); decoder.done(); return { type: PacketType.connack, protocolLevel: 5, sessionPresent, reasonCode, properties, }; }