package packets import ( "bytes" "errors" ) // FixedHeader contains the values of the fixed header portion of the MQTT packet. type FixedHeader struct { // Type is the type of the packet (PUBLISH, SUBSCRIBE, etc) from bits 7 - 4 (byte 1). Type byte // Dup indicates if the packet is a duplicate. Dup bool // Qos byte indicates the quality of service expected. Qos byte // Retain indicates whether the message should be retained. Retain bool // Remaining is the number of remaining bytes in the payload. Remaining int } // encode encodes the FixedHeader and returns a bytes buffer. func (fh *FixedHeader) encode(buf *bytes.Buffer) { buf.WriteByte(fh.Type<<4 | encodeBool(fh.Dup)<<3 | fh.Qos<<1 | encodeBool(fh.Retain)) encodeLength(buf, fh.Remaining) } // Encode encodes the FixedHeader and returns a bytes buffer. /*func (fh *FixedHeader) encode() bytes.Buffer { var encoded bytes.Buffer // Encode flags. encoded.WriteByte(fh.Type<<4 | encodeBool(fh.Dup)<<3 | fh.Qos<<1 | encodeBool(fh.Retain)) // Determine encoded length and write the buffer. encoded.Write(encodeLength(fh.Remaining)) return encoded } */ // decode extracts the specification bits from the header byte. func (fh *FixedHeader) decode(headerByte byte) error { // Get the message type from the first 4 bytes. fh.Type = headerByte >> 4 // @SPEC [MQTT-2.2.2-1] // Where a flag bit is marked as “Reserved” in Table 2.2 - Flag Bits, // it is reserved for future use and MUST be set to the value listed in that table. switch fh.Type { case Publish: fh.Dup = (headerByte>>3)&0x01 > 0 // Extract flags. Check if message is duplicate. fh.Qos = (headerByte >> 1) & 0x03 // Extract QoS flag. fh.Retain = headerByte&0x01 > 0 // Extract retain flag. case Pubrel: fh.Qos = (headerByte >> 1) & 0x03 case Subscribe: fh.Qos = (headerByte >> 1) & 0x03 case Unsubscribe: fh.Qos = (headerByte >> 1) & 0x03 default: // [MQTT-2.2.2-2] // If invalid flags are received, the receiver MUST close the Network Connection. if (headerByte>>3)&0x01 > 0 || (headerByte>>1)&0x03 > 0 || headerByte&0x01 > 0 { return errors.New(ErrInvalidFlags) } } return nil } // encodeLength creates length bits for the header. /*func encodeLength(length int) []byte { encodedLength := make([]byte, 0, 8) for { digit := byte(length % 128) length /= 128 if length > 0 { digit |= 0x80 } encodedLength = append(encodedLength, digit) if length == 0 { break } } return encodedLength } */ // encodeLength writes length bits for the header. func encodeLength(buf *bytes.Buffer, length int) { for { digit := byte(length % 128) length /= 128 if length > 0 { digit |= 0x80 } buf.WriteByte(digit) if length == 0 { break } } }