connect.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. package packets
  2. import (
  3. "bytes"
  4. "fmt"
  5. "io"
  6. )
  7. // ConnectPacket is an internal representation of the fields of the
  8. // Connect MQTT packet
  9. type ConnectPacket struct {
  10. FixedHeader
  11. ProtocolName string
  12. ProtocolVersion byte
  13. CleanSession bool
  14. WillFlag bool
  15. WillQos byte
  16. WillRetain bool
  17. UsernameFlag bool
  18. PasswordFlag bool
  19. ReservedBit byte
  20. Keepalive uint16
  21. ClientIdentifier string
  22. WillTopic string
  23. WillMessage []byte
  24. Username string
  25. Password []byte
  26. }
  27. func (c *ConnectPacket) String() string {
  28. var password string
  29. if len(c.Password) > 0 {
  30. password = "<redacted>"
  31. }
  32. return fmt.Sprintf("%s protocolversion: %d protocolname: %s cleansession: %t willflag: %t WillQos: %d WillRetain: %t Usernameflag: %t Passwordflag: %t keepalive: %d clientId: %s willtopic: %s willmessage: %s Username: %s Password: %s", c.FixedHeader, c.ProtocolVersion, c.ProtocolName, c.CleanSession, c.WillFlag, c.WillQos, c.WillRetain, c.UsernameFlag, c.PasswordFlag, c.Keepalive, c.ClientIdentifier, c.WillTopic, c.WillMessage, c.Username, password)
  33. }
  34. func (c *ConnectPacket) Write(w io.Writer) error {
  35. var body bytes.Buffer
  36. var err error
  37. body.Write(encodeString(c.ProtocolName))
  38. body.WriteByte(c.ProtocolVersion)
  39. body.WriteByte(boolToByte(c.CleanSession)<<1 | boolToByte(c.WillFlag)<<2 | c.WillQos<<3 | boolToByte(c.WillRetain)<<5 | boolToByte(c.PasswordFlag)<<6 | boolToByte(c.UsernameFlag)<<7)
  40. body.Write(encodeUint16(c.Keepalive))
  41. body.Write(encodeString(c.ClientIdentifier))
  42. if c.WillFlag {
  43. body.Write(encodeString(c.WillTopic))
  44. body.Write(encodeBytes(c.WillMessage))
  45. }
  46. if c.UsernameFlag {
  47. body.Write(encodeString(c.Username))
  48. }
  49. if c.PasswordFlag {
  50. body.Write(encodeBytes(c.Password))
  51. }
  52. c.FixedHeader.RemainingLength = body.Len()
  53. packet := c.FixedHeader.pack()
  54. packet.Write(body.Bytes())
  55. _, err = packet.WriteTo(w)
  56. return err
  57. }
  58. // Unpack decodes the details of a ControlPacket after the fixed
  59. // header has been read
  60. func (c *ConnectPacket) Unpack(b io.Reader) error {
  61. var err error
  62. c.ProtocolName, err = decodeString(b)
  63. if err != nil {
  64. return err
  65. }
  66. c.ProtocolVersion, err = decodeByte(b)
  67. if err != nil {
  68. return err
  69. }
  70. options, err := decodeByte(b)
  71. if err != nil {
  72. return err
  73. }
  74. c.ReservedBit = 1 & options
  75. c.CleanSession = 1&(options>>1) > 0
  76. c.WillFlag = 1&(options>>2) > 0
  77. c.WillQos = 3 & (options >> 3)
  78. c.WillRetain = 1&(options>>5) > 0
  79. c.PasswordFlag = 1&(options>>6) > 0
  80. c.UsernameFlag = 1&(options>>7) > 0
  81. c.Keepalive, err = decodeUint16(b)
  82. if err != nil {
  83. return err
  84. }
  85. c.ClientIdentifier, err = decodeString(b)
  86. if err != nil {
  87. return err
  88. }
  89. if c.WillFlag {
  90. c.WillTopic, err = decodeString(b)
  91. if err != nil {
  92. return err
  93. }
  94. c.WillMessage, err = decodeBytes(b)
  95. if err != nil {
  96. return err
  97. }
  98. }
  99. if c.UsernameFlag {
  100. c.Username, err = decodeString(b)
  101. if err != nil {
  102. return err
  103. }
  104. }
  105. if c.PasswordFlag {
  106. c.Password, err = decodeBytes(b)
  107. if err != nil {
  108. return err
  109. }
  110. }
  111. return nil
  112. }
  113. // Validate performs validation of the fields of a Connect packet
  114. func (c *ConnectPacket) Validate() byte {
  115. if c.PasswordFlag && !c.UsernameFlag {
  116. return ErrRefusedBadUsernameOrPassword
  117. }
  118. if c.ReservedBit != 0 {
  119. // Bad reserved bit
  120. return ErrProtocolViolation
  121. }
  122. if (c.ProtocolName == "MQIsdp" && c.ProtocolVersion != 3) || (c.ProtocolName == "MQTT" && c.ProtocolVersion != 4) {
  123. // Mismatched or unsupported protocol version
  124. return ErrRefusedBadProtocolVersion
  125. }
  126. if c.ProtocolName != "MQIsdp" && c.ProtocolName != "MQTT" {
  127. // Bad protocol name
  128. return ErrProtocolViolation
  129. }
  130. if len(c.ClientIdentifier) > 65535 || len(c.Username) > 65535 || len(c.Password) > 65535 {
  131. // Bad size field
  132. return ErrProtocolViolation
  133. }
  134. if len(c.ClientIdentifier) == 0 && !c.CleanSession {
  135. // Bad client identifier
  136. return ErrRefusedIDRejected
  137. }
  138. return Accepted
  139. }
  140. // Details returns a Details struct containing the Qos and
  141. // MessageID of this ControlPacket
  142. func (c *ConnectPacket) Details() Details {
  143. return Details{Qos: 0, MessageID: 0}
  144. }