publish.go 2.0 KB

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