No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

113 líneas
2.6 KiB

  1. package packet
  2. import (
  3. "errors"
  4. "github.com/yosssi/gmq/mqtt"
  5. )
  6. // Minimum length of the fixed header of the SUBACK Packet
  7. const minLenSUBACKFixedHeader = 2
  8. // Length of the variable header of the SUBACK Packet
  9. const lenSUBACKVariableHeader = 2
  10. // Return Code Failure
  11. const SUBACKRetFailure byte = 0x80
  12. // Error value
  13. var ErrInvalidSUBACKReturnCode = errors.New("invalid SUBACK Return Code")
  14. // SUBACK represents a SUBACK Packet.
  15. type SUBACK struct {
  16. base
  17. // PacketID is the Packet Identifier of the variable header.
  18. PacketID uint16
  19. // ReturnCodes is the Return Codes of the payload.
  20. ReturnCodes []byte
  21. }
  22. // NewSUBACKFromBytes creates a SUBACK Packet
  23. // from the byte data and returns it.
  24. func NewSUBACKFromBytes(fixedHeader FixedHeader, remaining []byte) (Packet, error) {
  25. // Validate the byte data.
  26. if err := validateSUBACKBytes(fixedHeader, remaining); err != nil {
  27. return nil, err
  28. }
  29. // Extract the variable header.
  30. variableHeader := remaining[0:lenSUBACKVariableHeader]
  31. // Extract the payload.
  32. payload := remaining[lenSUBACKVariableHeader:]
  33. // Decode the Packet Identifier.
  34. // No error occur because of the precedent validation and
  35. // the returned error is not be taken care of.
  36. packetID, _ := decodeUint16(variableHeader)
  37. // Create a PUBACK Packet.
  38. p := &SUBACK{
  39. PacketID: packetID,
  40. ReturnCodes: payload,
  41. }
  42. // Set the fixed header to the Packet.
  43. p.fixedHeader = fixedHeader
  44. // Set the variable header to the Packet.
  45. p.variableHeader = variableHeader
  46. // Set the payload to the Packet.
  47. p.payload = payload
  48. // Return the Packet.
  49. return p, nil
  50. }
  51. // validateSUBACKBytes validates the fixed header and the remaining.
  52. func validateSUBACKBytes(fixedHeader FixedHeader, remaining []byte) error {
  53. // Extract the MQTT Control Packet type.
  54. ptype, err := fixedHeader.ptype()
  55. if err != nil {
  56. return err
  57. }
  58. // Check the length of the fixed header.
  59. if len(fixedHeader) < minLenSUBACKFixedHeader {
  60. return ErrInvalidFixedHeaderLen
  61. }
  62. // Check the MQTT Control Packet type.
  63. if ptype != TypeSUBACK {
  64. return ErrInvalidPacketType
  65. }
  66. // Check the reserved bits of the fixed header.
  67. if fixedHeader[0]<<4 != 0x00 {
  68. return ErrInvalidFixedHeader
  69. }
  70. // Check the length of the remaining.
  71. if len(remaining) < lenSUBACKVariableHeader+1 {
  72. return ErrInvalidRemainingLen
  73. }
  74. // Extract the Packet Identifier.
  75. packetID, _ := decodeUint16(remaining[0:lenSUBACKVariableHeader])
  76. // Check the Packet Identifier.
  77. if packetID == 0 {
  78. return ErrInvalidPacketID
  79. }
  80. // Check each Return Code.
  81. for _, b := range remaining[lenSUBACKVariableHeader:] {
  82. if !mqtt.ValidQoS(b) && b != SUBACKRetFailure {
  83. return ErrInvalidSUBACKReturnCode
  84. }
  85. }
  86. return nil
  87. }