You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

117 lines
3.2 KiB

  1. package packet
  2. import "errors"
  3. // Length of the fixed header of the CONNACK Packet
  4. const lenCONNACKFixedHeader = 2
  5. // Length of the variable header of the CONNACK Packet
  6. const lenCONNACKVariableHeader = 2
  7. // Connect Return code values
  8. const (
  9. connRetAccepted byte = 0x00
  10. connRetUnacceptableProtocolVersion byte = 0x01
  11. connRetIdentifierRejected byte = 0x02
  12. connRetServerUnavailable byte = 0x03
  13. connRetBadUserNameOrPassword byte = 0x04
  14. connRetNotAuthorized byte = 0x05
  15. )
  16. // Error values
  17. var (
  18. ErrInvalidFixedHeader = errors.New("invalid fixed header")
  19. ErrInvalidVariableHeaderLen = errors.New("invalid length of the variable header")
  20. ErrInvalidRemainingLen = errors.New("invalid length of the remaining")
  21. ErrInvalidVariableHeader = errors.New("invalid variable header")
  22. ErrInvalidRemainingLength = errors.New("invalid Remaining Length")
  23. ErrInvalidConnectReturnCode = errors.New("invalid Connect Return code")
  24. )
  25. // CONNACK represents a CONNACK Packet.
  26. type CONNACK struct {
  27. base
  28. // sessionPresent is the Session Present of the variable header.
  29. sessionPresent bool
  30. // connectReturnCode is the Connect Return code of the variable header.
  31. connectReturnCode byte
  32. }
  33. // NewCONNACKFromBytes creates the CONNACK Packet
  34. // from the byte data and returns it.
  35. func NewCONNACKFromBytes(fixedHeader FixedHeader, variableHeader []byte) (Packet, error) {
  36. // Validate the byte data.
  37. if err := validateCONNACKBytes(fixedHeader, variableHeader); err != nil {
  38. return nil, err
  39. }
  40. // Create a CONNACK Packet.
  41. p := &CONNACK{
  42. sessionPresent: variableHeader[0]<<7 == 0x80,
  43. connectReturnCode: variableHeader[1],
  44. }
  45. // Set the fixed header to the Packet.
  46. p.fixedHeader = fixedHeader
  47. // Set the variable header to the Packet.
  48. p.variableHeader = variableHeader
  49. // Return the Packet.
  50. return p, nil
  51. }
  52. // validateCONNACKBytes validates the fixed header and the variable header.
  53. func validateCONNACKBytes(fixedHeader FixedHeader, variableHeader []byte) error {
  54. // Extract the MQTT Control Packet type.
  55. ptype, err := fixedHeader.ptype()
  56. if err != nil {
  57. return err
  58. }
  59. // Check the length of the fixed header.
  60. if len(fixedHeader) != lenCONNACKFixedHeader {
  61. return ErrInvalidFixedHeaderLen
  62. }
  63. // Check the MQTT Control Packet type.
  64. if ptype != TypeCONNACK {
  65. return ErrInvalidPacketType
  66. }
  67. // Check the reserved bits of the fixed header.
  68. if fixedHeader[0]<<4 != 0x00 {
  69. return ErrInvalidFixedHeader
  70. }
  71. // Check the Remaining Length of the fixed header.
  72. if fixedHeader[1] != lenCONNACKVariableHeader {
  73. return ErrInvalidRemainingLength
  74. }
  75. // Check the length of the variable header.
  76. if len(variableHeader) != lenCONNACKVariableHeader {
  77. return ErrInvalidVariableHeaderLen
  78. }
  79. // Check the reserved bits of the variable header.
  80. if variableHeader[0]>>1 != 0x00 {
  81. return ErrInvalidVariableHeader
  82. }
  83. // Check the Connect Return code of the variable header.
  84. switch variableHeader[1] {
  85. case
  86. connRetAccepted,
  87. connRetUnacceptableProtocolVersion,
  88. connRetIdentifierRejected,
  89. connRetServerUnavailable,
  90. connRetBadUserNameOrPassword,
  91. connRetNotAuthorized:
  92. default:
  93. return ErrInvalidConnectReturnCode
  94. }
  95. return nil
  96. }