1package packets 2 3import ( 4 "bytes" 5 "fmt" 6 "io" 7) 8 9//PublishPacket is an internal representation of the fields of the 10//Publish MQTT packet 11type PublishPacket struct { 12 FixedHeader 13 TopicName string 14 MessageID uint16 15 Payload []byte 16} 17 18func (p *PublishPacket) String() string { 19 str := fmt.Sprintf("%s", p.FixedHeader) 20 str += " " 21 str += fmt.Sprintf("topicName: %s MessageID: %d", p.TopicName, p.MessageID) 22 str += " " 23 str += fmt.Sprintf("payload: %s", string(p.Payload)) 24 return str 25} 26 27func (p *PublishPacket) Write(w io.Writer) error { 28 var body bytes.Buffer 29 var err error 30 31 body.Write(encodeString(p.TopicName)) 32 if p.Qos > 0 { 33 body.Write(encodeUint16(p.MessageID)) 34 } 35 p.FixedHeader.RemainingLength = body.Len() + len(p.Payload) 36 packet := p.FixedHeader.pack() 37 packet.Write(body.Bytes()) 38 packet.Write(p.Payload) 39 _, err = w.Write(packet.Bytes()) 40 41 return err 42} 43 44//Unpack decodes the details of a ControlPacket after the fixed 45//header has been read 46func (p *PublishPacket) Unpack(b io.Reader) error { 47 var payloadLength = p.FixedHeader.RemainingLength 48 p.TopicName = decodeString(b) 49 if p.Qos > 0 { 50 p.MessageID = decodeUint16(b) 51 payloadLength -= len(p.TopicName) + 4 52 } else { 53 payloadLength -= len(p.TopicName) + 2 54 } 55 if payloadLength < 0 { 56 return fmt.Errorf("Error upacking publish, payload length < 0") 57 } 58 p.Payload = make([]byte, payloadLength) 59 _, err := b.Read(p.Payload) 60 61 return err 62} 63 64//Copy creates a new PublishPacket with the same topic and payload 65//but an empty fixed header, useful for when you want to deliver 66//a message with different properties such as Qos but the same 67//content 68func (p *PublishPacket) Copy() *PublishPacket { 69 newP := NewControlPacket(Publish).(*PublishPacket) 70 newP.TopicName = p.TopicName 71 newP.Payload = p.Payload 72 73 return newP 74} 75 76//Details returns a Details struct containing the Qos and 77//MessageID of this ControlPacket 78func (p *PublishPacket) Details() Details { 79 return Details{Qos: p.Qos, MessageID: p.MessageID} 80} 81