packets.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  1. package packets
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "errors"
  6. "fmt"
  7. "io"
  8. )
  9. // ControlPacket defines the interface for structs intended to hold
  10. // decoded MQTT packets, either from being read or before being
  11. // written
  12. type ControlPacket interface {
  13. Write(io.Writer) error
  14. Unpack(io.Reader) error
  15. String() string
  16. Details() Details
  17. }
  18. // PacketNames maps the constants for each of the MQTT packet types
  19. // to a string representation of their name.
  20. var PacketNames = map[uint8]string{
  21. 1: "CONNECT",
  22. 2: "CONNACK",
  23. 3: "PUBLISH",
  24. 4: "PUBACK",
  25. 5: "PUBREC",
  26. 6: "PUBREL",
  27. 7: "PUBCOMP",
  28. 8: "SUBSCRIBE",
  29. 9: "SUBACK",
  30. 10: "UNSUBSCRIBE",
  31. 11: "UNSUBACK",
  32. 12: "PINGREQ",
  33. 13: "PINGRESP",
  34. 14: "DISCONNECT",
  35. }
  36. // Below are the constants assigned to each of the MQTT packet types
  37. const (
  38. Connect = 1
  39. Connack = 2
  40. Publish = 3
  41. Puback = 4
  42. Pubrec = 5
  43. Pubrel = 6
  44. Pubcomp = 7
  45. Subscribe = 8
  46. Suback = 9
  47. Unsubscribe = 10
  48. Unsuback = 11
  49. Pingreq = 12
  50. Pingresp = 13
  51. Disconnect = 14
  52. )
  53. // Below are the const definitions for error codes returned by
  54. // Connect()
  55. const (
  56. Accepted = 0x00
  57. ErrRefusedBadProtocolVersion = 0x01
  58. ErrRefusedIDRejected = 0x02
  59. ErrRefusedServerUnavailable = 0x03
  60. ErrRefusedBadUsernameOrPassword = 0x04
  61. ErrRefusedNotAuthorised = 0x05
  62. ErrNetworkError = 0xFE
  63. ErrProtocolViolation = 0xFF
  64. )
  65. // ConnackReturnCodes is a map of the error codes constants for Connect()
  66. // to a string representation of the error
  67. var ConnackReturnCodes = map[uint8]string{
  68. 0: "Connection Accepted",
  69. 1: "Connection Refused: Bad Protocol Version",
  70. 2: "Connection Refused: Client Identifier Rejected",
  71. 3: "Connection Refused: Server Unavailable",
  72. 4: "Connection Refused: Username or Password in unknown format",
  73. 5: "Connection Refused: Not Authorised",
  74. 254: "Connection Error",
  75. 255: "Connection Refused: Protocol Violation",
  76. }
  77. var (
  78. ErrorRefusedBadProtocolVersion = errors.New("unacceptable protocol version")
  79. ErrorRefusedIDRejected = errors.New("identifier rejected")
  80. ErrorRefusedServerUnavailable = errors.New("server Unavailable")
  81. ErrorRefusedBadUsernameOrPassword = errors.New("bad user name or password")
  82. ErrorRefusedNotAuthorised = errors.New("not Authorized")
  83. ErrorNetworkError = errors.New("network Error")
  84. ErrorProtocolViolation = errors.New("protocol Violation")
  85. )
  86. // ConnErrors is a map of the errors codes constants for Connect()
  87. // to a Go error
  88. var ConnErrors = map[byte]error{
  89. Accepted: nil,
  90. ErrRefusedBadProtocolVersion: ErrorRefusedBadProtocolVersion,
  91. ErrRefusedIDRejected: ErrorRefusedIDRejected,
  92. ErrRefusedServerUnavailable: ErrorRefusedServerUnavailable,
  93. ErrRefusedBadUsernameOrPassword: ErrorRefusedBadUsernameOrPassword,
  94. ErrRefusedNotAuthorised: ErrorRefusedNotAuthorised,
  95. ErrNetworkError: ErrorNetworkError,
  96. ErrProtocolViolation: ErrorProtocolViolation,
  97. }
  98. // ReadPacket takes an instance of an io.Reader (such as net.Conn) and attempts
  99. // to read an MQTT packet from the stream. It returns a ControlPacket
  100. // representing the decoded MQTT packet and an error. One of these returns will
  101. // always be nil, a nil ControlPacket indicating an error occurred.
  102. func ReadPacket(r io.Reader) (ControlPacket, error) {
  103. var fh FixedHeader
  104. b := make([]byte, 1)
  105. _, err := io.ReadFull(r, b)
  106. if err != nil {
  107. return nil, err
  108. }
  109. err = fh.unpack(b[0], r)
  110. if err != nil {
  111. return nil, err
  112. }
  113. cp, err := NewControlPacketWithHeader(fh)
  114. if err != nil {
  115. return nil, err
  116. }
  117. packetBytes := make([]byte, fh.RemainingLength)
  118. n, err := io.ReadFull(r, packetBytes)
  119. if err != nil {
  120. return nil, err
  121. }
  122. if n != fh.RemainingLength {
  123. return nil, errors.New("failed to read expected data")
  124. }
  125. err = cp.Unpack(bytes.NewBuffer(packetBytes))
  126. return cp, err
  127. }
  128. // NewControlPacket is used to create a new ControlPacket of the type specified
  129. // by packetType, this is usually done by reference to the packet type constants
  130. // defined in packets.go. The newly created ControlPacket is empty and a pointer
  131. // is returned.
  132. func NewControlPacket(packetType byte) ControlPacket {
  133. switch packetType {
  134. case Connect:
  135. return &ConnectPacket{FixedHeader: FixedHeader{MessageType: Connect}}
  136. case Connack:
  137. return &ConnackPacket{FixedHeader: FixedHeader{MessageType: Connack}}
  138. case Disconnect:
  139. return &DisconnectPacket{FixedHeader: FixedHeader{MessageType: Disconnect}}
  140. case Publish:
  141. return &PublishPacket{FixedHeader: FixedHeader{MessageType: Publish}}
  142. case Puback:
  143. return &PubackPacket{FixedHeader: FixedHeader{MessageType: Puback}}
  144. case Pubrec:
  145. return &PubrecPacket{FixedHeader: FixedHeader{MessageType: Pubrec}}
  146. case Pubrel:
  147. return &PubrelPacket{FixedHeader: FixedHeader{MessageType: Pubrel, Qos: 1}}
  148. case Pubcomp:
  149. return &PubcompPacket{FixedHeader: FixedHeader{MessageType: Pubcomp}}
  150. case Subscribe:
  151. return &SubscribePacket{FixedHeader: FixedHeader{MessageType: Subscribe, Qos: 1}}
  152. case Suback:
  153. return &SubackPacket{FixedHeader: FixedHeader{MessageType: Suback}}
  154. case Unsubscribe:
  155. return &UnsubscribePacket{FixedHeader: FixedHeader{MessageType: Unsubscribe, Qos: 1}}
  156. case Unsuback:
  157. return &UnsubackPacket{FixedHeader: FixedHeader{MessageType: Unsuback}}
  158. case Pingreq:
  159. return &PingreqPacket{FixedHeader: FixedHeader{MessageType: Pingreq}}
  160. case Pingresp:
  161. return &PingrespPacket{FixedHeader: FixedHeader{MessageType: Pingresp}}
  162. }
  163. return nil
  164. }
  165. // NewControlPacketWithHeader is used to create a new ControlPacket of the type
  166. // specified within the FixedHeader that is passed to the function.
  167. // The newly created ControlPacket is empty and a pointer is returned.
  168. func NewControlPacketWithHeader(fh FixedHeader) (ControlPacket, error) {
  169. switch fh.MessageType {
  170. case Connect:
  171. return &ConnectPacket{FixedHeader: fh}, nil
  172. case Connack:
  173. return &ConnackPacket{FixedHeader: fh}, nil
  174. case Disconnect:
  175. return &DisconnectPacket{FixedHeader: fh}, nil
  176. case Publish:
  177. return &PublishPacket{FixedHeader: fh}, nil
  178. case Puback:
  179. return &PubackPacket{FixedHeader: fh}, nil
  180. case Pubrec:
  181. return &PubrecPacket{FixedHeader: fh}, nil
  182. case Pubrel:
  183. return &PubrelPacket{FixedHeader: fh}, nil
  184. case Pubcomp:
  185. return &PubcompPacket{FixedHeader: fh}, nil
  186. case Subscribe:
  187. return &SubscribePacket{FixedHeader: fh}, nil
  188. case Suback:
  189. return &SubackPacket{FixedHeader: fh}, nil
  190. case Unsubscribe:
  191. return &UnsubscribePacket{FixedHeader: fh}, nil
  192. case Unsuback:
  193. return &UnsubackPacket{FixedHeader: fh}, nil
  194. case Pingreq:
  195. return &PingreqPacket{FixedHeader: fh}, nil
  196. case Pingresp:
  197. return &PingrespPacket{FixedHeader: fh}, nil
  198. }
  199. return nil, fmt.Errorf("unsupported packet type 0x%x", fh.MessageType)
  200. }
  201. // Details struct returned by the Details() function called on
  202. // ControlPackets to present details of the Qos and MessageID
  203. // of the ControlPacket
  204. type Details struct {
  205. Qos byte
  206. MessageID uint16
  207. }
  208. // FixedHeader is a struct to hold the decoded information from
  209. // the fixed header of an MQTT ControlPacket
  210. type FixedHeader struct {
  211. MessageType byte
  212. Dup bool
  213. Qos byte
  214. Retain bool
  215. RemainingLength int
  216. }
  217. func (fh FixedHeader) String() string {
  218. return fmt.Sprintf("%s: dup: %t qos: %d retain: %t rLength: %d", PacketNames[fh.MessageType], fh.Dup, fh.Qos, fh.Retain, fh.RemainingLength)
  219. }
  220. func boolToByte(b bool) byte {
  221. switch b {
  222. case true:
  223. return 1
  224. default:
  225. return 0
  226. }
  227. }
  228. func (fh *FixedHeader) pack() bytes.Buffer {
  229. var header bytes.Buffer
  230. header.WriteByte(fh.MessageType<<4 | boolToByte(fh.Dup)<<3 | fh.Qos<<1 | boolToByte(fh.Retain))
  231. header.Write(encodeLength(fh.RemainingLength))
  232. return header
  233. }
  234. func (fh *FixedHeader) unpack(typeAndFlags byte, r io.Reader) error {
  235. fh.MessageType = typeAndFlags >> 4
  236. fh.Dup = (typeAndFlags>>3)&0x01 > 0
  237. fh.Qos = (typeAndFlags >> 1) & 0x03
  238. fh.Retain = typeAndFlags&0x01 > 0
  239. var err error
  240. fh.RemainingLength, err = decodeLength(r)
  241. return err
  242. }
  243. func decodeByte(b io.Reader) (byte, error) {
  244. num := make([]byte, 1)
  245. _, err := b.Read(num)
  246. if err != nil {
  247. return 0, err
  248. }
  249. return num[0], nil
  250. }
  251. func decodeUint16(b io.Reader) (uint16, error) {
  252. num := make([]byte, 2)
  253. _, err := b.Read(num)
  254. if err != nil {
  255. return 0, err
  256. }
  257. return binary.BigEndian.Uint16(num), nil
  258. }
  259. func encodeUint16(num uint16) []byte {
  260. bytesResult := make([]byte, 2)
  261. binary.BigEndian.PutUint16(bytesResult, num)
  262. return bytesResult
  263. }
  264. func encodeString(field string) []byte {
  265. return encodeBytes([]byte(field))
  266. }
  267. func decodeString(b io.Reader) (string, error) {
  268. buf, err := decodeBytes(b)
  269. return string(buf), err
  270. }
  271. func decodeBytes(b io.Reader) ([]byte, error) {
  272. fieldLength, err := decodeUint16(b)
  273. if err != nil {
  274. return nil, err
  275. }
  276. field := make([]byte, fieldLength)
  277. _, err = b.Read(field)
  278. if err != nil {
  279. return nil, err
  280. }
  281. return field, nil
  282. }
  283. func encodeBytes(field []byte) []byte {
  284. fieldLength := make([]byte, 2)
  285. binary.BigEndian.PutUint16(fieldLength, uint16(len(field)))
  286. return append(fieldLength, field...)
  287. }
  288. func encodeLength(length int) []byte {
  289. var encLength []byte
  290. for {
  291. digit := byte(length % 128)
  292. length /= 128
  293. if length > 0 {
  294. digit |= 0x80
  295. }
  296. encLength = append(encLength, digit)
  297. if length == 0 {
  298. break
  299. }
  300. }
  301. return encLength
  302. }
  303. func decodeLength(r io.Reader) (int, error) {
  304. var rLength uint32
  305. var multiplier uint32
  306. b := make([]byte, 1)
  307. for multiplier < 27 { // fix: Infinite '(digit & 128) == 1' will cause the dead loop
  308. _, err := io.ReadFull(r, b)
  309. if err != nil {
  310. return 0, err
  311. }
  312. digit := b[0]
  313. rLength |= uint32(digit&127) << multiplier
  314. if (digit & 128) == 0 {
  315. break
  316. }
  317. multiplier += 7
  318. }
  319. return int(rLength), nil
  320. }