package packet import "errors" // Length of the fixed header of the CONNACK Packet const lenCONNACKFixedHeader = 2 // Length of the variable header of the CONNACK Packet const lenCONNACKVariableHeader = 2 // Connect Return code values const ( connRetAccepted byte = 0x00 connRetUnacceptableProtocolVersion byte = 0x01 connRetIdentifierRejected byte = 0x02 connRetServerUnavailable byte = 0x03 connRetBadUserNameOrPassword byte = 0x04 connRetNotAuthorized byte = 0x05 ) // Error values var ( ErrInvalidFixedHeader = errors.New("invalid fixed header") ErrInvalidVariableHeaderLen = errors.New("invalid length of the variable header") ErrInvalidRemainingLen = errors.New("invalid length of the remaining") ErrInvalidVariableHeader = errors.New("invalid variable header") ErrInvalidRemainingLength = errors.New("invalid Remaining Length") ErrInvalidConnectReturnCode = errors.New("invalid Connect Return code") ) // CONNACK represents a CONNACK Packet. type CONNACK struct { base // sessionPresent is the Session Present of the variable header. sessionPresent bool // connectReturnCode is the Connect Return code of the variable header. connectReturnCode byte } // NewCONNACKFromBytes creates the CONNACK Packet // from the byte data and returns it. func NewCONNACKFromBytes(fixedHeader FixedHeader, variableHeader []byte) (Packet, error) { // Validate the byte data. if err := validateCONNACKBytes(fixedHeader, variableHeader); err != nil { return nil, err } // Create a CONNACK Packet. p := &CONNACK{ sessionPresent: variableHeader[0]<<7 == 0x80, connectReturnCode: variableHeader[1], } // Set the fixed header to the Packet. p.fixedHeader = fixedHeader // Set the variable header to the Packet. p.variableHeader = variableHeader // Return the Packet. return p, nil } // validateCONNACKBytes validates the fixed header and the variable header. func validateCONNACKBytes(fixedHeader FixedHeader, variableHeader []byte) error { // Extract the MQTT Control Packet type. ptype, err := fixedHeader.ptype() if err != nil { return err } // Check the length of the fixed header. if len(fixedHeader) != lenCONNACKFixedHeader { return ErrInvalidFixedHeaderLen } // Check the MQTT Control Packet type. if ptype != TypeCONNACK { return ErrInvalidPacketType } // Check the reserved bits of the fixed header. if fixedHeader[0]<<4 != 0x00 { return ErrInvalidFixedHeader } // Check the Remaining Length of the fixed header. if fixedHeader[1] != lenCONNACKVariableHeader { return ErrInvalidRemainingLength } // Check the length of the variable header. if len(variableHeader) != lenCONNACKVariableHeader { return ErrInvalidVariableHeaderLen } // Check the reserved bits of the variable header. if variableHeader[0]>>1 != 0x00 { return ErrInvalidVariableHeader } // Check the Connect Return code of the variable header. switch variableHeader[1] { case connRetAccepted, connRetUnacceptableProtocolVersion, connRetIdentifierRejected, connRetServerUnavailable, connRetBadUserNameOrPassword, connRetNotAuthorized: default: return ErrInvalidConnectReturnCode } return nil }