connect.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. package packets
  2. import (
  3. "bytes"
  4. "fmt"
  5. "github.com/pborman/uuid"
  6. "io"
  7. )
  8. //ConnectPacket is an internal representation of the fields of the
  9. //Connect MQTT packet
  10. type ConnectPacket struct {
  11. FixedHeader
  12. ProtocolName string
  13. ProtocolVersion byte
  14. CleanSession bool
  15. WillFlag bool
  16. WillQos byte
  17. WillRetain bool
  18. UsernameFlag bool
  19. PasswordFlag bool
  20. ReservedBit byte
  21. KeepaliveTimer uint16
  22. ClientIdentifier string
  23. WillTopic string
  24. WillMessage []byte
  25. Username string
  26. Password []byte
  27. uuid uuid.UUID
  28. }
  29. func (c *ConnectPacket) String() string {
  30. str := fmt.Sprintf("%s\n", c.FixedHeader)
  31. str += fmt.Sprintf("protocolversion: %d protocolname: %s cleansession: %t willflag: %t WillQos: %d WillRetain: %t Usernameflag: %t Passwordflag: %t keepalivetimer: %d\nclientId: %s\nwilltopic: %s\nwillmessage: %s\nUsername: %s\nPassword: %s\n", c.ProtocolVersion, c.ProtocolName, c.CleanSession, c.WillFlag, c.WillQos, c.WillRetain, c.UsernameFlag, c.PasswordFlag, c.KeepaliveTimer, c.ClientIdentifier, c.WillTopic, c.WillMessage, c.Username, c.Password)
  32. return str
  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.KeepaliveTimer))
  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) {
  61. c.ProtocolName = decodeString(b)
  62. c.ProtocolVersion = decodeByte(b)
  63. options := decodeByte(b)
  64. c.ReservedBit = 1 & options
  65. c.CleanSession = 1&(options>>1) > 0
  66. c.WillFlag = 1&(options>>2) > 0
  67. c.WillQos = 3 & (options >> 3)
  68. c.WillRetain = 1&(options>>5) > 0
  69. c.PasswordFlag = 1&(options>>6) > 0
  70. c.UsernameFlag = 1&(options>>7) > 0
  71. c.KeepaliveTimer = decodeUint16(b)
  72. c.ClientIdentifier = decodeString(b)
  73. if c.WillFlag {
  74. c.WillTopic = decodeString(b)
  75. c.WillMessage = decodeBytes(b)
  76. }
  77. if c.UsernameFlag {
  78. c.Username = decodeString(b)
  79. }
  80. if c.PasswordFlag {
  81. c.Password = decodeBytes(b)
  82. }
  83. }
  84. //Validate performs validation of the fields of a Connect packet
  85. func (c *ConnectPacket) Validate() byte {
  86. if c.PasswordFlag && !c.UsernameFlag {
  87. return ErrRefusedBadUsernameOrPassword
  88. }
  89. if c.ReservedBit != 0 {
  90. //Bad reserved bit
  91. return ErrProtocolViolation
  92. }
  93. if (c.ProtocolName == "MQIsdp" && c.ProtocolVersion != 3) || (c.ProtocolName == "MQTT" && c.ProtocolVersion != 4) {
  94. //Mismatched or unsupported protocol version
  95. return ErrRefusedBadProtocolVersion
  96. }
  97. if c.ProtocolName != "MQIsdp" && c.ProtocolName != "MQTT" {
  98. //Bad protocol name
  99. return ErrProtocolViolation
  100. }
  101. if len(c.ClientIdentifier) > 65535 || len(c.Username) > 65535 || len(c.Password) > 65535 {
  102. //Bad size field
  103. return ErrProtocolViolation
  104. }
  105. return Accepted
  106. }
  107. //Details returns a Details struct containing the Qos and
  108. //MessageID of this ControlPacket
  109. func (c *ConnectPacket) Details() Details {
  110. return Details{Qos: 0, MessageID: 0}
  111. }
  112. //UUID returns the unique ID assigned to the ControlPacket when
  113. //it was originally received. Note: this is not related to the
  114. //MessageID field for MQTT packets
  115. func (c *ConnectPacket) UUID() uuid.UUID {
  116. return c.uuid
  117. }