MqttMsgSuback.cs 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /*
  2. Copyright (c) 2013, 2014 Paolo Patierno
  3. All rights reserved. This program and the accompanying materials
  4. are made available under the terms of the Eclipse Public License v1.0
  5. and Eclipse Distribution License v1.0 which accompany this distribution.
  6. The Eclipse Public License is available at
  7. http://www.eclipse.org/legal/epl-v10.html
  8. and the Eclipse Distribution License is available at
  9. http://www.eclipse.org/org/documents/edl-v10.php.
  10. Contributors:
  11. Paolo Patierno - initial API and implementation and/or initial documentation
  12. */
  13. using System;
  14. using uPLibrary.Networking.M2Mqtt.Exceptions;
  15. namespace uPLibrary.Networking.M2Mqtt.Messages
  16. {
  17. /// <summary>
  18. /// Class for SUBACK message from broker to client
  19. /// </summary>
  20. public class MqttMsgSuback : MqttMsgBase
  21. {
  22. #region Properties...
  23. /// <summary>
  24. /// List of granted QOS Levels
  25. /// </summary>
  26. public byte[] GrantedQoSLevels
  27. {
  28. get { return this.grantedQosLevels; }
  29. set { this.grantedQosLevels = value; }
  30. }
  31. #endregion
  32. // granted QOS levels
  33. byte[] grantedQosLevels;
  34. /// <summary>
  35. /// Constructor
  36. /// </summary>
  37. public MqttMsgSuback()
  38. {
  39. this.type = MQTT_MSG_SUBACK_TYPE;
  40. }
  41. /// <summary>
  42. /// Parse bytes for a SUBACK message
  43. /// </summary>
  44. /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
  45. /// <param name="protocolVersion">Protocol Version</param>
  46. /// <param name="channel">Channel connected to the broker</param>
  47. /// <returns>SUBACK message instance</returns>
  48. public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
  49. {
  50. byte[] buffer;
  51. int index = 0;
  52. MqttMsgSuback msg = new MqttMsgSuback();
  53. if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
  54. {
  55. // [v3.1.1] check flag bits
  56. if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS)
  57. throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
  58. }
  59. // get remaining length and allocate buffer
  60. int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
  61. buffer = new byte[remainingLength];
  62. // read bytes from socket...
  63. channel.Receive(buffer);
  64. // message id
  65. msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
  66. msg.messageId |= (buffer[index++]);
  67. // payload contains QoS levels granted
  68. msg.grantedQosLevels = new byte[remainingLength - MESSAGE_ID_SIZE];
  69. int qosIdx = 0;
  70. do
  71. {
  72. msg.grantedQosLevels[qosIdx++] = buffer[index++];
  73. } while (index < remainingLength);
  74. return msg;
  75. }
  76. public override byte[] GetBytes(byte protocolVersion)
  77. {
  78. int fixedHeaderSize = 0;
  79. int varHeaderSize = 0;
  80. int payloadSize = 0;
  81. int remainingLength = 0;
  82. byte[] buffer;
  83. int index = 0;
  84. // message identifier
  85. varHeaderSize += MESSAGE_ID_SIZE;
  86. int grantedQosIdx = 0;
  87. for (grantedQosIdx = 0; grantedQosIdx < this.grantedQosLevels.Length; grantedQosIdx++)
  88. {
  89. payloadSize++;
  90. }
  91. remainingLength += (varHeaderSize + payloadSize);
  92. // first byte of fixed header
  93. fixedHeaderSize = 1;
  94. int temp = remainingLength;
  95. // increase fixed header size based on remaining length
  96. // (each remaining length byte can encode until 128)
  97. do
  98. {
  99. fixedHeaderSize++;
  100. temp = temp / 128;
  101. } while (temp > 0);
  102. // allocate buffer for message
  103. buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
  104. // first fixed header byte
  105. if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
  106. buffer[index++] = (MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBACK_FLAG_BITS; // [v.3.1.1]
  107. else
  108. buffer[index++] = (byte)(MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET);
  109. // encode remaining length
  110. index = this.encodeRemainingLength(remainingLength, buffer, index);
  111. // message id
  112. buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB
  113. buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB
  114. // payload contains QoS levels granted
  115. for (grantedQosIdx = 0; grantedQosIdx < this.grantedQosLevels.Length; grantedQosIdx++)
  116. {
  117. buffer[index++] = this.grantedQosLevels[grantedQosIdx];
  118. }
  119. return buffer;
  120. }
  121. public override string ToString()
  122. {
  123. #if TRACE
  124. return this.GetTraceString(
  125. "SUBACK",
  126. new object[] { "messageId", "grantedQosLevels" },
  127. new object[] { this.messageId, this.grantedQosLevels });
  128. #else
  129. return base.ToString();
  130. #endif
  131. }
  132. }
  133. }