/* M2Mqtt - MQTT Client Library for .Net Copyright (c) 2014, Paolo Patierno, All rights reserved. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3.0 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. */ #if SSL && !WINDOWS_PHONE #if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) using Microsoft.SPOT.Net.Security; #else using System.Net.Security; #endif #endif using System; namespace uPLibrary.Networking.M2Mqtt.Messages { /// /// Base class for all MQTT messages /// public abstract class MqttMsgBase { #region Constants... // mask, offset and size for fixed header fields internal const byte MSG_TYPE_MASK = 0xF0; internal const byte MSG_TYPE_OFFSET = 0x04; internal const byte MSG_TYPE_SIZE = 0x04; internal const byte DUP_FLAG_MASK = 0x08; internal const byte DUP_FLAG_OFFSET = 0x03; internal const byte DUP_FLAG_SIZE = 0x01; internal const byte QOS_LEVEL_MASK = 0x06; internal const byte QOS_LEVEL_OFFSET = 0x01; internal const byte QOS_LEVEL_SIZE = 0x02; internal const byte RETAIN_FLAG_MASK = 0x01; internal const byte RETAIN_FLAG_OFFSET = 0x00; internal const byte RETAIN_FLAG_SIZE = 0x01; // MQTT message types internal const byte MQTT_MSG_CONNECT_TYPE = 0x01; internal const byte MQTT_MSG_CONNACK_TYPE = 0x02; internal const byte MQTT_MSG_PUBLISH_TYPE = 0x03; internal const byte MQTT_MSG_PUBACK_TYPE = 0x04; internal const byte MQTT_MSG_PUBREC_TYPE = 0x05; internal const byte MQTT_MSG_PUBREL_TYPE = 0x06; internal const byte MQTT_MSG_PUBCOMP_TYPE = 0x07; internal const byte MQTT_MSG_SUBSCRIBE_TYPE = 0x08; internal const byte MQTT_MSG_SUBACK_TYPE = 0x09; internal const byte MQTT_MSG_UNSUBSCRIBE_TYPE = 0x0A; internal const byte MQTT_MSG_UNSUBACK_TYPE = 0x0B; internal const byte MQTT_MSG_PINGREQ_TYPE = 0x0C; internal const byte MQTT_MSG_PINGRESP_TYPE = 0x0D; internal const byte MQTT_MSG_DISCONNECT_TYPE = 0x0E; // QOS levels public const byte QOS_LEVEL_AT_MOST_ONCE = 0x00; public const byte QOS_LEVEL_AT_LEAST_ONCE = 0x01; public const byte QOS_LEVEL_EXACTLY_ONCE = 0x02; internal const ushort MAX_TOPIC_LENGTH = 65535; internal const ushort MIN_TOPIC_LENGTH = 1; internal const byte MESSAGE_ID_SIZE = 2; #endregion #region Properties... /// /// Message type /// public byte Type { get { return this.type; } set { this.type = value; } } /// /// Duplicate message flag /// public bool DupFlag { get { return this.dupFlag; } set { this.dupFlag = value; } } /// /// Quality of Service level /// public byte QosLevel { get { return this.qosLevel; } set { this.qosLevel = value; } } /// /// Retain message flag /// public bool Retain { get { return this.retain; } set { this.retain = value; } } #endregion // message type protected byte type; // duplicate delivery protected bool dupFlag; // quality of service level protected byte qosLevel; // retain flag protected bool retain; /// /// Returns message bytes rapresentation /// /// Bytes rapresentation public abstract byte[] GetBytes(); /// /// Encode remaining length and insert it into message buffer /// /// Remaining length value to encode /// Message buffer for inserting encoded value /// Index from which insert encoded value into buffer /// Index updated protected int encodeRemainingLength(int remainingLength, byte[] buffer, int index) { int digit = 0; do { digit = remainingLength % 128; remainingLength /= 128; if (remainingLength > 0) digit = digit | 0x80; buffer[index++] = (byte)digit; } while (remainingLength > 0); return index; } /// /// Decode remaining length reading bytes from socket /// /// Channel from reading bytes /// Decoded remaining length protected static int decodeRemainingLength(IMqttNetworkChannel channel) { int multiplier = 1; int value = 0; int digit = 0; byte[] nextByte = new byte[1]; do { // next digit from stream channel.Receive(nextByte); digit = nextByte[0]; value += ((digit & 127) * multiplier); multiplier *= 128; } while ((digit & 128) != 0); return value; } } }