mqtt/M2Mqtt/Messages/MqttMsgSuback.cs

144 lines
4.5 KiB
C#
Raw Permalink Normal View History

/*
2018-04-01 19:31:18 +02:00
Copyright (c) 2013, 2014 Paolo Patierno
2018-04-01 19:31:18 +02:00
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
2018-04-01 19:31:18 +02:00
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
2018-04-01 19:31:18 +02:00
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
2018-04-01 19:31:18 +02:00
using uPLibrary.Networking.M2Mqtt.Exceptions;
2019-11-26 15:34:16 +01:00
namespace uPLibrary.Networking.M2Mqtt.Messages {
/// <summary>
/// Class for SUBACK message from broker to client
/// </summary>
public class MqttMsgSuback : MqttMsgBase {
#region Properties...
/// <summary>
2019-11-26 15:34:16 +01:00
/// List of granted QOS Levels
/// </summary>
2019-11-26 15:34:16 +01:00
public Byte[] GrantedQoSLevels { get; set; }
#endregion
// granted QOS levels
/// <summary>
/// Constructor
/// </summary>
public MqttMsgSuback() => this.Type = MQTT_MSG_SUBACK_TYPE;
/// <summary>
/// Parse bytes for a SUBACK message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>SUBACK message instance</returns>
public static MqttMsgSuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
Byte[] buffer;
Int32 index = 0;
MqttMsgSuback msg = new MqttMsgSuback();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
}
// get remaining length and allocate buffer
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new Byte[remainingLength];
// read bytes from socket...
_ = channel.Receive(buffer);
// message id
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.MessageId |= buffer[index++];
// payload contains QoS levels granted
msg.GrantedQoSLevels = new Byte[remainingLength - MESSAGE_ID_SIZE];
Int32 qosIdx = 0;
do {
msg.GrantedQoSLevels[qosIdx++] = buffer[index++];
} while (index < remainingLength);
return msg;
}
public override Byte[] GetBytes(Byte protocolVersion) {
Int32 varHeaderSize = 0;
Int32 payloadSize = 0;
Int32 remainingLength = 0;
Byte[] buffer;
Int32 index = 0;
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
Int32 grantedQosIdx;
for (grantedQosIdx = 0; grantedQosIdx < this.GrantedQoSLevels.Length; grantedQosIdx++) {
payloadSize++;
}
remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header
Int32 fixedHeaderSize = 1;
Int32 temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do {
fixedHeaderSize++;
temp /= 128;
} while (temp > 0);
// allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
? (Byte)((MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBACK_FLAG_BITS)
: (Byte)(MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length
index = this.EncodeRemainingLength(remainingLength, buffer, index);
// message id
buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
// payload contains QoS levels granted
for (grantedQosIdx = 0; grantedQosIdx < this.GrantedQoSLevels.Length; grantedQosIdx++) {
buffer[index++] = this.GrantedQoSLevels[grantedQosIdx];
}
return buffer;
}
public override String ToString() =>
2018-04-01 19:31:18 +02:00
#if TRACE
2019-11-26 15:34:16 +01:00
this.GetTraceString(
"SUBACK",
new Object[] { "messageId", "grantedQosLevels" },
new Object[] { this.MessageId, this.GrantedQoSLevels });
2018-04-01 19:31:18 +02:00
#else
2019-11-26 15:34:16 +01:00
base.ToString();
2018-04-01 19:31:18 +02:00
#endif
2019-11-26 15:34:16 +01:00
}
}