add netcore and refactoring

This commit is contained in:
Philip Schell 2019-11-26 15:34:16 +01:00
parent 57f343c908
commit bd6472e5e4
47 changed files with 4897 additions and 5569 deletions

View File

@ -16,117 +16,104 @@ Contributors:
using System; using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions namespace uPLibrary.Networking.M2Mqtt.Exceptions {
{ /// <summary>
/// MQTT client exception
/// </summary>
public class MqttClientException : Exception {
/// <summary> /// <summary>
/// MQTT client exception /// Constructor
/// </summary> /// </summary>
public class MqttClientException : Exception /// <param name="code">Error code</param>
{ public MqttClientException(MqttClientErrorCode errorCode) => this.ErrorCode = errorCode;
/// <summary>
/// Constructor
/// </summary>
/// <param name="code">Error code</param>
public MqttClientException(MqttClientErrorCode errorCode)
{
this.errorCode = errorCode;
}
// error code
private MqttClientErrorCode errorCode;
/// <summary>
/// Error code
/// </summary>
public MqttClientErrorCode ErrorCode
{
get { return this.errorCode; }
set { this.errorCode = value; }
}
}
/// <summary> /// <summary>
/// MQTT client erroro code /// Error code
/// </summary> /// </summary>
public enum MqttClientErrorCode public MqttClientErrorCode ErrorCode { get; set; }
{ }
/// <summary>
/// Will error (topic, message or QoS level) /// <summary>
/// </summary> /// MQTT client erroro code
WillWrong = 1, /// </summary>
public enum MqttClientErrorCode {
/// <summary> /// <summary>
/// Keep alive period too large /// Will error (topic, message or QoS level)
/// </summary> /// </summary>
KeepAliveWrong, WillWrong = 1,
/// <summary> /// <summary>
/// Topic contains wildcards /// Keep alive period too large
/// </summary> /// </summary>
TopicWildcard, KeepAliveWrong,
/// <summary> /// <summary>
/// Topic length wrong /// Topic contains wildcards
/// </summary> /// </summary>
TopicLength, TopicWildcard,
/// <summary> /// <summary>
/// QoS level not allowed /// Topic length wrong
/// </summary> /// </summary>
QosNotAllowed, TopicLength,
/// <summary> /// <summary>
/// Topics list empty for subscribe /// QoS level not allowed
/// </summary> /// </summary>
TopicsEmpty, QosNotAllowed,
/// <summary> /// <summary>
/// Qos levels list empty for subscribe /// Topics list empty for subscribe
/// </summary> /// </summary>
QosLevelsEmpty, TopicsEmpty,
/// <summary> /// <summary>
/// Topics / Qos Levels not match in subscribe /// Qos levels list empty for subscribe
/// </summary> /// </summary>
TopicsQosLevelsNotMatch, QosLevelsEmpty,
/// <summary> /// <summary>
/// Wrong message from broker /// Topics / Qos Levels not match in subscribe
/// </summary> /// </summary>
WrongBrokerMessage, TopicsQosLevelsNotMatch,
/// <summary> /// <summary>
/// Wrong Message Id /// Wrong message from broker
/// </summary> /// </summary>
WrongMessageId, WrongBrokerMessage,
/// <summary> /// <summary>
/// Inflight queue is full /// Wrong Message Id
/// </summary> /// </summary>
InflightQueueFull, WrongMessageId,
// [v3.1.1] /// <summary>
/// <summary> /// Inflight queue is full
/// Invalid flag bits received /// </summary>
/// </summary> InflightQueueFull,
InvalidFlagBits,
// [v3.1.1]
// [v3.1.1] /// <summary>
/// <summary> /// Invalid flag bits received
/// Invalid connect flags received /// </summary>
/// </summary> InvalidFlagBits,
InvalidConnectFlags,
// [v3.1.1]
// [v3.1.1] /// <summary>
/// <summary> /// Invalid connect flags received
/// Invalid client id /// </summary>
/// </summary> InvalidConnectFlags,
InvalidClientId,
// [v3.1.1]
// [v3.1.1] /// <summary>
/// <summary> /// Invalid client id
/// Invalid protocol name /// </summary>
/// </summary> InvalidClientId,
InvalidProtocolName
} // [v3.1.1]
/// <summary>
/// Invalid protocol name
/// </summary>
InvalidProtocolName
}
} }

View File

@ -16,27 +16,23 @@ Contributors:
using System; using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions namespace uPLibrary.Networking.M2Mqtt.Exceptions {
{ /// <summary>
/// Exception due to error communication with broker on socket
/// </summary>
public class MqttCommunicationException : Exception {
/// <summary> /// <summary>
/// Exception due to error communication with broker on socket /// Default constructor
/// </summary> /// </summary>
public class MqttCommunicationException : Exception public MqttCommunicationException() {
{ }
/// <summary>
/// Default constructor /// <summary>
/// </summary> /// Constructor
public MqttCommunicationException() /// </summary>
{ /// <param name="e">Inner Exception</param>
} public MqttCommunicationException(Exception e)
: base(String.Empty, e) {
/// <summary> }
/// Constructor }
/// </summary>
/// <param name="e">Inner Exception</param>
public MqttCommunicationException(Exception e)
: base(String.Empty, e)
{
}
}
} }

View File

@ -16,16 +16,13 @@ Contributors:
using System; using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions namespace uPLibrary.Networking.M2Mqtt.Exceptions {
{ /// <summary>
/// <summary> /// Connection to the broker exception
/// Connection to the broker exception /// </summary>
/// </summary> public class MqttConnectionException : Exception {
public class MqttConnectionException : Exception public MqttConnectionException(String message, Exception innerException)
{ : base(message, innerException) {
public MqttConnectionException(string message, Exception innerException) }
: base(message, innerException) }
{
}
}
} }

View File

@ -16,12 +16,10 @@ Contributors:
using System; using System;
namespace uPLibrary.Networking.M2Mqtt.Exceptions namespace uPLibrary.Networking.M2Mqtt.Exceptions {
{ /// <summary>
/// <summary> /// Timeout on receiving from broker exception
/// Timeout on receiving from broker exception /// </summary>
/// </summary> public class MqttTimeoutException : Exception {
public class MqttTimeoutException : Exception }
{
}
} }

View File

@ -15,55 +15,52 @@ Contributors:
*/ */
using System; using System;
using System.Text;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt {
{ /// <summary>
/// Interface for channel under MQTT library
/// </summary>
public interface IMqttNetworkChannel {
/// <summary> /// <summary>
/// Interface for channel under MQTT library /// Data available on channel
/// </summary> /// </summary>
public interface IMqttNetworkChannel Boolean DataAvailable { get; }
{
/// <summary> /// <summary>
/// Data available on channel /// Receive data from the network channel
/// </summary> /// </summary>
bool DataAvailable { get; } /// <param name="buffer">Data buffer for receiving data</param>
/// <returns>Number of bytes received</returns>
/// <summary> Int32 Receive(Byte[] buffer);
/// Receive data from the network channel
/// </summary> /// <summary>
/// <param name="buffer">Data buffer for receiving data</param> /// Receive data from the network channel with a specified timeout
/// <returns>Number of bytes received</returns> /// </summary>
int Receive(byte[] buffer); /// <param name="buffer">Data buffer for receiving data</param>
/// <param name="timeout">Timeout on receiving (in milliseconds)</param>
/// <summary> /// <returns>Number of bytes received</returns>
/// Receive data from the network channel with a specified timeout Int32 Receive(Byte[] buffer, Int32 timeout);
/// </summary>
/// <param name="buffer">Data buffer for receiving data</param> /// <summary>
/// <param name="timeout">Timeout on receiving (in milliseconds)</param> /// Send data on the network channel to the broker
/// <returns>Number of bytes received</returns> /// </summary>
int Receive(byte[] buffer, int timeout); /// <param name="buffer">Data buffer to send</param>
/// <returns>Number of byte sent</returns>
/// <summary> Int32 Send(Byte[] buffer);
/// Send data on the network channel to the broker
/// </summary> /// <summary>
/// <param name="buffer">Data buffer to send</param> /// Close the network channel
/// <returns>Number of byte sent</returns> /// </summary>
int Send(byte[] buffer); void Close();
/// <summary> /// <summary>
/// Close the network channel /// Connect to remote server
/// </summary> /// </summary>
void Close(); void Connect();
/// <summary> /// <summary>
/// Connect to remote server /// Accept client connection
/// </summary> /// </summary>
void Connect(); void Accept();
}
/// <summary>
/// Accept client connection
/// </summary>
void Accept();
}
} }

View File

@ -14,12 +14,10 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
namespace uPLibrary.Networking.M2Mqtt.Internal namespace uPLibrary.Networking.M2Mqtt.Internal {
{ /// <summary>
/// <summary> /// Generic internal event for dispatching
/// Generic internal event for dispatching /// </summary>
/// </summary> public abstract class InternalEvent {
public abstract class InternalEvent }
{
}
} }

View File

@ -16,36 +16,26 @@ Contributors:
using uPLibrary.Networking.M2Mqtt.Messages; using uPLibrary.Networking.M2Mqtt.Messages;
namespace uPLibrary.Networking.M2Mqtt.Internal namespace uPLibrary.Networking.M2Mqtt.Internal {
{ /// <summary>
/// Internal event with a message
/// </summary>
public class MsgInternalEvent : InternalEvent {
#region Properties ...
/// <summary> /// <summary>
/// Internal event with a message /// Related message
/// </summary> /// </summary>
public class MsgInternalEvent : InternalEvent public MqttMsgBase Message { get; set; }
{
#region Properties ... #endregion
/// <summary> // related message
/// Related message
/// </summary> /// <summary>
public MqttMsgBase Message /// Constructor
{ /// </summary>
get { return this.msg; } /// <param name="msg">Related message</param>
set { this.msg = value; } public MsgInternalEvent(MqttMsgBase msg) => this.Message = msg;
} }
#endregion
// related message
protected MqttMsgBase msg;
/// <summary>
/// Constructor
/// </summary>
/// <param name="msg">Related message</param>
public MsgInternalEvent(MqttMsgBase msg)
{
this.msg = msg;
}
}
} }

View File

@ -14,40 +14,31 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Messages; using uPLibrary.Networking.M2Mqtt.Messages;
namespace uPLibrary.Networking.M2Mqtt.Internal namespace uPLibrary.Networking.M2Mqtt.Internal {
{ /// <summary>
/// Internal event for a published message
/// </summary>
public class MsgPublishedInternalEvent : MsgInternalEvent {
#region Properties...
/// <summary> /// <summary>
/// Internal event for a published message /// Message published (or failed due to retries)
/// </summary> /// </summary>
public class MsgPublishedInternalEvent : MsgInternalEvent public Boolean IsPublished { get; internal set; }
{
#region Properties... #endregion
/// <summary> // published flag
/// Message published (or failed due to retries)
/// </summary> /// <summary>
public bool IsPublished /// Constructor
{ /// </summary>
get { return this.isPublished; } /// <param name="msg">Message published</param>
internal set { this.isPublished = value; } /// <param name="isPublished">Publish flag</param>
} public MsgPublishedInternalEvent(MqttMsgBase msg, Boolean isPublished)
: base(msg) => this.IsPublished = isPublished;
#endregion }
// published flag
bool isPublished;
/// <summary>
/// Constructor
/// </summary>
/// <param name="msg">Message published</param>
/// <param name="isPublished">Publish flag</param>
public MsgPublishedInternalEvent(MqttMsgBase msg, bool isPublished)
: base(msg)
{
this.isPublished = isPublished;
}
}
} }

24
M2Mqtt/M2Mqtt_Core.csproj Normal file
View File

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<AssemblyName>M2Mqtt</AssemblyName>
<RootNamespace>uPLibrary.Networking.M2Mqtt</RootNamespace>
<Description>MQTT Client Library for M2M communication</Description>
<Authors>Paolo Patierno</Authors>
<Company>Paolo Patierno</Company>
<Copyright>Copyright © Paolo Patierno 2014</Copyright>
<Version>4.3.0</Version>
<AssemblyVersion>4.3.0</AssemblyVersion>
<FileVersion>4.3.0</FileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<DefineConstants>TRACE;SSL</DefineConstants>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<DefineConstants>TRACE;SSL</DefineConstants>
</PropertyGroup>
</Project>

View File

@ -17,259 +17,220 @@ Contributors:
using System; using System;
using System.Text; using System.Text;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Base class for all MQTT messages
/// </summary>
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 MSG_FLAG_BITS_MASK = 0x0F; // [v3.1.1]
internal const Byte MSG_FLAG_BITS_OFFSET = 0x00; // [v3.1.1]
internal const Byte MSG_FLAG_BITS_SIZE = 0x04; // [v3.1.1]
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;
// [v3.1.1] MQTT flag bits
internal const Byte MQTT_MSG_CONNECT_FLAG_BITS = 0x00;
internal const Byte MQTT_MSG_CONNACK_FLAG_BITS = 0x00;
internal const Byte MQTT_MSG_PUBLISH_FLAG_BITS = 0x00; // just defined as 0x00 but depends on publish props (dup, qos, retain)
internal const Byte MQTT_MSG_PUBACK_FLAG_BITS = 0x00;
internal const Byte MQTT_MSG_PUBREC_FLAG_BITS = 0x00;
internal const Byte MQTT_MSG_PUBREL_FLAG_BITS = 0x02;
internal const Byte MQTT_MSG_PUBCOMP_FLAG_BITS = 0x00;
internal const Byte MQTT_MSG_SUBSCRIBE_FLAG_BITS = 0x02;
internal const Byte MQTT_MSG_SUBACK_FLAG_BITS = 0x00;
internal const Byte MQTT_MSG_UNSUBSCRIBE_FLAG_BITS = 0x02;
internal const Byte MQTT_MSG_UNSUBACK_FLAG_BITS = 0x00;
internal const Byte MQTT_MSG_PINGREQ_FLAG_BITS = 0x00;
internal const Byte MQTT_MSG_PINGRESP_FLAG_BITS = 0x00;
internal const Byte MQTT_MSG_DISCONNECT_FLAG_BITS = 0x00;
// 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;
// SUBSCRIBE QoS level granted failure [v3.1.1]
public const Byte QOS_LEVEL_GRANTED_FAILURE = 0x80;
internal const UInt16 MAX_TOPIC_LENGTH = 65535;
internal const UInt16 MIN_TOPIC_LENGTH = 1;
internal const Byte MESSAGE_ID_SIZE = 2;
#endregion
#region Properties...
/// <summary> /// <summary>
/// Base class for all MQTT messages /// Message type
/// </summary> /// </summary>
public abstract class MqttMsgBase public Byte Type { get; set; }
{
#region Constants... /// <summary>
/// Duplicate message flag
// mask, offset and size for fixed header fields /// </summary>
internal const byte MSG_TYPE_MASK = 0xF0; public Boolean DupFlag { get; set; }
internal const byte MSG_TYPE_OFFSET = 0x04;
internal const byte MSG_TYPE_SIZE = 0x04; /// <summary>
internal const byte MSG_FLAG_BITS_MASK = 0x0F; // [v3.1.1] /// Quality of Service level
internal const byte MSG_FLAG_BITS_OFFSET = 0x00; // [v3.1.1] /// </summary>
internal const byte MSG_FLAG_BITS_SIZE = 0x04; // [v3.1.1] public Byte QosLevel { get; set; }
internal const byte DUP_FLAG_MASK = 0x08;
internal const byte DUP_FLAG_OFFSET = 0x03; /// <summary>
internal const byte DUP_FLAG_SIZE = 0x01; /// Retain message flag
internal const byte QOS_LEVEL_MASK = 0x06; /// </summary>
internal const byte QOS_LEVEL_OFFSET = 0x01; public Boolean Retain { get; set; }
internal const byte QOS_LEVEL_SIZE = 0x02;
internal const byte RETAIN_FLAG_MASK = 0x01; /// <summary>
internal const byte RETAIN_FLAG_OFFSET = 0x00; /// Message identifier for the message
internal const byte RETAIN_FLAG_SIZE = 0x01; /// </summary>
public UInt16 MessageId { get; set; }
// MQTT message types
internal const byte MQTT_MSG_CONNECT_TYPE = 0x01; #endregion
internal const byte MQTT_MSG_CONNACK_TYPE = 0x02;
internal const byte MQTT_MSG_PUBLISH_TYPE = 0x03; // message type
internal const byte MQTT_MSG_PUBACK_TYPE = 0x04; // duplicate delivery
internal const byte MQTT_MSG_PUBREC_TYPE = 0x05; // quality of service level
internal const byte MQTT_MSG_PUBREL_TYPE = 0x06; // retain flag
internal const byte MQTT_MSG_PUBCOMP_TYPE = 0x07; // message identifier
internal const byte MQTT_MSG_SUBSCRIBE_TYPE = 0x08;
internal const byte MQTT_MSG_SUBACK_TYPE = 0x09; /// <summary>
internal const byte MQTT_MSG_UNSUBSCRIBE_TYPE = 0x0A; /// Returns message bytes rapresentation
internal const byte MQTT_MSG_UNSUBACK_TYPE = 0x0B; /// </summary>
internal const byte MQTT_MSG_PINGREQ_TYPE = 0x0C; /// <param name="protocolVersion">Protocol version</param>
internal const byte MQTT_MSG_PINGRESP_TYPE = 0x0D; /// <returns>Bytes rapresentation</returns>
internal const byte MQTT_MSG_DISCONNECT_TYPE = 0x0E; public abstract Byte[] GetBytes(Byte protocolVersion);
// [v3.1.1] MQTT flag bits /// <summary>
internal const byte MQTT_MSG_CONNECT_FLAG_BITS = 0x00; /// Encode remaining length and insert it into message buffer
internal const byte MQTT_MSG_CONNACK_FLAG_BITS = 0x00; /// </summary>
internal const byte MQTT_MSG_PUBLISH_FLAG_BITS = 0x00; // just defined as 0x00 but depends on publish props (dup, qos, retain) /// <param name="remainingLength">Remaining length value to encode</param>
internal const byte MQTT_MSG_PUBACK_FLAG_BITS = 0x00; /// <param name="buffer">Message buffer for inserting encoded value</param>
internal const byte MQTT_MSG_PUBREC_FLAG_BITS = 0x00; /// <param name="index">Index from which insert encoded value into buffer</param>
internal const byte MQTT_MSG_PUBREL_FLAG_BITS = 0x02; /// <returns>Index updated</returns>
internal const byte MQTT_MSG_PUBCOMP_FLAG_BITS = 0x00; protected Int32 EncodeRemainingLength(Int32 remainingLength, Byte[] buffer, Int32 index) {
internal const byte MQTT_MSG_SUBSCRIBE_FLAG_BITS = 0x02; do {
internal const byte MQTT_MSG_SUBACK_FLAG_BITS = 0x00; Int32 digit = remainingLength % 128;
internal const byte MQTT_MSG_UNSUBSCRIBE_FLAG_BITS = 0x02; remainingLength /= 128;
internal const byte MQTT_MSG_UNSUBACK_FLAG_BITS = 0x00; if (remainingLength > 0) {
internal const byte MQTT_MSG_PINGREQ_FLAG_BITS = 0x00; digit |= 0x80;
internal const byte MQTT_MSG_PINGRESP_FLAG_BITS = 0x00; }
internal const byte MQTT_MSG_DISCONNECT_FLAG_BITS = 0x00;
buffer[index++] = (Byte)digit;
// QOS levels } while (remainingLength > 0);
public const byte QOS_LEVEL_AT_MOST_ONCE = 0x00; return index;
public const byte QOS_LEVEL_AT_LEAST_ONCE = 0x01; }
public const byte QOS_LEVEL_EXACTLY_ONCE = 0x02;
/// <summary>
// SUBSCRIBE QoS level granted failure [v3.1.1] /// Decode remaining length reading bytes from socket
public const byte QOS_LEVEL_GRANTED_FAILURE = 0x80; /// </summary>
/// <param name="channel">Channel from reading bytes</param>
internal const ushort MAX_TOPIC_LENGTH = 65535; /// <returns>Decoded remaining length</returns>
internal const ushort MIN_TOPIC_LENGTH = 1; protected static Int32 DecodeRemainingLength(IMqttNetworkChannel channel) {
internal const byte MESSAGE_ID_SIZE = 2; Int32 multiplier = 1;
Int32 value = 0;
#endregion Byte[] nextByte = new Byte[1];
Int32 digit;
#region Properties... do {
// next digit from stream
/// <summary> _ = channel.Receive(nextByte);
/// Message type digit = nextByte[0];
/// </summary> value += (digit & 127) * multiplier;
public byte Type multiplier *= 128;
{ } while ((digit & 128) != 0);
get { return this.type; } return value;
set { this.type = value; } }
}
/// <summary>
/// Duplicate message flag
/// </summary>
public bool DupFlag
{
get { return this.dupFlag; }
set { this.dupFlag = value; }
}
/// <summary>
/// Quality of Service level
/// </summary>
public byte QosLevel
{
get { return this.qosLevel; }
set { this.qosLevel = value; }
}
/// <summary>
/// Retain message flag
/// </summary>
public bool Retain
{
get { return this.retain; }
set { this.retain = value; }
}
/// <summary>
/// Message identifier for the message
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
set { this.messageId = value; }
}
#endregion
// message type
protected byte type;
// duplicate delivery
protected bool dupFlag;
// quality of service level
protected byte qosLevel;
// retain flag
protected bool retain;
// message identifier
protected ushort messageId;
/// <summary>
/// Returns message bytes rapresentation
/// </summary>
/// <param name="protocolVersion">Protocol version</param>
/// <returns>Bytes rapresentation</returns>
public abstract byte[] GetBytes(byte protocolVersion);
/// <summary>
/// Encode remaining length and insert it into message buffer
/// </summary>
/// <param name="remainingLength">Remaining length value to encode</param>
/// <param name="buffer">Message buffer for inserting encoded value</param>
/// <param name="index">Index from which insert encoded value into buffer</param>
/// <returns>Index updated</returns>
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;
}
/// <summary>
/// Decode remaining length reading bytes from socket
/// </summary>
/// <param name="channel">Channel from reading bytes</param>
/// <returns>Decoded remaining length</returns>
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;
}
#if TRACE #if TRACE
/// <summary> /// <summary>
/// Returns a string representation of the message for tracing /// Returns a string representation of the message for tracing
/// </summary> /// </summary>
/// <param name="name">Message name</param> /// <param name="name">Message name</param>
/// <param name="fieldNames">Message fields name</param> /// <param name="fieldNames">Message fields name</param>
/// <param name="fieldValues">Message fields value</param> /// <param name="fieldValues">Message fields value</param>
/// <returns>String representation of the message</returns> /// <returns>String representation of the message</returns>
protected string GetTraceString(string name, object[] fieldNames, object[] fieldValues) protected String GetTraceString(String name, Object[] fieldNames, Object[] fieldValues) {
{ StringBuilder sb = new StringBuilder();
StringBuilder sb = new StringBuilder(); _ = sb.Append(name);
sb.Append(name);
if (fieldNames != null && fieldValues != null) {
if ((fieldNames != null) && (fieldValues != null)) _ = sb.Append("(");
{ Boolean addComma = false;
sb.Append("("); for (Int32 i = 0; i < fieldValues.Length; i++) {
bool addComma = false; if (fieldValues[i] != null) {
for (int i = 0; i < fieldValues.Length; i++) if (addComma) {
{ _ = sb.Append(",");
if (fieldValues[i] != null) }
{
if (addComma) _ = sb.Append(fieldNames[i]);
{ _ = sb.Append(":");
sb.Append(","); _ = sb.Append(this.GetStringObject(fieldValues[i]));
} addComma = true;
}
sb.Append(fieldNames[i]); }
sb.Append(":"); _ = sb.Append(")");
sb.Append(GetStringObject(fieldValues[i])); }
addComma = true;
} return sb.ToString();
} }
sb.Append(")");
} Object GetStringObject(Object value) {
if (value is Byte[] binary) {
return sb.ToString(); String hexChars = "0123456789ABCDEF";
} StringBuilder sb = new StringBuilder(binary.Length * 2);
for (Int32 i = 0; i < binary.Length; ++i) {
object GetStringObject(object value) _ = sb.Append(hexChars[binary[i] >> 4]);
{ _ = sb.Append(hexChars[binary[i] & 0x0F]);
byte[] binary = value as byte[]; }
if (binary != null)
{ return sb.ToString();
string hexChars = "0123456789ABCDEF"; }
StringBuilder sb = new StringBuilder(binary.Length * 2);
for (int i = 0; i < binary.Length; ++i) if (value is Object[] list) {
{ StringBuilder sb = new StringBuilder();
sb.Append(hexChars[binary[i] >> 4]); _ = sb.Append('[');
sb.Append(hexChars[binary[i] & 0x0F]); for (Int32 i = 0; i < list.Length; ++i) {
} if (i > 0) {
_ = sb.Append(',');
return sb.ToString(); }
}
_ = sb.Append(list[i]);
object[] list = value as object[]; }
if (list != null) _ = sb.Append(']');
{
StringBuilder sb = new StringBuilder(); return sb.ToString();
sb.Append('['); }
for (int i = 0; i < list.Length; ++i)
{ return value;
if (i > 0) sb.Append(','); }
sb.Append(list[i]);
}
sb.Append(']');
return sb.ToString();
}
return value;
}
#endif #endif
} }
} }

View File

@ -17,175 +17,153 @@ Contributors:
using System; using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for CONNACK message from broker to client
/// </summary>
public class MqttMsgConnack : MqttMsgBase {
#region Constants...
// return codes for CONNACK message
public const Byte CONN_ACCEPTED = 0x00;
public const Byte CONN_REFUSED_PROT_VERS = 0x01;
public const Byte CONN_REFUSED_IDENT_REJECTED = 0x02;
public const Byte CONN_REFUSED_SERVER_UNAVAILABLE = 0x03;
public const Byte CONN_REFUSED_USERNAME_PASSWORD = 0x04;
public const Byte CONN_REFUSED_NOT_AUTHORIZED = 0x05;
//private const Byte TOPIC_NAME_COMP_RESP_BYTE_OFFSET = 0;
private const Byte TOPIC_NAME_COMP_RESP_BYTE_SIZE = 1;
// [v3.1.1] connect acknowledge flags replace "old" topic name compression respone (not used in 3.1)
private const Byte CONN_ACK_FLAGS_BYTE_OFFSET = 0;
private const Byte CONN_ACK_FLAGS_BYTE_SIZE = 1;
// [v3.1.1] session present flag
private const Byte SESSION_PRESENT_FLAG_MASK = 0x01;
private const Byte SESSION_PRESENT_FLAG_OFFSET = 0x00;
//private const Byte SESSION_PRESENT_FLAG_SIZE = 0x01;
private const Byte CONN_RETURN_CODE_BYTE_OFFSET = 1;
private const Byte CONN_RETURN_CODE_BYTE_SIZE = 1;
#endregion
#region Properties...
// [v3.1.1] session present flag
/// <summary> /// <summary>
/// Class for CONNACK message from broker to client /// Session present flag
/// </summary> /// </summary>
public class MqttMsgConnack : MqttMsgBase public Boolean SessionPresent { get; set; }
{
#region Constants... /// <summary>
/// Return Code
// return codes for CONNACK message /// </summary>
public const byte CONN_ACCEPTED = 0x00; public Byte ReturnCode { get; set; }
public const byte CONN_REFUSED_PROT_VERS = 0x01;
public const byte CONN_REFUSED_IDENT_REJECTED = 0x02; #endregion
public const byte CONN_REFUSED_SERVER_UNAVAILABLE = 0x03;
public const byte CONN_REFUSED_USERNAME_PASSWORD = 0x04; // [v3.1.1] session present flag
public const byte CONN_REFUSED_NOT_AUTHORIZED = 0x05;
/// <summary>
private const byte TOPIC_NAME_COMP_RESP_BYTE_OFFSET = 0; /// Constructor
private const byte TOPIC_NAME_COMP_RESP_BYTE_SIZE = 1; /// </summary>
// [v3.1.1] connect acknowledge flags replace "old" topic name compression respone (not used in 3.1) public MqttMsgConnack() => this.Type = MQTT_MSG_CONNACK_TYPE;
private const byte CONN_ACK_FLAGS_BYTE_OFFSET = 0;
private const byte CONN_ACK_FLAGS_BYTE_SIZE = 1; /// <summary>
// [v3.1.1] session present flag /// Parse bytes for a CONNACK message
private const byte SESSION_PRESENT_FLAG_MASK = 0x01; /// </summary>
private const byte SESSION_PRESENT_FLAG_OFFSET = 0x00; /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
private const byte SESSION_PRESENT_FLAG_SIZE = 0x01; /// <param name="protocolVersion">Protocol Version</param>
private const byte CONN_RETURN_CODE_BYTE_OFFSET = 1; /// <param name="channel">Channel connected to the broker</param>
private const byte CONN_RETURN_CODE_BYTE_SIZE = 1; /// <returns>CONNACK message instance</returns>
public static MqttMsgConnack Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
#endregion Byte[] buffer;
MqttMsgConnack msg = new MqttMsgConnack();
#region Properties...
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] session present flag // [v3.1.1] check flag bits
/// <summary> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS) {
/// Session present flag throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// </summary> }
public bool SessionPresent }
{
get { return this.sessionPresent; } // get remaining length and allocate buffer
set { this.sessionPresent = value; } Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
} buffer = new Byte[remainingLength];
/// <summary> // read bytes from socket...
/// Return Code _ = channel.Receive(buffer);
/// </summary> if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
public byte ReturnCode // [v3.1.1] ... set session present flag ...
{ msg.SessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00;
get { return this.returnCode; } }
set { this.returnCode = value; } // ...and set return code from broker
} msg.ReturnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];
#endregion return msg;
}
// [v3.1.1] session present flag
private bool sessionPresent; public override Byte[] GetBytes(Byte ProtocolVersion) {
Int32 varHeaderSize = 0;
// return code for CONNACK message Int32 payloadSize = 0;
private byte returnCode; Int32 remainingLength = 0;
Byte[] buffer;
/// <summary> Int32 index = 0;
/// Constructor
/// </summary> if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
public MqttMsgConnack() // flags byte and connect return code
{ varHeaderSize += CONN_ACK_FLAGS_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE;
this.type = MQTT_MSG_CONNACK_TYPE; } else {
} // topic name compression response and connect return code
varHeaderSize += TOPIC_NAME_COMP_RESP_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE;
/// <summary> }
/// Parse bytes for a CONNACK message
/// </summary> remainingLength += varHeaderSize + payloadSize;
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param> // first byte of fixed header
/// <param name="channel">Channel connected to the broker</param> Int32 fixedHeaderSize = 1;
/// <returns>CONNACK message instance</returns>
public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) Int32 temp = remainingLength;
{ // increase fixed header size based on remaining length
byte[] buffer; // (each remaining length byte can encode until 128)
MqttMsgConnack msg = new MqttMsgConnack(); do {
fixedHeaderSize++;
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) temp /= 128;
{ } while (temp > 0);
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS) // allocate buffer for message
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
}
// first fixed header byte
// get remaining length and allocate buffer buffer[index++] = ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); ? (Byte)((MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNACK_FLAG_BITS)
buffer = new byte[remainingLength]; : (Byte)(MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET);
// read bytes from socket... // encode remaining length
channel.Receive(buffer); index = this.EncodeRemainingLength(remainingLength, buffer, index);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{ if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] ... set session present flag ... // [v3.1.1] session present flag
msg.sessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00; buffer[index++] = this.SessionPresent ? (Byte)(1 << SESSION_PRESENT_FLAG_OFFSET) : (Byte)0x00;
} } else {
// ...and set return code from broker // topic name compression response (reserved values. not used);
msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET]; buffer[index++] = 0x00;
}
return msg;
} // connect return code
buffer[index++] = this.ReturnCode;
public override byte[] GetBytes(byte ProtocolVersion)
{ return buffer;
int fixedHeaderSize = 0; }
int varHeaderSize = 0;
int payloadSize = 0; public override String ToString() =>
int remainingLength = 0;
byte[] buffer;
int index = 0;
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
// flags byte and connect return code
varHeaderSize += (CONN_ACK_FLAGS_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE);
else
// topic name compression response and connect return code
varHeaderSize += (TOPIC_NAME_COMP_RESP_BYTE_SIZE + CONN_RETURN_CODE_BYTE_SIZE);
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
fixedHeaderSize = 1;
int temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do
{
fixedHeaderSize++;
temp = temp / 128;
} while (temp > 0);
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNACK_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (byte)(MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET);
// encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index);
if (ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
// [v3.1.1] session present flag
buffer[index++] = this.sessionPresent ? (byte)(1 << SESSION_PRESENT_FLAG_OFFSET) : (byte)0x00;
else
// topic name compression response (reserved values. not used);
buffer[index++] = 0x00;
// connect return code
buffer[index++] = this.returnCode;
return buffer;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"CONNACK", "CONNACK",
new object[] { "returnCode" }, new Object[] { "returnCode" },
new object[] { this.returnCode }); new Object[] { this.ReturnCode });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -14,31 +14,26 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Event Args class for CONNECT message received from client
/// </summary>
public class MqttMsgConnectEventArgs : EventArgs {
/// <summary> /// <summary>
/// Event Args class for CONNECT message received from client /// Message received from client
/// </summary> /// </summary>
public class MqttMsgConnectEventArgs : EventArgs public MqttMsgConnect Message { get; private set; }
{
/// <summary> /// <summary>
/// Message received from client /// Constructor
/// </summary> /// </summary>
public MqttMsgConnect Message { get; private set; } /// <param name="msg">CONNECT message received from client</param>
public MqttMsgConnectEventArgs(MqttMsgConnect connect) => this.Message = connect;
/// <summary> }
/// Constructor }
/// </summary>
/// <param name="msg">CONNECT message received from client</param>
public MqttMsgConnectEventArgs(MqttMsgConnect connect)
{
this.Message = connect;
}
}
}

View File

@ -15,145 +15,137 @@ Contributors:
*/ */
using System; using System;
using System.Text;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Context for MQTT message
/// </summary>
public class MqttMsgContext {
/// <summary> /// <summary>
/// Context for MQTT message /// MQTT message
/// </summary> /// </summary>
public class MqttMsgContext public MqttMsgBase Message { get; set; }
{
/// <summary>
/// MQTT message
/// </summary>
public MqttMsgBase Message { get; set; }
/// <summary>
/// MQTT message state
/// </summary>
public MqttMsgState State { get; set; }
/// <summary>
/// Flow of the message
/// </summary>
public MqttMsgFlow Flow { get; set; }
/// <summary>
/// Timestamp in ticks (for retry)
/// </summary>
public int Timestamp { get; set; }
/// <summary>
/// Attempt (for retry)
/// </summary>
public int Attempt { get; set; }
/// <summary>
/// Unique key
/// </summary>
public string Key
{
get { return this.Flow + "_" + this.Message.MessageId; }
}
}
/// <summary>
/// Flow of the message
/// </summary>
public enum MqttMsgFlow
{
/// <summary>
/// To publish to subscribers
/// </summary>
ToPublish,
/// <summary>
/// To acknowledge to publisher
/// </summary>
ToAcknowledge
}
/// <summary> /// <summary>
/// MQTT message state /// MQTT message state
/// </summary> /// </summary>
public enum MqttMsgState public MqttMsgState State { get; set; }
{
/// <summary> /// <summary>
/// QOS = 0, Message queued /// Flow of the message
/// </summary> /// </summary>
QueuedQos0, public MqttMsgFlow Flow { get; set; }
/// <summary> /// <summary>
/// QOS = 1, Message queued /// Timestamp in ticks (for retry)
/// </summary> /// </summary>
QueuedQos1, public Int32 Timestamp { get; set; }
/// <summary> /// <summary>
/// QOS = 2, Message queued /// Attempt (for retry)
/// </summary> /// </summary>
QueuedQos2, public Int32 Attempt { get; set; }
/// <summary> /// <summary>
/// QOS = 1, PUBLISH sent, wait for PUBACK /// Unique key
/// </summary> /// </summary>
WaitForPuback, public String Key => this.Flow + "_" + this.Message.MessageId;
}
/// <summary>
/// QOS = 2, PUBLISH sent, wait for PUBREC /// <summary>
/// </summary> /// Flow of the message
WaitForPubrec, /// </summary>
public enum MqttMsgFlow {
/// <summary> /// <summary>
/// QOS = 2, PUBREC sent, wait for PUBREL /// To publish to subscribers
/// </summary> /// </summary>
WaitForPubrel, ToPublish,
/// <summary> /// <summary>
/// QOS = 2, PUBREL sent, wait for PUBCOMP /// To acknowledge to publisher
/// </summary> /// </summary>
WaitForPubcomp, ToAcknowledge
}
/// <summary>
/// QOS = 2, start first phase handshake send PUBREC /// <summary>
/// </summary> /// MQTT message state
SendPubrec, /// </summary>
public enum MqttMsgState {
/// <summary> /// <summary>
/// QOS = 2, start second phase handshake send PUBREL /// QOS = 0, Message queued
/// </summary> /// </summary>
SendPubrel, QueuedQos0,
/// <summary> /// <summary>
/// QOS = 2, end second phase handshake send PUBCOMP /// QOS = 1, Message queued
/// </summary> /// </summary>
SendPubcomp, QueuedQos1,
/// <summary> /// <summary>
/// QOS = 1, PUBLISH received, send PUBACK /// QOS = 2, Message queued
/// </summary> /// </summary>
SendPuback, QueuedQos2,
// [v3.1.1] SUBSCRIBE isn't "officially" QOS = 1 /// <summary>
/// <summary> /// QOS = 1, PUBLISH sent, wait for PUBACK
/// Send SUBSCRIBE message /// </summary>
/// </summary> WaitForPuback,
SendSubscribe,
/// <summary>
// [v3.1.1] UNSUBSCRIBE isn't "officially" QOS = 1 /// QOS = 2, PUBLISH sent, wait for PUBREC
/// <summary> /// </summary>
/// Send UNSUBSCRIBE message WaitForPubrec,
/// </summary>
SendUnsubscribe, /// <summary>
/// QOS = 2, PUBREC sent, wait for PUBREL
/// <summary> /// </summary>
/// (QOS = 1), SUBSCRIBE sent, wait for SUBACK WaitForPubrel,
/// </summary>
WaitForSuback, /// <summary>
/// QOS = 2, PUBREL sent, wait for PUBCOMP
/// <summary> /// </summary>
/// (QOS = 1), UNSUBSCRIBE sent, wait for UNSUBACK WaitForPubcomp,
/// </summary>
WaitForUnsuback /// <summary>
} /// QOS = 2, start first phase handshake send PUBREC
/// </summary>
SendPubrec,
/// <summary>
/// QOS = 2, start second phase handshake send PUBREL
/// </summary>
SendPubrel,
/// <summary>
/// QOS = 2, end second phase handshake send PUBCOMP
/// </summary>
SendPubcomp,
/// <summary>
/// QOS = 1, PUBLISH received, send PUBACK
/// </summary>
SendPuback,
// [v3.1.1] SUBSCRIBE isn't "officially" QOS = 1
/// <summary>
/// Send SUBSCRIBE message
/// </summary>
SendSubscribe,
// [v3.1.1] UNSUBSCRIBE isn't "officially" QOS = 1
/// <summary>
/// Send UNSUBSCRIBE message
/// </summary>
SendUnsubscribe,
/// <summary>
/// (QOS = 1), SUBSCRIBE sent, wait for SUBACK
/// </summary>
WaitForSuback,
/// <summary>
/// (QOS = 1), UNSUBSCRIBE sent, wait for UNSUBACK
/// </summary>
WaitForUnsuback
}
} }

View File

@ -14,73 +14,66 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for DISCONNECT message from client to broker
/// </summary>
public class MqttMsgDisconnect : MqttMsgBase {
/// <summary> /// <summary>
/// Class for DISCONNECT message from client to broker /// Constructor
/// </summary> /// </summary>
public class MqttMsgDisconnect : MqttMsgBase public MqttMsgDisconnect() => this.Type = MQTT_MSG_DISCONNECT_TYPE;
{
/// <summary> /// <summary>
/// Constructor /// Parse bytes for a DISCONNECT message
/// </summary> /// </summary>
public MqttMsgDisconnect() /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
{ /// <param name="protocolVersion">Protocol Version</param>
this.type = MQTT_MSG_DISCONNECT_TYPE; /// <param name="channel">Channel connected to the broker</param>
} /// <returns>DISCONNECT message instance</returns>
public static MqttMsgDisconnect Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
/// <summary> MqttMsgDisconnect msg = new MqttMsgDisconnect();
/// Parse bytes for a DISCONNECT message
/// </summary> if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
/// <param name="fixedHeaderFirstByte">First fixed header byte</param> // [v3.1.1] check flag bits
/// <param name="protocolVersion">Protocol Version</param> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS) {
/// <param name="channel">Channel connected to the broker</param> throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// <returns>DISCONNECT message instance</returns> }
public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) }
{
MqttMsgDisconnect msg = new MqttMsgDisconnect(); // get remaining length and allocate buffer
_ = DecodeRemainingLength(channel);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) // NOTE : remainingLength must be 0
{
// [v3.1.1] check flag bits return msg;
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS) }
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} public override Byte[] GetBytes(Byte protocolVersion) {
Byte[] buffer = new Byte[2];
// get remaining length and allocate buffer Int32 index = 0;
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
// NOTE : remainingLength must be 0 // first fixed header byte
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
return msg; ? (Byte)((MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_DISCONNECT_FLAG_BITS)
} : (Byte)(MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET);
public override byte[] GetBytes(byte protocolVersion) buffer[index++] = 0x00;
{
byte[] buffer = new byte[2]; return buffer;
int index = 0; }
// first fixed header byte public override String ToString() =>
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_DISCONNECT_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = 0x00;
return buffer;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"DISCONNECT", "DISCONNECT",
null, null,
null); null);
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,73 +14,66 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for PINGREQ message from client to broker
/// </summary>
public class MqttMsgPingReq : MqttMsgBase {
/// <summary> /// <summary>
/// Class for PINGREQ message from client to broker /// Constructor
/// </summary> /// </summary>
public class MqttMsgPingReq : MqttMsgBase public MqttMsgPingReq() => this.Type = MQTT_MSG_PINGREQ_TYPE;
{
/// <summary> public override Byte[] GetBytes(Byte protocolVersion) {
/// Constructor Byte[] buffer = new Byte[2];
/// </summary> Int32 index = 0;
public MqttMsgPingReq()
{ // first fixed header byte
this.type = MQTT_MSG_PINGREQ_TYPE; buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
} ? (Byte)((MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGREQ_FLAG_BITS)
: (Byte)(MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET);
public override byte[] GetBytes(byte protocolVersion)
{ buffer[index++] = 0x00;
byte[] buffer = new byte[2];
int index = 0; return buffer;
}
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) /// <summary>
buffer[index++] = (MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGREQ_FLAG_BITS; // [v.3.1.1] /// Parse bytes for a PINGREQ message
else /// </summary>
buffer[index++] = (MQTT_MSG_PINGREQ_TYPE << MSG_TYPE_OFFSET); /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
buffer[index++] = 0x00; /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
return buffer; /// <returns>PINGREQ message instance</returns>
} public static MqttMsgPingReq Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
MqttMsgPingReq msg = new MqttMsgPingReq();
/// <summary>
/// Parse bytes for a PINGREQ message if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
/// </summary> // [v3.1.1] check flag bits
/// <param name="fixedHeaderFirstByte">First fixed header byte</param> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGREQ_FLAG_BITS) {
/// <param name="protocolVersion">Protocol Version</param> throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// <param name="channel">Channel connected to the broker</param> }
/// <returns>PINGREQ message instance</returns> }
public static MqttMsgPingReq Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{ // already know remaininglength is zero (MQTT specification),
MqttMsgPingReq msg = new MqttMsgPingReq(); // so it isn't necessary to read other data from socket
_ = DecodeRemainingLength(channel);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{ return msg;
// [v3.1.1] check flag bits }
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGREQ_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); public override String ToString() =>
}
// already know remaininglength is zero (MQTT specification),
// so it isn't necessary to read other data from socket
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
return msg;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PINGREQ", "PINGREQ",
null, null,
null); null);
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -17,71 +17,63 @@ Contributors:
using System; using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for PINGRESP message from client to broker
/// </summary>
public class MqttMsgPingResp : MqttMsgBase {
/// <summary> /// <summary>
/// Class for PINGRESP message from client to broker /// Constructor
/// </summary> /// </summary>
public class MqttMsgPingResp : MqttMsgBase public MqttMsgPingResp() => this.Type = MQTT_MSG_PINGRESP_TYPE;
{
/// <summary> /// <summary>
/// Constructor /// Parse bytes for a PINGRESP message
/// </summary> /// </summary>
public MqttMsgPingResp() /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
{ /// <param name="protocolVersion">Protocol Version</param>
this.type = MQTT_MSG_PINGRESP_TYPE; /// <param name="channel">Channel connected to the broker</param>
} /// <returns>PINGRESP message instance</returns>
public static MqttMsgPingResp Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
/// <summary> MqttMsgPingResp msg = new MqttMsgPingResp();
/// Parse bytes for a PINGRESP message
/// </summary> if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
/// <param name="fixedHeaderFirstByte">First fixed header byte</param> // [v3.1.1] check flag bits
/// <param name="protocolVersion">Protocol Version</param> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS) {
/// <param name="channel">Channel connected to the broker</param> throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// <returns>PINGRESP message instance</returns> }
public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) }
{
MqttMsgPingResp msg = new MqttMsgPingResp(); // already know remaininglength is zero (MQTT specification),
// so it isn't necessary to read other data from socket
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) _ = DecodeRemainingLength(channel);
{
// [v3.1.1] check flag bits return msg;
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS) }
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} public override Byte[] GetBytes(Byte protocolVersion) {
Byte[] buffer = new Byte[2];
// already know remaininglength is zero (MQTT specification), Int32 index = 0;
// so it isn't necessary to read other data from socket
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); // first fixed header byte
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
return msg; ? (Byte)((MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGRESP_FLAG_BITS)
} : (Byte)(MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET);
public override byte[] GetBytes(byte protocolVersion) buffer[index++] = 0x00;
{
byte[] buffer = new byte[2]; return buffer;
int index = 0; }
// first fixed header byte public override String ToString() =>
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PINGRESP_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (MQTT_MSG_PINGRESP_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = 0x00;
return buffer;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PINGRESP", "PINGRESP",
null, null,
null); null);
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,112 +14,102 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for PUBACK message from broker to client
/// </summary>
public class MqttMsgPuback : MqttMsgBase {
/// <summary> /// <summary>
/// Class for PUBACK message from broker to client /// Constructor
/// </summary> /// </summary>
public class MqttMsgPuback : MqttMsgBase public MqttMsgPuback() => this.Type = MQTT_MSG_PUBACK_TYPE;
{
/// <summary> public override Byte[] GetBytes(Byte protocolVersion) {
/// Constructor Int32 varHeaderSize = 0;
/// </summary> Int32 payloadSize = 0;
public MqttMsgPuback() Int32 remainingLength = 0;
{ Byte[] buffer;
this.type = MQTT_MSG_PUBACK_TYPE; Int32 index = 0;
}
// message identifier
public override byte[] GetBytes(byte protocolVersion) varHeaderSize += MESSAGE_ID_SIZE;
{
int fixedHeaderSize = 0; remainingLength += varHeaderSize + payloadSize;
int varHeaderSize = 0;
int payloadSize = 0; // first byte of fixed header
int remainingLength = 0; Int32 fixedHeaderSize = 1;
byte[] buffer;
int index = 0; Int32 temp = remainingLength;
// increase fixed header size based on remaining length
// message identifier // (each remaining length byte can encode until 128)
varHeaderSize += MESSAGE_ID_SIZE; do {
fixedHeaderSize++;
remainingLength += (varHeaderSize + payloadSize); temp /= 128;
} while (temp > 0);
// first byte of fixed header
fixedHeaderSize = 1; // allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
int temp = remainingLength;
// increase fixed header size based on remaining length // first fixed header byte
// (each remaining length byte can encode until 128) buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
do ? (Byte)((MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBACK_FLAG_BITS)
{ : (Byte)(MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET);
fixedHeaderSize++;
temp = temp / 128; // encode remaining length
} while (temp > 0); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// allocate buffer for message // get message identifier
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) return buffer;
buffer[index++] = (MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBACK_FLAG_BITS; // [v.3.1.1] }
else
buffer[index++] = (MQTT_MSG_PUBACK_TYPE << MSG_TYPE_OFFSET); /// <summary>
/// Parse bytes for a PUBACK message
// encode remaining length /// </summary>
index = this.encodeRemainingLength(remainingLength, buffer, index); /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
// get message identifier /// <param name="channel">Channel connected to the broker</param>
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB /// <returns>PUBACK message instance</returns>
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB public static MqttMsgPuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
Byte[] buffer;
return buffer; Int32 index = 0;
} MqttMsgPuback msg = new MqttMsgPuback();
/// <summary> if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
/// Parse bytes for a PUBACK message // [v3.1.1] check flag bits
/// </summary> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBACK_FLAG_BITS) {
/// <param name="fixedHeaderFirstByte">First fixed header byte</param> throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// <param name="protocolVersion">Protocol Version</param> }
/// <param name="channel">Channel connected to the broker</param> }
/// <returns>PUBACK message instance</returns>
public static MqttMsgPuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) // get remaining length and allocate buffer
{ Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
byte[] buffer; buffer = new Byte[remainingLength];
int index = 0;
MqttMsgPuback msg = new MqttMsgPuback(); // read bytes from socket...
_ = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{ // message id
// [v3.1.1] check flag bits msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBACK_FLAG_BITS) msg.MessageId |= buffer[index++];
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} return msg;
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); public override String ToString() =>
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
return msg;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBACK", "PUBACK",
new object[] { "messageId" }, new Object[] { "messageId" },
new object[] { this.messageId }); new Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,112 +14,102 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for PUBCOMP message from broker to client
/// </summary>
public class MqttMsgPubcomp : MqttMsgBase {
/// <summary> /// <summary>
/// Class for PUBCOMP message from broker to client /// Constructor
/// </summary> /// </summary>
public class MqttMsgPubcomp : MqttMsgBase public MqttMsgPubcomp() => this.Type = MQTT_MSG_PUBCOMP_TYPE;
{
/// <summary> public override Byte[] GetBytes(Byte protocolVersion) {
/// Constructor Int32 varHeaderSize = 0;
/// </summary> Int32 payloadSize = 0;
public MqttMsgPubcomp() Int32 remainingLength = 0;
{ Byte[] buffer;
this.type = MQTT_MSG_PUBCOMP_TYPE; Int32 index = 0;
}
// message identifier
public override byte[] GetBytes(byte protocolVersion) varHeaderSize += MESSAGE_ID_SIZE;
{
int fixedHeaderSize = 0; remainingLength += varHeaderSize + payloadSize;
int varHeaderSize = 0;
int payloadSize = 0; // first byte of fixed header
int remainingLength = 0; Int32 fixedHeaderSize = 1;
byte[] buffer;
int index = 0; Int32 temp = remainingLength;
// increase fixed header size based on remaining length
// message identifier // (each remaining length byte can encode until 128)
varHeaderSize += MESSAGE_ID_SIZE; do {
fixedHeaderSize++;
remainingLength += (varHeaderSize + payloadSize); temp /= 128;
} while (temp > 0);
// first byte of fixed header
fixedHeaderSize = 1; // allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
int temp = remainingLength;
// increase fixed header size based on remaining length // first fixed header byte
// (each remaining length byte can encode until 128) buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
do ? (Byte)((MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBCOMP_FLAG_BITS)
{ : (Byte)(MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET);
fixedHeaderSize++;
temp = temp / 128; // encode remaining length
} while (temp > 0); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// allocate buffer for message // get message identifier
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) return buffer;
buffer[index++] = (MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBCOMP_FLAG_BITS; // [v.3.1.1] }
else
buffer[index++] = (MQTT_MSG_PUBCOMP_TYPE << MSG_TYPE_OFFSET); /// <summary>
/// Parse bytes for a PUBCOMP message
// encode remaining length /// </summary>
index = this.encodeRemainingLength(remainingLength, buffer, index); /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
// get message identifier /// <param name="channel">Channel connected to the broker</param>
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB /// <returns>PUBCOMP message instance</returns>
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB public static MqttMsgPubcomp Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
Byte[] buffer;
return buffer; Int32 index = 0;
} MqttMsgPubcomp msg = new MqttMsgPubcomp();
/// <summary> if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
/// Parse bytes for a PUBCOMP message // [v3.1.1] check flag bits
/// </summary> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBCOMP_FLAG_BITS) {
/// <param name="fixedHeaderFirstByte">First fixed header byte</param> throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// <param name="protocolVersion">Protocol Version</param> }
/// <param name="channel">Channel connected to the broker</param> }
/// <returns>PUBCOMP message instance</returns>
public static MqttMsgPubcomp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) // get remaining length and allocate buffer
{ Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
byte[] buffer; buffer = new Byte[remainingLength];
int index = 0;
MqttMsgPubcomp msg = new MqttMsgPubcomp(); // read bytes from socket...
_ = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{ // message id
// [v3.1.1] check flag bits msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBCOMP_FLAG_BITS) msg.MessageId |= buffer[index++];
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} return msg;
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); public override String ToString() =>
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
return msg;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBCOMP", "PUBCOMP",
new object[] { "messageId" }, new Object[] { "messageId" },
new object[] { this.messageId }); new Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -40,9 +40,7 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
public MqttMsgPublish() { public MqttMsgPublish() => this.Type = MQTT_MSG_PUBLISH_TYPE;
this.type = MQTT_MSG_PUBLISH_TYPE;
}
/// <summary> /// <summary>
/// Constructor /// Constructor
@ -61,17 +59,16 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
/// <param name="qosLevel">Quality of Service level</param> /// <param name="qosLevel">Quality of Service level</param>
/// <param name="retain">Retain flag</param> /// <param name="retain">Retain flag</param>
public MqttMsgPublish(String topic, Byte[] message, Boolean dupFlag, Byte qosLevel, Boolean retain) : base() { public MqttMsgPublish(String topic, Byte[] message, Boolean dupFlag, Byte qosLevel, Boolean retain) : base() {
this.type = MQTT_MSG_PUBLISH_TYPE; this.Type = MQTT_MSG_PUBLISH_TYPE;
this.Topic = topic; this.Topic = topic;
this.Message = message; this.Message = message;
this.dupFlag = dupFlag; this.DupFlag = dupFlag;
this.qosLevel = qosLevel; this.QosLevel = qosLevel;
this.retain = retain; this.Retain = retain;
this.messageId = 0; this.MessageId = 0;
} }
public override Byte[] GetBytes(Byte protocolVersion) { public override Byte[] GetBytes(Byte protocolVersion) {
Int32 fixedHeaderSize = 0;
Int32 varHeaderSize = 0; Int32 varHeaderSize = 0;
Int32 payloadSize = 0; Int32 payloadSize = 0;
Int32 remainingLength = 0; Int32 remainingLength = 0;
@ -79,17 +76,17 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
Int32 index = 0; Int32 index = 0;
// topic can't contain wildcards // topic can't contain wildcards
if ((this.Topic.IndexOf('#') != -1) || (this.Topic.IndexOf('+') != -1)) { if (this.Topic.IndexOf('#') != -1 || this.Topic.IndexOf('+') != -1) {
throw new MqttClientException(MqttClientErrorCode.TopicWildcard); throw new MqttClientException(MqttClientErrorCode.TopicWildcard);
} }
// check topic length // check topic length
if ((this.Topic.Length < MIN_TOPIC_LENGTH) || (this.Topic.Length > MAX_TOPIC_LENGTH)) { if (this.Topic.Length < MIN_TOPIC_LENGTH || this.Topic.Length > MAX_TOPIC_LENGTH) {
throw new MqttClientException(MqttClientErrorCode.TopicLength); throw new MqttClientException(MqttClientErrorCode.TopicLength);
} }
// check wrong QoS level (both bits can't be set 1) // check wrong QoS level (both bits can't be set 1)
if (this.qosLevel > QOS_LEVEL_EXACTLY_ONCE) { if (this.QosLevel > QOS_LEVEL_EXACTLY_ONCE) {
throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
} }
@ -99,7 +96,7 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
varHeaderSize += topicUtf8.Length + 2; varHeaderSize += topicUtf8.Length + 2;
// message id is valid only with QOS level 1 or QOS level 2 // message id is valid only with QOS level 1 or QOS level 2
if ((this.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || (this.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { if (this.QosLevel == QOS_LEVEL_AT_LEAST_ONCE || this.QosLevel == QOS_LEVEL_EXACTLY_ONCE) {
varHeaderSize += MESSAGE_ID_SIZE; varHeaderSize += MESSAGE_ID_SIZE;
} }
@ -109,30 +106,30 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
payloadSize += this.Message.Length; payloadSize += this.Message.Length;
} }
remainingLength += (varHeaderSize + payloadSize); remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header // first byte of fixed header
fixedHeaderSize = 1; Int32 fixedHeaderSize = 1;
Int32 temp = remainingLength; Int32 temp = remainingLength;
// increase fixed header size based on remaining length // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128) // (each remaining length byte can encode until 128)
do { do {
fixedHeaderSize++; fixedHeaderSize++;
temp = temp / 128; temp /= 128;
} while (temp > 0); } while (temp > 0);
// allocate buffer for message // allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte // first fixed header byte
buffer[index] = (Byte)((MQTT_MSG_PUBLISH_TYPE << MSG_TYPE_OFFSET) | (this.qosLevel << QOS_LEVEL_OFFSET)); buffer[index] = (Byte)((MQTT_MSG_PUBLISH_TYPE << MSG_TYPE_OFFSET) | (this.QosLevel << QOS_LEVEL_OFFSET));
buffer[index] |= this.dupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00; buffer[index] |= this.DupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00;
buffer[index] |= this.retain ? (Byte)(1 << RETAIN_FLAG_OFFSET) : (Byte)0x00; buffer[index] |= this.Retain ? (Byte)(1 << RETAIN_FLAG_OFFSET) : (Byte)0x00;
index++; index++;
// encode remaining length // encode remaining length
index = this.encodeRemainingLength(remainingLength, buffer, index); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// topic name // topic name
buffer[index++] = (Byte)((topicUtf8.Length >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((topicUtf8.Length >> 8) & 0x00FF); // MSB
@ -141,22 +138,22 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
index += topicUtf8.Length; index += topicUtf8.Length;
// message id is valid only with QOS level 1 or QOS level 2 // message id is valid only with QOS level 1 or QOS level 2
if ((this.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || if (this.QosLevel == QOS_LEVEL_AT_LEAST_ONCE ||
(this.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { this.QosLevel == QOS_LEVEL_EXACTLY_ONCE) {
// check message identifier assigned // check message identifier assigned
if (this.messageId == 0) { if (this.MessageId == 0) {
throw new MqttClientException(MqttClientErrorCode.WrongMessageId); throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
} }
buffer[index++] = (Byte)((this.messageId >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(this.messageId & 0x00FF); // LSB buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
} }
// check on message with zero length // check on message with zero length
if (this.Message != null) { if (this.Message != null) {
// message data // message data
Array.Copy(this.Message, 0, buffer, index, this.Message.Length); Array.Copy(this.Message, 0, buffer, index, this.Message.Length);
index += this.Message.Length; _ = this.Message.Length;
} }
return buffer; return buffer;
@ -177,14 +174,14 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
MqttMsgPublish msg = new MqttMsgPublish(); MqttMsgPublish msg = new MqttMsgPublish();
// get remaining length and allocate buffer // get remaining length and allocate buffer
Int32 remainingLength = decodeRemainingLength(channel); Int32 remainingLength = DecodeRemainingLength(channel);
buffer = new Byte[remainingLength]; buffer = new Byte[remainingLength];
// read bytes from socket... // read bytes from socket...
Int32 received = channel.Receive(buffer); Int32 received = channel.Receive(buffer);
// topic name // topic name
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length = (buffer[index++] << 8) & 0xFF00;
topicUtf8Length |= buffer[index++]; topicUtf8Length |= buffer[index++];
topicUtf8 = new Byte[topicUtf8Length]; topicUtf8 = new Byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
@ -192,22 +189,22 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
msg.Topic = new String(Encoding.UTF8.GetChars(topicUtf8)); msg.Topic = new String(Encoding.UTF8.GetChars(topicUtf8));
// read QoS level from fixed header // read QoS level from fixed header
msg.qosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); msg.QosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// check wrong QoS level (both bits can't be set 1) // check wrong QoS level (both bits can't be set 1)
if (msg.qosLevel > QOS_LEVEL_EXACTLY_ONCE) { if (msg.QosLevel > QOS_LEVEL_EXACTLY_ONCE) {
throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
} }
// read DUP flag from fixed header // read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01); msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
// read retain flag from fixed header // read retain flag from fixed header
msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01); msg.Retain = (fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET == 0x01;
// message id is valid only with QOS level 1 or QOS level 2 // message id is valid only with QOS level 1 or QOS level 2
if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) || if (msg.QosLevel == QOS_LEVEL_AT_LEAST_ONCE ||
(msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE)) { msg.QosLevel == QOS_LEVEL_EXACTLY_ONCE) {
// message id // message id
msg.messageId = (UInt16)((buffer[index++] << 8) & 0xFF00); msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]); msg.MessageId |= buffer[index++];
} }
// get payload with message data // get payload with message data
@ -220,8 +217,8 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
// copy first part of payload data received // copy first part of payload data received
Array.Copy(buffer, index, msg.Message, messageOffset, received - index); Array.Copy(buffer, index, msg.Message, messageOffset, received - index);
remaining -= (received - index); remaining -= received - index;
messageOffset += (received - index); messageOffset += received - index;
// if payload isn't finished // if payload isn't finished
while (remaining > 0) { while (remaining > 0) {
@ -235,15 +232,15 @@ namespace uPLibrary.Networking.M2Mqtt.Messages {
return msg; return msg;
} }
public override String ToString() { public override String ToString() =>
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBLISH", "PUBLISH",
new Object[] { "messageId", "topic", "message" }, new Object[] { "messageId", "topic", "message" },
new Object[] { this.messageId, this.Topic, this.Message }); new Object[] { this.MessageId, this.Topic, this.Message });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,98 +14,66 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Event Args class for PUBLISH message received from broker
/// </summary>
public class MqttMsgPublishEventArgs : EventArgs {
#region Properties...
/// <summary> /// <summary>
/// Event Args class for PUBLISH message received from broker /// Message topic
/// </summary> /// </summary>
public class MqttMsgPublishEventArgs : EventArgs public String Topic { get; internal set; }
{
#region Properties... /// <summary>
/// Message data
/// <summary> /// </summary>
/// Message topic public Byte[] Message { get; internal set; }
/// </summary>
public string Topic /// <summary>
{ /// Duplicate message flag
get { return this.topic; } /// </summary>
internal set { this.topic = value; } public Boolean DupFlag { get; set; }
}
/// <summary>
/// <summary> /// Quality of Service level
/// Message data /// </summary>
/// </summary> public Byte QosLevel { get; internal set; }
public byte[] Message
{ /// <summary>
get { return this.message; } /// Retain message flag
internal set { this.message = value; } /// </summary>
} public Boolean Retain { get; internal set; }
/// <summary> #endregion
/// Duplicate message flag
/// </summary> // message topic
public bool DupFlag
{ /// <summary>
get { return this.dupFlag; } /// Constructor
set { this.dupFlag = value; } /// </summary>
} /// <param name="topic">Message topic</param>
/// <param name="message">Message data</param>
/// <summary> /// <param name="dupFlag">Duplicate delivery flag</param>
/// Quality of Service level /// <param name="qosLevel">Quality of Service level</param>
/// </summary> /// <param name="retain">Retain flag</param>
public byte QosLevel public MqttMsgPublishEventArgs(String topic,
{ Byte[] message,
get { return this.qosLevel; } Boolean dupFlag,
internal set { this.qosLevel = value; } Byte qosLevel,
} Boolean retain) {
this.Topic = topic;
/// <summary> this.Message = message;
/// Retain message flag this.DupFlag = dupFlag;
/// </summary> this.QosLevel = qosLevel;
public bool Retain this.Retain = retain;
{ }
get { return this.retain; } }
internal set { this.retain = value; }
}
#endregion
// message topic
private string topic;
// message data
private byte[] message;
// duplicate delivery
private bool dupFlag;
// quality of service level
private byte qosLevel;
// retain flag
private bool retain;
/// <summary>
/// Constructor
/// </summary>
/// <param name="topic">Message topic</param>
/// <param name="message">Message data</param>
/// <param name="dupFlag">Duplicate delivery flag</param>
/// <param name="qosLevel">Quality of Service level</param>
/// <param name="retain">Retain flag</param>
public MqttMsgPublishEventArgs(string topic,
byte[] message,
bool dupFlag,
byte qosLevel,
bool retain)
{
this.topic = topic;
this.message = message;
this.dupFlag = dupFlag;
this.qosLevel = qosLevel;
this.retain = retain;
}
}
} }

View File

@ -14,65 +14,49 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Event Args class for published message
/// </summary>
public class MqttMsgPublishedEventArgs : EventArgs {
#region Properties...
/// <summary> /// <summary>
/// Event Args class for published message /// Message identifier
/// </summary> /// </summary>
public class MqttMsgPublishedEventArgs : EventArgs public UInt16 MessageId { get; internal set; }
{
#region Properties... /// <summary>
/// Message published (or failed due to retries)
/// <summary> /// </summary>
/// Message identifier public Boolean IsPublished { get; internal set; }
/// </summary>
public ushort MessageId #endregion
{
get { return this.messageId; } // message identifier
internal set { this.messageId = value; }
} /// <summary>
/// Constructor (published message)
/// <summary> /// </summary>
/// Message published (or failed due to retries) /// <param name="messageId">Message identifier published</param>
/// </summary> public MqttMsgPublishedEventArgs(UInt16 messageId)
public bool IsPublished : this(messageId, true) {
{ }
get { return this.isPublished; }
internal set { this.isPublished = value; } /// <summary>
} /// Constructor
/// </summary>
#endregion /// <param name="messageId">Message identifier</param>
/// <param name="isPublished">Publish flag</param>
// message identifier public MqttMsgPublishedEventArgs(UInt16 messageId, Boolean isPublished) {
ushort messageId; this.MessageId = messageId;
this.IsPublished = isPublished;
// published flag }
bool isPublished; }
/// <summary>
/// Constructor (published message)
/// </summary>
/// <param name="messageId">Message identifier published</param>
public MqttMsgPublishedEventArgs(ushort messageId)
: this(messageId, true)
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier</param>
/// <param name="isPublished">Publish flag</param>
public MqttMsgPublishedEventArgs(ushort messageId, bool isPublished)
{
this.messageId = messageId;
this.isPublished = isPublished;
}
}
} }

View File

@ -14,112 +14,102 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for PUBREC message from broker to client
/// </summary>
public class MqttMsgPubrec : MqttMsgBase {
/// <summary> /// <summary>
/// Class for PUBREC message from broker to client /// Constructor
/// </summary> /// </summary>
public class MqttMsgPubrec : MqttMsgBase public MqttMsgPubrec() => this.Type = MQTT_MSG_PUBREC_TYPE;
{
/// <summary> public override Byte[] GetBytes(Byte protocolVersion) {
/// Constructor Int32 varHeaderSize = 0;
/// </summary> Int32 payloadSize = 0;
public MqttMsgPubrec() Int32 remainingLength = 0;
{ Byte[] buffer;
this.type = MQTT_MSG_PUBREC_TYPE; Int32 index = 0;
}
// message identifier
public override byte[] GetBytes(byte protocolVersion) varHeaderSize += MESSAGE_ID_SIZE;
{
int fixedHeaderSize = 0; remainingLength += varHeaderSize + payloadSize;
int varHeaderSize = 0;
int payloadSize = 0; // first byte of fixed header
int remainingLength = 0; Int32 fixedHeaderSize = 1;
byte[] buffer;
int index = 0; Int32 temp = remainingLength;
// increase fixed header size based on remaining length
// message identifier // (each remaining length byte can encode until 128)
varHeaderSize += MESSAGE_ID_SIZE; do {
fixedHeaderSize++;
remainingLength += (varHeaderSize + payloadSize); temp /= 128;
} while (temp > 0);
// first byte of fixed header
fixedHeaderSize = 1; // allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
int temp = remainingLength;
// increase fixed header size based on remaining length // first fixed header byte
// (each remaining length byte can encode until 128) buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
do ? (Byte)((MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREC_FLAG_BITS)
{ : (Byte)(MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET);
fixedHeaderSize++;
temp = temp / 128; // encode remaining length
} while (temp > 0); index = this.EncodeRemainingLength(remainingLength, buffer, index);
// allocate buffer for message // get message identifier
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) return buffer;
buffer[index++] = (MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREC_FLAG_BITS; // [v.3.1.1] }
else
buffer[index++] = (MQTT_MSG_PUBREC_TYPE << MSG_TYPE_OFFSET); /// <summary>
/// Parse bytes for a PUBREC message
// encode remaining length /// </summary>
index = this.encodeRemainingLength(remainingLength, buffer, index); /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
// get message identifier /// <param name="channel">Channel connected to the broker</param>
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB /// <returns>PUBREC message instance</returns>
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB public static MqttMsgPubrec Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
Byte[] buffer;
return buffer; Int32 index = 0;
} MqttMsgPubrec msg = new MqttMsgPubrec();
/// <summary> if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
/// Parse bytes for a PUBREC message // [v3.1.1] check flag bits
/// </summary> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREC_FLAG_BITS) {
/// <param name="fixedHeaderFirstByte">First fixed header byte</param> throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// <param name="protocolVersion">Protocol Version</param> }
/// <param name="channel">Channel connected to the broker</param> }
/// <returns>PUBREC message instance</returns>
public static MqttMsgPubrec Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) // get remaining length and allocate buffer
{ Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
byte[] buffer; buffer = new Byte[remainingLength];
int index = 0;
MqttMsgPubrec msg = new MqttMsgPubrec(); // read bytes from socket...
_ = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{ // message id
// [v3.1.1] check flag bits msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREC_FLAG_BITS) msg.MessageId |= buffer[index++];
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} return msg;
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); public override String ToString() =>
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
return msg;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBREC", "PUBREC",
new object[] { "messageId" }, new Object[] { "messageId" },
new object[] { this.messageId }); new Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -16,127 +16,117 @@ Contributors:
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for PUBREL message from client top broker
/// </summary>
public class MqttMsgPubrel : MqttMsgBase {
/// <summary> /// <summary>
/// Class for PUBREL message from client top broker /// Constructor
/// </summary> /// </summary>
public class MqttMsgPubrel : MqttMsgBase public MqttMsgPubrel() {
{ this.Type = MQTT_MSG_PUBREL_TYPE;
/// <summary> // PUBREL message use QoS Level 1 (not "officially" in 3.1.1)
/// Constructor this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
/// </summary> }
public MqttMsgPubrel()
{ public override System.Byte[] GetBytes(System.Byte protocolVersion) {
this.type = MQTT_MSG_PUBREL_TYPE; System.Int32 varHeaderSize = 0;
// PUBREL message use QoS Level 1 (not "officially" in 3.1.1) System.Int32 payloadSize = 0;
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE; System.Int32 remainingLength = 0;
} System.Byte[] buffer;
System.Int32 index = 0;
public override byte[] GetBytes(byte protocolVersion)
{ // message identifier
int fixedHeaderSize = 0; varHeaderSize += MESSAGE_ID_SIZE;
int varHeaderSize = 0;
int payloadSize = 0; remainingLength += varHeaderSize + payloadSize;
int remainingLength = 0;
byte[] buffer; // first byte of fixed header
int index = 0; System.Int32 fixedHeaderSize = 1;
// message identifier System.Int32 temp = remainingLength;
varHeaderSize += MESSAGE_ID_SIZE; // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
remainingLength += (varHeaderSize + payloadSize); do {
fixedHeaderSize++;
// first byte of fixed header temp /= 128;
fixedHeaderSize = 1; } while (temp > 0);
int temp = remainingLength; // allocate buffer for message
// increase fixed header size based on remaining length buffer = new System.Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// (each remaining length byte can encode until 128)
do // first fixed header byte
{ if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
fixedHeaderSize++; buffer[index++] = (MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREL_FLAG_BITS; // [v.3.1.1]
temp = temp / 128; } else {
} while (temp > 0); buffer[index] = (System.Byte)((MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) |
(this.QosLevel << QOS_LEVEL_OFFSET));
// allocate buffer for message buffer[index] |= this.DupFlag ? (System.Byte)(1 << DUP_FLAG_OFFSET) : (System.Byte)0x00;
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; index++;
}
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) // encode remaining length
buffer[index++] = (MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_PUBREL_FLAG_BITS; // [v.3.1.1] index = this.EncodeRemainingLength(remainingLength, buffer, index);
else
{ // get next message identifier
buffer[index] = (byte)((MQTT_MSG_PUBREL_TYPE << MSG_TYPE_OFFSET) | buffer[index++] = (System.Byte)((this.MessageId >> 8) & 0x00FF); // MSB
(this.qosLevel << QOS_LEVEL_OFFSET)); buffer[index++] = (System.Byte)(this.MessageId & 0x00FF); // LSB
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
index++; return buffer;
} }
// encode remaining length /// <summary>
index = this.encodeRemainingLength(remainingLength, buffer, index); /// Parse bytes for a PUBREL message
/// </summary>
// get next message identifier /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
buffer[index++] = (byte)((this.messageId >> 8) & 0x00FF); // MSB /// <param name="protocolVersion">Protocol Version</param>
buffer[index++] = (byte)(this.messageId & 0x00FF); // LSB /// <param name="channel">Channel connected to the broker</param>
/// <returns>PUBREL message instance</returns>
return buffer; public static MqttMsgPubrel Parse(System.Byte fixedHeaderFirstByte, System.Byte protocolVersion, IMqttNetworkChannel channel) {
} System.Byte[] buffer;
System.Int32 index = 0;
/// <summary> MqttMsgPubrel msg = new MqttMsgPubrel();
/// Parse bytes for a PUBREL message
/// </summary> if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
/// <param name="fixedHeaderFirstByte">First fixed header byte</param> // [v3.1.1] check flag bits
/// <param name="protocolVersion">Protocol Version</param> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREL_FLAG_BITS) {
/// <param name="channel">Channel connected to the broker</param> throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// <returns>PUBREL message instance</returns> }
public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) }
{
byte[] buffer; // get remaining length and allocate buffer
int index = 0; System.Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
MqttMsgPubrel msg = new MqttMsgPubrel(); buffer = new System.Byte[remainingLength];
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) // read bytes from socket...
{ _ = channel.Receive(buffer);
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREL_FLAG_BITS) if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); // only 3.1.0
}
// read QoS level from fixed header (would be QoS Level 1)
// get remaining length and allocate buffer msg.QosLevel = (System.Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); // read DUP flag from fixed header
buffer = new byte[remainingLength]; msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
}
// read bytes from socket...
channel.Receive(buffer); // message id
msg.MessageId = (System.UInt16)((buffer[index++] << 8) & 0xFF00);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) msg.MessageId |= buffer[index++];
{
// only 3.1.0 return msg;
}
// read QoS level from fixed header (would be QoS Level 1)
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET); public override System.String ToString() =>
// read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
}
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
return msg;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"PUBREL", "PUBREL",
new object[] { "messageId" }, new System.Object[] { "messageId" },
new object[] { this.messageId }); new System.Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -17,146 +17,127 @@ Contributors:
using System; using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for SUBACK message from broker to client
/// </summary>
public class MqttMsgSuback : MqttMsgBase {
#region Properties...
/// <summary> /// <summary>
/// Class for SUBACK message from broker to client /// List of granted QOS Levels
/// </summary> /// </summary>
public class MqttMsgSuback : MqttMsgBase public Byte[] GrantedQoSLevels { get; set; }
{
#region Properties... #endregion
/// <summary> // granted QOS levels
/// List of granted QOS Levels
/// </summary> /// <summary>
public byte[] GrantedQoSLevels /// Constructor
{ /// </summary>
get { return this.grantedQosLevels; } public MqttMsgSuback() => this.Type = MQTT_MSG_SUBACK_TYPE;
set { this.grantedQosLevels = value; }
} /// <summary>
/// Parse bytes for a SUBACK message
#endregion /// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
// granted QOS levels /// <param name="protocolVersion">Protocol Version</param>
byte[] grantedQosLevels; /// <param name="channel">Channel connected to the broker</param>
/// <returns>SUBACK message instance</returns>
/// <summary> public static MqttMsgSuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
/// Constructor Byte[] buffer;
/// </summary> Int32 index = 0;
public MqttMsgSuback() MqttMsgSuback msg = new MqttMsgSuback();
{
this.type = MQTT_MSG_SUBACK_TYPE; 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) {
/// <summary> throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// Parse bytes for a SUBACK message }
/// </summary> }
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param> // get remaining length and allocate buffer
/// <param name="channel">Channel connected to the broker</param> Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
/// <returns>SUBACK message instance</returns> buffer = new Byte[remainingLength];
public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{ // read bytes from socket...
byte[] buffer; _ = channel.Receive(buffer);
int index = 0;
MqttMsgSuback msg = new MqttMsgSuback(); // message id
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) msg.MessageId |= buffer[index++];
{
// [v3.1.1] check flag bits // payload contains QoS levels granted
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS) msg.GrantedQoSLevels = new Byte[remainingLength - MESSAGE_ID_SIZE];
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); Int32 qosIdx = 0;
} do {
msg.GrantedQoSLevels[qosIdx++] = buffer[index++];
// get remaining length and allocate buffer } while (index < remainingLength);
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength]; return msg;
}
// read bytes from socket...
channel.Receive(buffer); public override Byte[] GetBytes(Byte protocolVersion) {
Int32 varHeaderSize = 0;
// message id Int32 payloadSize = 0;
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); Int32 remainingLength = 0;
msg.messageId |= (buffer[index++]); Byte[] buffer;
Int32 index = 0;
// payload contains QoS levels granted
msg.grantedQosLevels = new byte[remainingLength - MESSAGE_ID_SIZE]; // message identifier
int qosIdx = 0; varHeaderSize += MESSAGE_ID_SIZE;
do
{ Int32 grantedQosIdx;
msg.grantedQosLevels[qosIdx++] = buffer[index++]; for (grantedQosIdx = 0; grantedQosIdx < this.GrantedQoSLevels.Length; grantedQosIdx++) {
} while (index < remainingLength); payloadSize++;
}
return msg;
} remainingLength += varHeaderSize + payloadSize;
public override byte[] GetBytes(byte protocolVersion) // first byte of fixed header
{ Int32 fixedHeaderSize = 1;
int fixedHeaderSize = 0;
int varHeaderSize = 0; Int32 temp = remainingLength;
int payloadSize = 0; // increase fixed header size based on remaining length
int remainingLength = 0; // (each remaining length byte can encode until 128)
byte[] buffer; do {
int index = 0; fixedHeaderSize++;
temp /= 128;
// message identifier } while (temp > 0);
varHeaderSize += MESSAGE_ID_SIZE;
// allocate buffer for message
int grantedQosIdx = 0; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
for (grantedQosIdx = 0; grantedQosIdx < this.grantedQosLevels.Length; grantedQosIdx++)
{ // first fixed header byte
payloadSize++; 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);
remainingLength += (varHeaderSize + payloadSize);
// encode remaining length
// first byte of fixed header index = this.EncodeRemainingLength(remainingLength, buffer, index);
fixedHeaderSize = 1;
// message id
int temp = remainingLength; buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
// increase fixed header size based on remaining length buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
// (each remaining length byte can encode until 128)
do // payload contains QoS levels granted
{ for (grantedQosIdx = 0; grantedQosIdx < this.GrantedQoSLevels.Length; grantedQosIdx++) {
fixedHeaderSize++; buffer[index++] = this.GrantedQoSLevels[grantedQosIdx];
temp = temp / 128; }
} while (temp > 0);
return buffer;
// allocate buffer for message }
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize];
public override String ToString() =>
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
buffer[index++] = (MQTT_MSG_SUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBACK_FLAG_BITS; // [v.3.1.1]
else
buffer[index++] = (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()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"SUBACK", "SUBACK",
new object[] { "messageId", "grantedQosLevels" }, new Object[] { "messageId", "grantedQosLevels" },
new object[] { this.messageId, this.grantedQosLevels }); new Object[] { this.MessageId, this.GrantedQoSLevels });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -16,257 +16,234 @@ Contributors:
using System; using System;
// if NOT .Net Micro Framework // if NOT .Net Micro Framework
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System.Collections.Generic; using System.Collections.Generic;
#endif #endif
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for SUBSCRIBE message from client to broker
/// </summary>
public class MqttMsgSubscribe : MqttMsgBase {
#region Properties...
/// <summary> /// <summary>
/// Class for SUBSCRIBE message from client to broker /// List of topics to subscribe
/// </summary> /// </summary>
public class MqttMsgSubscribe : MqttMsgBase public String[] Topics { get; set; }
{
#region Properties... /// <summary>
/// List of QOS Levels related to topics
/// <summary> /// </summary>
/// List of topics to subscribe public Byte[] QoSLevels { get; set; }
/// </summary>
public string[] Topics #endregion
{
get { return this.topics; } // topics to subscribe
set { this.topics = value; }
} /// <summary>
/// Constructor
/// <summary> /// </summary>
/// List of QOS Levels related to topics public MqttMsgSubscribe() => this.Type = MQTT_MSG_SUBSCRIBE_TYPE;
/// </summary>
public byte[] QoSLevels /// <summary>
{ /// Constructor
get { return this.qosLevels; } /// </summary>
set { this.qosLevels = value; } /// <param name="topics">List of topics to subscribe</param>
} /// <param name="qosLevels">List of QOS Levels related to topics</param>
public MqttMsgSubscribe(String[] topics, Byte[] qosLevels) {
#endregion this.Type = MQTT_MSG_SUBSCRIBE_TYPE;
// topics to subscribe this.Topics = topics;
string[] topics; this.QoSLevels = qosLevels;
// QOS levels related to topics
byte[] qosLevels; // SUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
/// <summary> }
/// Constructor
/// </summary> /// <summary>
public MqttMsgSubscribe() /// Parse bytes for a SUBSCRIBE message
{ /// </summary>
this.type = MQTT_MSG_SUBSCRIBE_TYPE; /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
} /// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <summary> /// <returns>SUBSCRIBE message instance</returns>
/// Constructor public static MqttMsgSubscribe Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
/// </summary> Byte[] buffer;
/// <param name="topics">List of topics to subscribe</param> Int32 index = 0;
/// <param name="qosLevels">List of QOS Levels related to topics</param> Byte[] topicUtf8;
public MqttMsgSubscribe(string[] topics, byte[] qosLevels) Int32 topicUtf8Length;
{ MqttMsgSubscribe msg = new MqttMsgSubscribe();
this.type = MQTT_MSG_SUBSCRIBE_TYPE;
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
this.topics = topics; // [v3.1.1] check flag bits
this.qosLevels = qosLevels; if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
// SUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1) }
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE; }
}
// get remaining length and allocate buffer
/// <summary> Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
/// Parse bytes for a SUBSCRIBE message buffer = new Byte[remainingLength];
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param> // read bytes from socket...
/// <param name="protocolVersion">Protocol Version</param> Int32 received = channel.Receive(buffer);
/// <param name="channel">Channel connected to the broker</param>
/// <returns>SUBSCRIBE message instance</returns> if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) {
public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) // only 3.1.0
{
byte[] buffer; // read QoS level from fixed header
int index = 0; msg.QosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
byte[] topicUtf8; // read DUP flag from fixed header
int topicUtf8Length; msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
MqttMsgSubscribe msg = new MqttMsgSubscribe(); // retain flag not used
msg.Retain = false;
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) }
{
// [v3.1.1] check flag bits // message id
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS) msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); msg.MessageId |= buffer[index++];
}
// payload contains topics and QoS levels
// get remaining length and allocate buffer // NOTE : before, I don't know how many topics will be in the payload (so use List)
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength]; // if .Net Micro Framework
#if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
// read bytes from socket...
int received = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
{
// only 3.1.0
// read QoS level from fixed header
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
// retain flag not used
msg.retain = false;
}
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
// payload contains topics and QoS levels
// NOTE : before, I don't know how many topics will be in the payload (so use List)
// if .Net Micro Framework
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
IList tmpTopics = new ArrayList(); IList tmpTopics = new ArrayList();
IList tmpQosLevels = new ArrayList(); IList tmpQosLevels = new ArrayList();
// else other frameworks (.Net, .Net Compact, Mono, Windows Phone) // else other frameworks (.Net, .Net Compact, Mono, Windows Phone)
#else #else
IList<String> tmpTopics = new List<String>(); IList<String> tmpTopics = new List<String>();
IList<byte> tmpQosLevels = new List<byte>(); IList<Byte> tmpQosLevels = new List<Byte>();
#endif #endif
do do {
{ // topic name
// topic name topicUtf8Length = (buffer[index++] << 8) & 0xFF00;
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++];
topicUtf8Length |= buffer[index++]; topicUtf8 = new Byte[topicUtf8Length];
topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length;
index += topicUtf8Length; tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
// QoS level
// QoS level tmpQosLevels.Add(buffer[index++]);
tmpQosLevels.Add(buffer[index++]);
} while (index < remainingLength);
} while (index < remainingLength);
// copy from list to array
// copy from list to array msg.Topics = new String[tmpTopics.Count];
msg.topics = new string[tmpTopics.Count]; msg.QoSLevels = new Byte[tmpQosLevels.Count];
msg.qosLevels = new byte[tmpQosLevels.Count]; for (Int32 i = 0; i < tmpTopics.Count; i++) {
for (int i = 0; i < tmpTopics.Count; i++) msg.Topics[i] = (String)tmpTopics[i];
{ msg.QoSLevels[i] = (Byte)tmpQosLevels[i];
msg.topics[i] = (string)tmpTopics[i]; }
msg.qosLevels[i] = (byte)tmpQosLevels[i];
} return msg;
}
return msg;
} public override Byte[] GetBytes(Byte protocolVersion) {
Int32 varHeaderSize = 0;
public override byte[] GetBytes(byte protocolVersion) Int32 payloadSize = 0;
{ Int32 remainingLength = 0;
int fixedHeaderSize = 0; Byte[] buffer;
int varHeaderSize = 0; Int32 index = 0;
int payloadSize = 0;
int remainingLength = 0; // topics list empty
byte[] buffer; if (this.Topics == null || this.Topics.Length == 0) {
int index = 0; throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
}
// topics list empty
if ((this.topics == null) || (this.topics.Length == 0)) // qos levels list empty
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty); if (this.QoSLevels == null || this.QoSLevels.Length == 0) {
throw new MqttClientException(MqttClientErrorCode.QosLevelsEmpty);
// qos levels list empty }
if ((this.qosLevels == null) || (this.qosLevels.Length == 0))
throw new MqttClientException(MqttClientErrorCode.QosLevelsEmpty); // topics and qos levels lists length don't match
if (this.Topics.Length != this.QoSLevels.Length) {
// topics and qos levels lists length don't match throw new MqttClientException(MqttClientErrorCode.TopicsQosLevelsNotMatch);
if (this.topics.Length != this.qosLevels.Length) }
throw new MqttClientException(MqttClientErrorCode.TopicsQosLevelsNotMatch);
// message identifier
// message identifier varHeaderSize += MESSAGE_ID_SIZE;
varHeaderSize += MESSAGE_ID_SIZE; Byte[][] topicsUtf8 = new Byte[this.Topics.Length][];
int topicIdx = 0;
byte[][] topicsUtf8 = new byte[this.topics.Length][]; Int32 topicIdx;
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++) // check topic length
{ if (this.Topics[topicIdx].Length < MIN_TOPIC_LENGTH || this.Topics[topicIdx].Length > MAX_TOPIC_LENGTH) {
// check topic length throw new MqttClientException(MqttClientErrorCode.TopicLength);
if ((this.topics[topicIdx].Length < MIN_TOPIC_LENGTH) || (this.topics[topicIdx].Length > MAX_TOPIC_LENGTH)) }
throw new MqttClientException(MqttClientErrorCode.TopicLength);
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.Topics[topicIdx]);
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.topics[topicIdx]); payloadSize += 2; // topic size (MSB, LSB)
payloadSize += 2; // topic size (MSB, LSB) payloadSize += topicsUtf8[topicIdx].Length;
payloadSize += topicsUtf8[topicIdx].Length; payloadSize++; // byte for QoS
payloadSize++; // byte for QoS }
}
remainingLength += varHeaderSize + payloadSize;
remainingLength += (varHeaderSize + payloadSize);
// first byte of fixed header
// first byte of fixed header Int32 fixedHeaderSize = 1;
fixedHeaderSize = 1;
Int32 temp = remainingLength;
int temp = remainingLength; // increase fixed header size based on remaining length
// increase fixed header size based on remaining length // (each remaining length byte can encode until 128)
// (each remaining length byte can encode until 128) do {
do fixedHeaderSize++;
{ temp /= 128;
fixedHeaderSize++; } while (temp > 0);
temp = temp / 128;
} while (temp > 0); // allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// allocate buffer for message
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; // first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// first fixed header byte buffer[index++] = (MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBSCRIBE_FLAG_BITS; // [v.3.1.1]
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) } else {
buffer[index++] = (MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBSCRIBE_FLAG_BITS; // [v.3.1.1] buffer[index] = (Byte)((MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
else (this.QosLevel << QOS_LEVEL_OFFSET));
{ buffer[index] |= this.DupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00;
buffer[index] = (byte)((MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | index++;
(this.qosLevel << QOS_LEVEL_OFFSET)); }
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00;
index++; // encode remaining length
} index = this.EncodeRemainingLength(remainingLength, buffer, index);
// encode remaining length // check message identifier assigned (SUBSCRIBE uses QoS Level 1, so message id is mandatory)
index = this.encodeRemainingLength(remainingLength, buffer, index); if (this.MessageId == 0) {
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
// check message identifier assigned (SUBSCRIBE uses QoS Level 1, so message id is mandatory) }
if (this.messageId == 0)
throw new MqttClientException(MqttClientErrorCode.WrongMessageId); buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)((messageId >> 8) & 0x00FF); // MSB buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
buffer[index++] = (byte)(messageId & 0x00FF); // LSB
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
topicIdx = 0; // topic name
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++) buffer[index++] = (Byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
{ buffer[index++] = (Byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
// topic name Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB index += topicsUtf8[topicIdx].Length;
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length); // requested QoS
index += topicsUtf8[topicIdx].Length; buffer[index++] = this.QoSLevels[topicIdx];
}
// requested QoS
buffer[index++] = this.qosLevels[topicIdx]; return buffer;
} }
return buffer; public override String ToString() =>
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"SUBSCRIBE", "SUBSCRIBE",
new object[] { "messageId", "topics", "qosLevels" }, new Object[] { "messageId", "topics", "qosLevels" },
new object[] { this.messageId, this.topics, this.qosLevels }); new Object[] { this.MessageId, this.Topics, this.QoSLevels });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,68 +14,48 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Event Args class for subscribe request on topics
/// </summary>
public class MqttMsgSubscribeEventArgs : EventArgs {
#region Properties...
/// <summary> /// <summary>
/// Event Args class for subscribe request on topics /// Message identifier
/// </summary> /// </summary>
public class MqttMsgSubscribeEventArgs : EventArgs public UInt16 MessageId { get; internal set; }
{
#region Properties... /// <summary>
/// Topics requested to subscribe
/// <summary> /// </summary>
/// Message identifier public String[] Topics { get; internal set; }
/// </summary>
public ushort MessageId /// <summary>
{ /// List of QOS Levels requested
get { return this.messageId; } /// </summary>
internal set { this.messageId = value; } public Byte[] QoSLevels { get; internal set; }
}
#endregion
/// <summary>
/// Topics requested to subscribe // message identifier
/// </summary>
public string[] Topics /// <summary>
{ /// Constructor
get { return this.topics; } /// </summary>
internal set { this.topics = value; } /// <param name="messageId">Message identifier for subscribe topics request</param>
} /// <param name="topics">Topics requested to subscribe</param>
/// <param name="qosLevels">List of QOS Levels requested</param>
/// <summary> public MqttMsgSubscribeEventArgs(UInt16 messageId, String[] topics, Byte[] qosLevels) {
/// List of QOS Levels requested this.MessageId = messageId;
/// </summary> this.Topics = topics;
public byte[] QoSLevels this.QoSLevels = qosLevels;
{ }
get { return this.qosLevels; } }
internal set { this.qosLevels = value; }
}
#endregion
// message identifier
ushort messageId;
// topics requested to subscribe
string[] topics;
// QoS levels requested
byte[] qosLevels;
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for subscribe topics request</param>
/// <param name="topics">Topics requested to subscribe</param>
/// <param name="qosLevels">List of QOS Levels requested</param>
public MqttMsgSubscribeEventArgs(ushort messageId, string[] topics, byte[] qosLevels)
{
this.messageId = messageId;
this.topics = topics;
this.qosLevels = qosLevels;
}
}
} }

View File

@ -14,55 +14,41 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Event Args class for subscribed topics
/// </summary>
public class MqttMsgSubscribedEventArgs : EventArgs {
#region Properties...
/// <summary> /// <summary>
/// Event Args class for subscribed topics /// Message identifier
/// </summary> /// </summary>
public class MqttMsgSubscribedEventArgs : EventArgs public UInt16 MessageId { get; internal set; }
{
#region Properties... /// <summary>
/// List of granted QOS Levels
/// <summary> /// </summary>
/// Message identifier public Byte[] GrantedQoSLevels { get; internal set; }
/// </summary>
public ushort MessageId #endregion
{
get { return this.messageId; } // message identifier
internal set { this.messageId = value; }
} /// <summary>
/// Constructor
/// <summary> /// </summary>
/// List of granted QOS Levels /// <param name="messageId">Message identifier for subscribed topics</param>
/// </summary> /// <param name="grantedQosLevels">List of granted QOS Levels</param>
public byte[] GrantedQoSLevels public MqttMsgSubscribedEventArgs(UInt16 messageId, Byte[] grantedQosLevels) {
{ this.MessageId = messageId;
get { return this.grantedQosLevels; } this.GrantedQoSLevels = grantedQosLevels;
internal set { this.grantedQosLevels = value; } }
} }
#endregion
// message identifier
ushort messageId;
// granted QOS levels
byte[] grantedQosLevels;
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for subscribed topics</param>
/// <param name="grantedQosLevels">List of granted QOS Levels</param>
public MqttMsgSubscribedEventArgs(ushort messageId, byte[] grantedQosLevels)
{
this.messageId = messageId;
this.grantedQosLevels = grantedQosLevels;
}
}
} }

View File

@ -17,110 +17,99 @@ Contributors:
using System; using System;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for UNSUBACK message from broker to client
/// </summary>
public class MqttMsgUnsuback : MqttMsgBase {
/// <summary> /// <summary>
/// Class for UNSUBACK message from broker to client /// Constructor
/// </summary> /// </summary>
public class MqttMsgUnsuback : MqttMsgBase public MqttMsgUnsuback() => this.Type = MQTT_MSG_UNSUBACK_TYPE;
{
/// <summary> /// <summary>
/// Constructor /// Parse bytes for a UNSUBACK message
/// </summary> /// </summary>
public MqttMsgUnsuback() /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
{ /// <param name="protocolVersion">Protocol Version</param>
this.type = MQTT_MSG_UNSUBACK_TYPE; /// <param name="channel">Channel connected to the broker</param>
} /// <returns>UNSUBACK message instance</returns>
public static MqttMsgUnsuback Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
/// <summary> Byte[] buffer;
/// Parse bytes for a UNSUBACK message Int32 index = 0;
/// </summary> MqttMsgUnsuback msg = new MqttMsgUnsuback();
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param> if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
/// <param name="channel">Channel connected to the broker</param> // [v3.1.1] check flag bits
/// <returns>UNSUBACK message instance</returns> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBACK_FLAG_BITS) {
public static MqttMsgUnsuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
{ }
byte[] buffer; }
int index = 0;
MqttMsgUnsuback msg = new MqttMsgUnsuback(); // get remaining length and allocate buffer
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) buffer = new Byte[remainingLength];
{
// [v3.1.1] check flag bits // read bytes from socket...
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBACK_FLAG_BITS) _ = channel.Receive(buffer);
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
} // message id
msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
// get remaining length and allocate buffer msg.MessageId |= buffer[index++];
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength]; return msg;
}
// read bytes from socket...
channel.Receive(buffer); public override Byte[] GetBytes(Byte protocolVersion) {
Int32 varHeaderSize = 0;
// message id Int32 payloadSize = 0;
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00); Int32 remainingLength = 0;
msg.messageId |= (buffer[index++]); Byte[] buffer;
Int32 index = 0;
return msg;
} // message identifier
varHeaderSize += MESSAGE_ID_SIZE;
public override byte[] GetBytes(byte protocolVersion)
{ remainingLength += varHeaderSize + payloadSize;
int fixedHeaderSize = 0;
int varHeaderSize = 0; // first byte of fixed header
int payloadSize = 0; Int32 fixedHeaderSize = 1;
int remainingLength = 0;
byte[] buffer; Int32 temp = remainingLength;
int index = 0; // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
// message identifier do {
varHeaderSize += MESSAGE_ID_SIZE; fixedHeaderSize++;
temp /= 128;
remainingLength += (varHeaderSize + payloadSize); } while (temp > 0);
// first byte of fixed header // allocate buffer for message
fixedHeaderSize = 1; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
int temp = remainingLength; // first fixed header byte
// increase fixed header size based on remaining length buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
// (each remaining length byte can encode until 128) ? (Byte)((MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBACK_FLAG_BITS)
do : (Byte)(MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET);
{
fixedHeaderSize++; // encode remaining length
temp = temp / 128; index = this.EncodeRemainingLength(remainingLength, buffer, index);
} while (temp > 0);
// message id
// allocate buffer for message buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
// first fixed header byte return buffer;
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) }
buffer[index++] = (MQTT_MSG_UNSUBACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBACK_FLAG_BITS; // [v.3.1.1]
else public override String ToString() =>
buffer[index++] = (byte)(MQTT_MSG_UNSUBACK_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
return buffer;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"UNSUBACK", "UNSUBACK",
new object[] { "messageId" }, new Object[] { "messageId" },
new object[] { this.messageId }); new Object[] { this.MessageId });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -16,224 +16,205 @@ Contributors:
using System; using System;
// if NOT .Net Micro Framework // if NOT .Net Micro Framework
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System.Collections.Generic; using System.Collections.Generic;
#endif #endif
using System.Collections; using System.Collections;
using System.Text; using System.Text;
using uPLibrary.Networking.M2Mqtt.Exceptions; using uPLibrary.Networking.M2Mqtt.Exceptions;
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Class for UNSUBSCRIBE message from client to broker
/// </summary>
public class MqttMsgUnsubscribe : MqttMsgBase {
#region Properties...
/// <summary> /// <summary>
/// Class for UNSUBSCRIBE message from client to broker /// List of topics to unsubscribe
/// </summary> /// </summary>
public class MqttMsgUnsubscribe : MqttMsgBase public String[] Topics { get; set; }
{
#region Properties... #endregion
/// <summary> // topics to unsubscribe
/// List of topics to unsubscribe
/// </summary> /// <summary>
public string[] Topics /// Constructor
{ /// </summary>
get { return this.topics; } public MqttMsgUnsubscribe() => this.Type = MQTT_MSG_UNSUBSCRIBE_TYPE;
set { this.topics = value; }
} /// <summary>
/// Constructor
#endregion /// </summary>
/// <param name="topics">List of topics to unsubscribe</param>
// topics to unsubscribe public MqttMsgUnsubscribe(String[] topics) {
string[] topics; this.Type = MQTT_MSG_UNSUBSCRIBE_TYPE;
/// <summary> this.Topics = topics;
/// Constructor
/// </summary> // UNSUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
public MqttMsgUnsubscribe() this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
{ }
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE;
} /// <summary>
/// Parse bytes for a UNSUBSCRIBE message
/// <summary> /// </summary>
/// Constructor /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// </summary> /// <param name="protocolVersion">Protocol Version</param>
/// <param name="topics">List of topics to unsubscribe</param> /// <param name="channel">Channel connected to the broker</param>
public MqttMsgUnsubscribe(string[] topics) /// <returns>UNSUBSCRIBE message instance</returns>
{ public static MqttMsgUnsubscribe Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE; Byte[] buffer;
Int32 index = 0;
this.topics = topics; Byte[] topicUtf8;
Int32 topicUtf8Length;
// UNSUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1) MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe();
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE;
} if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] check flag bits
/// <summary> if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS) {
/// Parse bytes for a UNSUBSCRIBE message throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
/// </summary> }
/// <param name="fixedHeaderFirstByte">First fixed header byte</param> }
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param> // get remaining length and allocate buffer
/// <returns>UNSUBSCRIBE message instance</returns> Int32 remainingLength = DecodeRemainingLength(channel);
public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) buffer = new Byte[remainingLength];
{
byte[] buffer; // read bytes from socket...
int index = 0; Int32 received = channel.Receive(buffer);
byte[] topicUtf8;
int topicUtf8Length; if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1) {
MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe(); // only 3.1.0
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) // read QoS level from fixed header
{ msg.QosLevel = (Byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// [v3.1.1] check flag bits // read DUP flag from fixed header
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS) msg.DupFlag = (fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET == 0x01;
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits); // retain flag not used
} msg.Retain = false;
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel); // message id
buffer = new byte[remainingLength]; msg.MessageId = (UInt16)((buffer[index++] << 8) & 0xFF00);
msg.MessageId |= buffer[index++];
// read bytes from socket...
int received = channel.Receive(buffer); // payload contains topics
// NOTE : before, I don't know how many topics will be in the payload (so use List)
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
{ // if .Net Micro Framework
// only 3.1.0 #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
// read QoS level from fixed header
msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
// read DUP flag from fixed header
msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
// retain flag not used
msg.retain = false;
}
// message id
msg.messageId = (ushort)((buffer[index++] << 8) & 0xFF00);
msg.messageId |= (buffer[index++]);
// payload contains topics
// NOTE : before, I don't know how many topics will be in the payload (so use List)
// if .Net Micro Framework
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
IList tmpTopics = new ArrayList(); IList tmpTopics = new ArrayList();
// else other frameworks (.Net, .Net Compact, Mono, Windows Phone) // else other frameworks (.Net, .Net Compact, Mono, Windows Phone)
#else #else
IList<String> tmpTopics = new List<String>(); IList<String> tmpTopics = new List<String>();
#endif #endif
do do {
{ // topic name
// topic name topicUtf8Length = (buffer[index++] << 8) & 0xFF00;
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00); topicUtf8Length |= buffer[index++];
topicUtf8Length |= buffer[index++]; topicUtf8 = new Byte[topicUtf8Length];
topicUtf8 = new byte[topicUtf8Length]; Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); index += topicUtf8Length;
index += topicUtf8Length; tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8))); } while (index < remainingLength);
} while (index < remainingLength);
// copy from list to array
// copy from list to array msg.Topics = new String[tmpTopics.Count];
msg.topics = new string[tmpTopics.Count]; for (Int32 i = 0; i < tmpTopics.Count; i++) {
for (int i = 0; i < tmpTopics.Count; i++) msg.Topics[i] = (String)tmpTopics[i];
{ }
msg.topics[i] = (string)tmpTopics[i];
} return msg;
}
return msg;
} public override Byte[] GetBytes(Byte protocolVersion) {
Int32 varHeaderSize = 0;
public override byte[] GetBytes(byte protocolVersion) Int32 payloadSize = 0;
{ Int32 remainingLength = 0;
int fixedHeaderSize = 0; Byte[] buffer;
int varHeaderSize = 0; Int32 index = 0;
int payloadSize = 0;
int remainingLength = 0; // topics list empty
byte[] buffer; if (this.Topics == null || this.Topics.Length == 0) {
int index = 0; throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
}
// topics list empty
if ((this.topics == null) || (this.topics.Length == 0)) // message identifier
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty); varHeaderSize += MESSAGE_ID_SIZE;
Byte[][] topicsUtf8 = new Byte[this.Topics.Length][];
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
Int32 topicIdx;
int topicIdx = 0; for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
byte[][] topicsUtf8 = new byte[this.topics.Length][]; // check topic length
if (this.Topics[topicIdx].Length < MIN_TOPIC_LENGTH || this.Topics[topicIdx].Length > MAX_TOPIC_LENGTH) {
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++) throw new MqttClientException(MqttClientErrorCode.TopicLength);
{ }
// check topic length
if ((this.topics[topicIdx].Length < MIN_TOPIC_LENGTH) || (this.topics[topicIdx].Length > MAX_TOPIC_LENGTH)) topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.Topics[topicIdx]);
throw new MqttClientException(MqttClientErrorCode.TopicLength); payloadSize += 2; // topic size (MSB, LSB)
payloadSize += topicsUtf8[topicIdx].Length;
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.topics[topicIdx]); }
payloadSize += 2; // topic size (MSB, LSB)
payloadSize += topicsUtf8[topicIdx].Length; remainingLength += varHeaderSize + payloadSize;
}
// first byte of fixed header
remainingLength += (varHeaderSize + payloadSize); Int32 fixedHeaderSize = 1;
// first byte of fixed header Int32 temp = remainingLength;
fixedHeaderSize = 1; // increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
int temp = remainingLength; do {
// increase fixed header size based on remaining length fixedHeaderSize++;
// (each remaining length byte can encode until 128) temp /= 128;
do } while (temp > 0);
{
fixedHeaderSize++; // allocate buffer for message
temp = temp / 128; buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
} while (temp > 0);
// first fixed header byte
// allocate buffer for message if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
buffer = new byte[fixedHeaderSize + varHeaderSize + payloadSize]; buffer[index++] = (MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBSCRIBE_FLAG_BITS; // [v.3.1.1]
} else {
// first fixed header byte buffer[index] = (Byte)((MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) (this.QosLevel << QOS_LEVEL_OFFSET));
buffer[index++] = (MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBSCRIBE_FLAG_BITS; // [v.3.1.1] buffer[index] |= this.DupFlag ? (Byte)(1 << DUP_FLAG_OFFSET) : (Byte)0x00;
else index++;
{ }
buffer[index] = (byte)((MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
(this.qosLevel << QOS_LEVEL_OFFSET)); // encode remaining length
buffer[index] |= this.dupFlag ? (byte)(1 << DUP_FLAG_OFFSET) : (byte)0x00; index = this.EncodeRemainingLength(remainingLength, buffer, index);
index++;
} // check message identifier assigned
if (this.MessageId == 0) {
// encode remaining length throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
index = this.encodeRemainingLength(remainingLength, buffer, index); }
// check message identifier assigned buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
if (this.messageId == 0) buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
buffer[index++] = (byte)((messageId >> 8) & 0x00FF); // MSB for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
buffer[index++] = (byte)(messageId & 0x00FF); // LSB // topic name
buffer[index++] = (Byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
topicIdx = 0; buffer[index++] = (Byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++) Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
{ index += topicsUtf8[topicIdx].Length;
// topic name }
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB return buffer;
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length); }
index += topicsUtf8[topicIdx].Length;
} public override String ToString() =>
return buffer;
}
public override string ToString()
{
#if TRACE #if TRACE
return this.GetTraceString( this.GetTraceString(
"UNSUBSCRIBE", "UNSUBSCRIBE",
new object[] { "messageId", "topics" }, new Object[] { "messageId", "topics" },
new object[] { this.messageId, this.topics }); new Object[] { this.MessageId, this.Topics });
#else #else
return base.ToString(); base.ToString();
#endif #endif
}
} }
} }

View File

@ -14,55 +14,41 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Event Args class for unsubscribe request on topics
/// </summary>
public class MqttMsgUnsubscribeEventArgs : EventArgs {
#region Properties...
/// <summary> /// <summary>
/// Event Args class for unsubscribe request on topics /// Message identifier
/// </summary> /// </summary>
public class MqttMsgUnsubscribeEventArgs : EventArgs public UInt16 MessageId { get; internal set; }
{
#region Properties... /// <summary>
/// Topics requested to subscribe
/// <summary> /// </summary>
/// Message identifier public String[] Topics { get; internal set; }
/// </summary>
public ushort MessageId #endregion
{
get { return this.messageId; } // message identifier
internal set { this.messageId = value; }
} /// <summary>
/// Constructor
/// <summary> /// </summary>
/// Topics requested to subscribe /// <param name="messageId">Message identifier for subscribed topics</param>
/// </summary> /// <param name="topics">Topics requested to subscribe</param>
public string[] Topics public MqttMsgUnsubscribeEventArgs(UInt16 messageId, String[] topics) {
{ this.MessageId = messageId;
get { return this.topics; } this.Topics = topics;
internal set { this.topics = value; } }
} }
#endregion
// message identifier
ushort messageId;
// topics requested to unsubscribe
string[] topics;
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for subscribed topics</param>
/// <param name="topics">Topics requested to subscribe</param>
public MqttMsgUnsubscribeEventArgs(ushort messageId, string[] topics)
{
this.messageId = messageId;
this.topics = topics;
}
}
} }

View File

@ -14,42 +14,32 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System; using System;
#else #else
using Microsoft.SPOT; using Microsoft.SPOT;
#endif #endif
namespace uPLibrary.Networking.M2Mqtt.Messages namespace uPLibrary.Networking.M2Mqtt.Messages {
{ /// <summary>
/// Event Args class for unsubscribed topic
/// </summary>
public class MqttMsgUnsubscribedEventArgs : EventArgs {
#region Properties...
/// <summary> /// <summary>
/// Event Args class for unsubscribed topic /// Message identifier
/// </summary> /// </summary>
public class MqttMsgUnsubscribedEventArgs : EventArgs public UInt16 MessageId { get; internal set; }
{
#region Properties... #endregion
/// <summary> // message identifier
/// Message identifier
/// </summary> /// <summary>
public ushort MessageId /// Constructor
{ /// </summary>
get { return this.messageId; } /// <param name="messageId">Message identifier for unsubscribed topic</param>
internal set { this.messageId = value; } public MqttMsgUnsubscribedEventArgs(UInt16 messageId) => this.MessageId = messageId;
} }
#endregion
// message identifier
ushort messageId;
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for unsubscribed topic</param>
public MqttMsgUnsubscribedEventArgs(ushort messageId)
{
this.messageId = messageId;
}
}
} }

File diff suppressed because it is too large Load Diff

View File

@ -14,17 +14,15 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt {
{ /// <summary>
/// <summary> /// Supported SSL/TLS protocol versions
/// Supported SSL/TLS protocol versions /// </summary>
/// </summary> public enum MqttSslProtocols {
public enum MqttSslProtocols None,
{ SSLv3,
None, TLSv1_0,
SSLv3, TLSv1_1,
TLSv1_0, TLSv1_2
TLSv1_1, }
TLSv1_2
}
} }

View File

@ -14,91 +14,90 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
namespace uPLibrary.Networking.M2Mqtt using System;
{
namespace uPLibrary.Networking.M2Mqtt {
/// <summary>
/// Settings class for the MQTT broker
/// </summary>
public class MqttSettings {
// default port for MQTT protocol
public const Int32 MQTT_BROKER_DEFAULT_PORT = 1883;
public const Int32 MQTT_BROKER_DEFAULT_SSL_PORT = 8883;
// default timeout on receiving from client
public const Int32 MQTT_DEFAULT_TIMEOUT = 30000;
// max publish, subscribe and unsubscribe retry for QoS Level 1 or 2
public const Int32 MQTT_ATTEMPTS_RETRY = 3;
// delay for retry publish, subscribe and unsubscribe for QoS Level 1 or 2
public const Int32 MQTT_DELAY_RETRY = 10000;
// broker need to receive the first message (CONNECT)
// within a reasonable amount of time after TCP/IP connection
public const Int32 MQTT_CONNECT_TIMEOUT = 30000;
// default inflight queue size
public const Int32 MQTT_MAX_INFLIGHT_QUEUE_SIZE = Int32.MaxValue;
/// <summary> /// <summary>
/// Settings class for the MQTT broker /// Listening connection port
/// </summary> /// </summary>
public class MqttSettings public Int32 Port { get; internal set; }
{
// default port for MQTT protocol /// <summary>
public const int MQTT_BROKER_DEFAULT_PORT = 1883; /// Listening connection SSL port
public const int MQTT_BROKER_DEFAULT_SSL_PORT = 8883; /// </summary>
// default timeout on receiving from client public Int32 SslPort { get; internal set; }
public const int MQTT_DEFAULT_TIMEOUT = 30000;
// max publish, subscribe and unsubscribe retry for QoS Level 1 or 2 /// <summary>
public const int MQTT_ATTEMPTS_RETRY = 3; /// Timeout on client connection (before receiving CONNECT message)
// delay for retry publish, subscribe and unsubscribe for QoS Level 1 or 2 /// </summary>
public const int MQTT_DELAY_RETRY = 10000; public Int32 TimeoutOnConnection { get; internal set; }
// broker need to receive the first message (CONNECT)
// within a reasonable amount of time after TCP/IP connection /// <summary>
public const int MQTT_CONNECT_TIMEOUT = 30000; /// Timeout on receiving
// default inflight queue size /// </summary>
public const int MQTT_MAX_INFLIGHT_QUEUE_SIZE = int.MaxValue; public Int32 TimeoutOnReceiving { get; internal set; }
/// <summary> /// <summary>
/// Listening connection port /// Attempts on retry
/// </summary> /// </summary>
public int Port { get; internal set; } public Int32 AttemptsOnRetry { get; internal set; }
/// <summary> /// <summary>
/// Listening connection SSL port /// Delay on retry
/// </summary> /// </summary>
public int SslPort { get; internal set; } public Int32 DelayOnRetry { get; internal set; }
/// <summary> /// <summary>
/// Timeout on client connection (before receiving CONNECT message) /// Inflight queue size
/// </summary> /// </summary>
public int TimeoutOnConnection { get; internal set; } public Int32 InflightQueueSize { get; set; }
/// <summary> /// <summary>
/// Timeout on receiving /// Singleton instance of settings
/// </summary> /// </summary>
public int TimeoutOnReceiving { get; internal set; } public static MqttSettings Instance {
get {
/// <summary> if (instance == null) {
/// Attempts on retry instance = new MqttSettings();
/// </summary> }
public int AttemptsOnRetry { get; internal set; }
return instance;
/// <summary> }
/// Delay on retry }
/// </summary>
public int DelayOnRetry { get; internal set; } // singleton instance
private static MqttSettings instance;
/// <summary>
/// Inflight queue size /// <summary>
/// </summary> /// Constructor
public int InflightQueueSize { get; set; } /// </summary>
private MqttSettings() {
/// <summary> this.Port = MQTT_BROKER_DEFAULT_PORT;
/// Singleton instance of settings this.SslPort = MQTT_BROKER_DEFAULT_SSL_PORT;
/// </summary> this.TimeoutOnReceiving = MQTT_DEFAULT_TIMEOUT;
public static MqttSettings Instance this.AttemptsOnRetry = MQTT_ATTEMPTS_RETRY;
{ this.DelayOnRetry = MQTT_DELAY_RETRY;
get this.TimeoutOnConnection = MQTT_CONNECT_TIMEOUT;
{ this.InflightQueueSize = MQTT_MAX_INFLIGHT_QUEUE_SIZE;
if (instance == null) }
instance = new MqttSettings(); }
return instance;
}
}
// singleton instance
private static MqttSettings instance;
/// <summary>
/// Constructor
/// </summary>
private MqttSettings()
{
this.Port = MQTT_BROKER_DEFAULT_PORT;
this.SslPort = MQTT_BROKER_DEFAULT_SSL_PORT;
this.TimeoutOnReceiving = MQTT_DEFAULT_TIMEOUT;
this.AttemptsOnRetry = MQTT_ATTEMPTS_RETRY;
this.DelayOnRetry = MQTT_DELAY_RETRY;
this.TimeoutOnConnection = MQTT_CONNECT_TIMEOUT;
this.InflightQueueSize = MQTT_MAX_INFLIGHT_QUEUE_SIZE;
}
}
} }

View File

@ -14,23 +14,16 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using System.Threading; using System.Threading;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt {
{ /// <summary>
/// <summary> /// Support methods fos specific framework
/// Support methods fos specific framework /// </summary>
/// </summary> public class Fx {
public class Fx public static void StartThread(ThreadStart threadStart) => new Thread(threadStart).Start();
{
public static void StartThread(ThreadStart threadStart) public static void SleepThread(Int32 millisecondsTimeout) => Thread.Sleep(millisecondsTimeout);
{ }
new Thread(threadStart).Start();
}
public static void SleepThread(int millisecondsTimeout)
{
Thread.Sleep(millisecondsTimeout);
}
}
} }

View File

@ -15,13 +15,17 @@ Contributors:
*/ */
#if SSL #if SSL
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
using Microsoft.SPOT.Net.Security; using Microsoft.SPOT.Net.Security;
#else #else
using System.Net.Security;
using System.Security.Authentication; using System.Security.Authentication;
#if NETCOREAPP
using System.Net.Security;
#endif
#endif #endif
#endif #endif
using System.Net.Sockets; using System.Net.Sockets;
using System.Net; using System.Net;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
@ -29,90 +33,73 @@ using System;
//using System.Security.Authentication; //using System.Security.Authentication;
//using System.Net.Security; //using System.Net.Security;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt {
{ /// <summary>
/// <summary> /// Channel to communicate over the network
/// Channel to communicate over the network /// </summary>
/// </summary> public class MqttNetworkChannel : IMqttNetworkChannel {
public class MqttNetworkChannel : IMqttNetworkChannel
{
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
private readonly RemoteCertificateValidationCallback userCertificateValidationCallback; private readonly RemoteCertificateValidationCallback userCertificateValidationCallback;
private readonly LocalCertificateSelectionCallback userCertificateSelectionCallback; private readonly LocalCertificateSelectionCallback userCertificateSelectionCallback;
#endif #endif
// remote host information // remote host information
private string remoteHostName;
private IPAddress remoteIpAddress;
private int remotePort;
// socket for communication // socket for communication
private Socket socket; private Socket socket;
// using SSL // using SSL
private bool secure; private readonly Boolean secure;
// CA certificate (on client) // CA certificate (on client)
private X509Certificate caCert; private readonly X509Certificate caCert;
// Server certificate (on broker) // Server certificate (on broker)
private X509Certificate serverCert; private readonly X509Certificate serverCert;
// client certificate (on client) // client certificate (on client)
private X509Certificate clientCert; private readonly X509Certificate clientCert;
// SSL/TLS protocol version // SSL/TLS protocol version
private MqttSslProtocols sslProtocol; private readonly MqttSslProtocols sslProtocol;
/// <summary> /// <summary>
/// Remote host name /// Remote host name
/// </summary> /// </summary>
public string RemoteHostName { get { return this.remoteHostName; } } public String RemoteHostName { get; }
/// <summary> /// <summary>
/// Remote IP address /// Remote IP address
/// </summary> /// </summary>
public IPAddress RemoteIpAddress { get { return this.remoteIpAddress; } } public IPAddress RemoteIpAddress { get; }
/// <summary> /// <summary>
/// Remote port /// Remote port
/// </summary> /// </summary>
public int RemotePort { get { return this.remotePort; } } public Int32 RemotePort { get; }
#if SSL #if SSL
// SSL stream // SSL stream
private SslStream sslStream; private SslStream sslStream;
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) #if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
private NetworkStream netStream; private NetworkStream netStream;
#endif #endif
#endif #endif
/// <summary> /// <summary>
/// Data available on the channel /// Data available on the channel
/// </summary> /// </summary>
public bool DataAvailable
{
get
{
#if SSL #if SSL
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
if (secure) public Boolean DataAvailable => this.secure ? this.sslStream.DataAvailable : this.socket.Available > 0;
return this.sslStream.DataAvailable;
else
return (this.socket.Available > 0);
#else #else
if (secure) public Boolean DataAvailable => this.secure ? this.netStream.DataAvailable : this.socket.Available > 0;
return this.netStream.DataAvailable;
else
return (this.socket.Available > 0);
#endif #endif
#else #else
return (this.socket.Available > 0); public Boolean DataAvailable => this.socket.Available > 0;
#endif #endif
}
}
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="socket">Socket opened with the client</param> /// <param name="socket">Socket opened with the client</param>
public MqttNetworkChannel(Socket socket) public MqttNetworkChannel(Socket socket)
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
: this(socket, false, null, MqttSslProtocols.None, null, null) : this(socket, false, null, MqttSslProtocols.None, null, null)
#else #else
@ -120,212 +107,203 @@ namespace uPLibrary.Networking.M2Mqtt
#endif #endif
{ {
} }
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="socket">Socket opened with the client</param> /// <param name="socket">Socket opened with the client</param>
/// <param name="secure">Secure connection (SSL/TLS)</param> /// <param name="secure">Secure connection (SSL/TLS)</param>
/// <param name="serverCert">Server X509 certificate for secure connection</param> /// <param name="serverCert">Server X509 certificate for secure connection</param>
/// <param name="sslProtocol">SSL/TLS protocol version</param> /// <param name="sslProtocol">SSL/TLS protocol version</param>
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
/// <param name="userCertificateSelectionCallback">A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party</param> /// <param name="userCertificateSelectionCallback">A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party</param>
/// <param name="userCertificateValidationCallback">A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication</param> /// <param name="userCertificateValidationCallback">A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication</param>
public MqttNetworkChannel(Socket socket, bool secure, X509Certificate serverCert, MqttSslProtocols sslProtocol, public MqttNetworkChannel(Socket socket, Boolean secure, X509Certificate serverCert, MqttSslProtocols sslProtocol,
RemoteCertificateValidationCallback userCertificateValidationCallback, RemoteCertificateValidationCallback userCertificateValidationCallback,
LocalCertificateSelectionCallback userCertificateSelectionCallback) LocalCertificateSelectionCallback userCertificateSelectionCallback)
#else #else
public MqttNetworkChannel(Socket socket, bool secure, X509Certificate serverCert, MqttSslProtocols sslProtocol) public MqttNetworkChannel(Socket socket, bool secure, X509Certificate serverCert, MqttSslProtocols sslProtocol)
#endif #endif
{ {
this.socket = socket; this.socket = socket;
this.secure = secure; this.secure = secure;
this.serverCert = serverCert; this.serverCert = serverCert;
this.sslProtocol = sslProtocol; this.sslProtocol = sslProtocol;
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
this.userCertificateValidationCallback = userCertificateValidationCallback; this.userCertificateValidationCallback = userCertificateValidationCallback;
this.userCertificateSelectionCallback = userCertificateSelectionCallback; this.userCertificateSelectionCallback = userCertificateSelectionCallback;
#endif #endif
} }
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="remoteHostName">Remote Host name</param> /// <param name="remoteHostName">Remote Host name</param>
/// <param name="remotePort">Remote port</param> /// <param name="remotePort">Remote port</param>
public MqttNetworkChannel(string remoteHostName, int remotePort) public MqttNetworkChannel(String remoteHostName, Int32 remotePort)
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
: this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None, null, null) : this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None, null, null)
#else #else
: this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None) : this(remoteHostName, remotePort, false, null, null, MqttSslProtocols.None)
#endif #endif
{ {
} }
/// <summary> /// <summary>
/// Constructor /// Constructor
/// </summary> /// </summary>
/// <param name="remoteHostName">Remote Host name</param> /// <param name="remoteHostName">Remote Host name</param>
/// <param name="remotePort">Remote port</param> /// <param name="remotePort">Remote port</param>
/// <param name="secure">Using SSL</param> /// <param name="secure">Using SSL</param>
/// <param name="caCert">CA certificate</param> /// <param name="caCert">CA certificate</param>
/// <param name="clientCert">Client certificate</param> /// <param name="clientCert">Client certificate</param>
/// <param name="sslProtocol">SSL/TLS protocol version</param> /// <param name="sslProtocol">SSL/TLS protocol version</param>
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
/// <param name="userCertificateSelectionCallback">A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party</param> /// <param name="userCertificateSelectionCallback">A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party</param>
/// <param name="userCertificateValidationCallback">A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication</param> /// <param name="userCertificateValidationCallback">A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication</param>
public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol, public MqttNetworkChannel(String remoteHostName, Int32 remotePort, Boolean secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol,
RemoteCertificateValidationCallback userCertificateValidationCallback, RemoteCertificateValidationCallback userCertificateValidationCallback,
LocalCertificateSelectionCallback userCertificateSelectionCallback) LocalCertificateSelectionCallback userCertificateSelectionCallback)
#else #else
public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol) public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol)
#endif #endif
{ {
IPAddress remoteIpAddress = null; IPAddress remoteIpAddress = null;
try try {
{ // check if remoteHostName is a valid IP address and get it
// check if remoteHostName is a valid IP address and get it remoteIpAddress = IPAddress.Parse(remoteHostName);
remoteIpAddress = IPAddress.Parse(remoteHostName); } catch {
} }
catch
{
}
// in this case the parameter remoteHostName isn't a valid IP address // in this case the parameter remoteHostName isn't a valid IP address
if (remoteIpAddress == null) if (remoteIpAddress == null) {
{ IPHostEntry hostEntry = Dns.GetHostEntry(remoteHostName);
IPHostEntry hostEntry = Dns.GetHostEntry(remoteHostName); if (hostEntry != null && hostEntry.AddressList.Length > 0) {
if ((hostEntry != null) && (hostEntry.AddressList.Length > 0)) // check for the first address not null
{ // it seems that with .Net Micro Framework, the IPV6 addresses aren't supported and return "null"
// check for the first address not null Int32 i = 0;
// it seems that with .Net Micro Framework, the IPV6 addresses aren't supported and return "null" while (hostEntry.AddressList[i] == null) {
int i = 0; i++;
while (hostEntry.AddressList[i] == null) i++; }
remoteIpAddress = hostEntry.AddressList[i];
}
else
{
throw new Exception("No address found for the remote host name");
}
}
this.remoteHostName = remoteHostName; remoteIpAddress = hostEntry.AddressList[i];
this.remoteIpAddress = remoteIpAddress; } else {
this.remotePort = remotePort; throw new Exception("No address found for the remote host name");
this.secure = secure;
this.caCert = caCert;
this.clientCert = clientCert;
this.sslProtocol = sslProtocol;
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
this.userCertificateValidationCallback = userCertificateValidationCallback;
this.userCertificateSelectionCallback = userCertificateSelectionCallback;
#endif
} }
}
/// <summary> this.RemoteHostName = remoteHostName;
/// Connect to remote server this.RemoteIpAddress = remoteIpAddress;
/// </summary> this.RemotePort = remotePort;
public void Connect() this.secure = secure;
{ this.caCert = caCert;
this.socket = new Socket(IPAddressUtility.GetAddressFamily(this.remoteIpAddress), SocketType.Stream, ProtocolType.Tcp); this.clientCert = clientCert;
// try connection to the broker this.sslProtocol = sslProtocol;
this.socket.Connect(new IPEndPoint(this.remoteIpAddress, this.remotePort)); #if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK)
this.userCertificateValidationCallback = userCertificateValidationCallback;
this.userCertificateSelectionCallback = userCertificateSelectionCallback;
#endif
}
/// <summary>
/// Connect to remote server
/// </summary>
public void Connect() {
this.socket = new Socket(IPAddressUtility.GetAddressFamily(this.RemoteIpAddress), SocketType.Stream, ProtocolType.Tcp);
// try connection to the broker
this.socket.Connect(new IPEndPoint(this.RemoteIpAddress, this.RemotePort));
#if SSL #if SSL
// secure channel requested // secure channel requested
if (secure) if (this.secure) {
{ // create SSL stream
// create SSL stream #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
this.sslStream = new SslStream(this.socket); this.sslStream = new SslStream(this.socket);
#else #else
this.netStream = new NetworkStream(this.socket); this.netStream = new NetworkStream(this.socket);
this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback); this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback);
#endif #endif
// server authentication (SSL/TLS handshake) // server authentication (SSL/TLS handshake)
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) #if MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
this.sslStream.AuthenticateAsClient(this.remoteHostName, this.sslStream.AuthenticateAsClient(this.remoteHostName,
this.clientCert, this.clientCert,
new X509Certificate[] { this.caCert }, new X509Certificate[] { this.caCert },
SslVerification.CertificateRequired, SslVerification.CertificateRequired,
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol)); MqttSslUtility.ToSslPlatformEnum(this.sslProtocol));
#else #else
X509CertificateCollection clientCertificates = null; X509CertificateCollection clientCertificates = null;
// check if there is a client certificate to add to the collection, otherwise it's null (as empty) // check if there is a client certificate to add to the collection, otherwise it's null (as empty)
if (this.clientCert != null) if (this.clientCert != null) {
clientCertificates = new X509CertificateCollection(new X509Certificate[] { this.clientCert }); clientCertificates = new X509CertificateCollection(new X509Certificate[] { this.clientCert });
this.sslStream.AuthenticateAsClient(this.remoteHostName,
clientCertificates,
MqttSslUtility.ToSslPlatformEnum(this.sslProtocol),
false);
#endif
}
#endif
} }
/// <summary> this.sslStream.AuthenticateAsClient(this.RemoteHostName,
/// Send data on the network channel clientCertificates,
/// </summary> MqttSslUtility.ToSslPlatformEnum(this.sslProtocol),
/// <param name="buffer">Data buffer to send</param> false);
/// <returns>Number of byte sent</returns>
public int Send(byte[] buffer) #endif
{ }
#endif
}
/// <summary>
/// Send data on the network channel
/// </summary>
/// <param name="buffer">Data buffer to send</param>
/// <returns>Number of byte sent</returns>
public Int32 Send(Byte[] buffer) {
#if SSL #if SSL
if (this.secure) if (this.secure) {
{ this.sslStream.Write(buffer, 0, buffer.Length);
this.sslStream.Write(buffer, 0, buffer.Length); this.sslStream.Flush();
this.sslStream.Flush(); return buffer.Length;
return buffer.Length; } else {
} return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
else }
return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
#else #else
return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None); return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None);
#endif #endif
} }
/// <summary> /// <summary>
/// Receive data from the network /// Receive data from the network
/// </summary> /// </summary>
/// <param name="buffer">Data buffer for receiving data</param> /// <param name="buffer">Data buffer for receiving data</param>
/// <returns>Number of bytes received</returns> /// <returns>Number of bytes received</returns>
public int Receive(byte[] buffer) public Int32 Receive(Byte[] buffer) {
{
#if SSL #if SSL
if (this.secure) if (this.secure) {
{ // read all data needed (until fill buffer)
// read all data needed (until fill buffer) Int32 idx = 0, read = 0;
int idx = 0, read = 0; while (idx < buffer.Length) {
while (idx < buffer.Length) // fixed scenario with socket closed gracefully by peer/broker and
{ // Read return 0. Avoid infinite loop.
// fixed scenario with socket closed gracefully by peer/broker and read = this.sslStream.Read(buffer, idx, buffer.Length - idx);
// Read return 0. Avoid infinite loop. if (read == 0) {
read = this.sslStream.Read(buffer, idx, buffer.Length - idx); return 0;
if (read == 0) }
return 0;
idx += read; idx += read;
} }
return buffer.Length; return buffer.Length;
} } else {
else // read all data needed (until fill buffer)
{ Int32 idx = 0, read = 0;
// read all data needed (until fill buffer) while (idx < buffer.Length) {
int idx = 0, read = 0; // fixed scenario with socket closed gracefully by peer/broker and
while (idx < buffer.Length) // Read return 0. Avoid infinite loop.
{ read = this.socket.Receive(buffer, idx, buffer.Length - idx, SocketFlags.None);
// fixed scenario with socket closed gracefully by peer/broker and if (read == 0) {
// Read return 0. Avoid infinite loop. return 0;
read = this.socket.Receive(buffer, idx, buffer.Length - idx, SocketFlags.None); }
if (read == 0)
return 0; idx += read;
idx += read; }
} return buffer.Length;
return buffer.Length; }
}
#else #else
// read all data needed (until fill buffer) // read all data needed (until fill buffer)
int idx = 0, read = 0; int idx = 0, read = 0;
@ -340,118 +318,94 @@ namespace uPLibrary.Networking.M2Mqtt
} }
return buffer.Length; return buffer.Length;
#endif #endif
}
/// <summary>
/// Receive data from the network channel with a specified timeout
/// </summary>
/// <param name="buffer">Data buffer for receiving data</param>
/// <param name="timeout">Timeout on receiving (in milliseconds)</param>
/// <returns>Number of bytes received</returns>
public int Receive(byte[] buffer, int timeout)
{
// check data availability (timeout is in microseconds)
if (this.socket.Poll(timeout * 1000, SelectMode.SelectRead))
{
return this.Receive(buffer);
}
else
{
return 0;
}
}
/// <summary>
/// Close the network channel
/// </summary>
public void Close()
{
#if SSL
if (this.secure)
{
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
this.netStream.Close();
#endif
this.sslStream.Close();
}
this.socket.Close();
#else
this.socket.Close();
#endif
}
/// <summary>
/// Accept connection from a remote client
/// </summary>
public void Accept()
{
#if SSL
// secure channel requested
if (secure)
{
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
this.netStream = new NetworkStream(this.socket);
this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback);
this.sslStream.AuthenticateAsServer(this.serverCert, false, MqttSslUtility.ToSslPlatformEnum(this.sslProtocol), false);
#endif
}
return;
#else
return;
#endif
}
} }
/// <summary> /// <summary>
/// IPAddress Utility class /// Receive data from the network channel with a specified timeout
/// </summary> /// </summary>
public static class IPAddressUtility /// <param name="buffer">Data buffer for receiving data</param>
{ /// <param name="timeout">Timeout on receiving (in milliseconds)</param>
/// <summary> /// <returns>Number of bytes received</returns>
/// Return AddressFamily for the IP address public Int32 Receive(Byte[] buffer, Int32 timeout) =>
/// </summary> // check data availability (timeout is in microseconds)
/// <param name="ipAddress">IP address to check</param> this.socket.Poll(timeout * 1000, SelectMode.SelectRead) ? this.Receive(buffer) : 0;
/// <returns>Address family</returns>
public static AddressFamily GetAddressFamily(IPAddress ipAddress) /// <summary>
{ /// Close the network channel
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) /// </summary>
return ipAddress.AddressFamily; public void Close() {
#if SSL
if (this.secure) {
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
this.netStream.Close();
#endif
this.sslStream.Close();
}
this.socket.Close();
#else
this.socket.Close();
#endif
}
/// <summary>
/// Accept connection from a remote client
/// </summary>
public void Accept() {
#if SSL
// secure channel requested
if (this.secure) {
#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
this.netStream = new NetworkStream(this.socket);
this.sslStream = new SslStream(this.netStream, false, this.userCertificateValidationCallback, this.userCertificateSelectionCallback);
this.sslStream.AuthenticateAsServer(this.serverCert, false, MqttSslUtility.ToSslPlatformEnum(this.sslProtocol), false);
#endif
}
return;
#else
return;
#endif
}
}
/// <summary>
/// IPAddress Utility class
/// </summary>
public static class IPAddressUtility {
/// <summary>
/// Return AddressFamily for the IP address
/// </summary>
/// <param name="ipAddress">IP address to check</param>
/// <returns>Address family</returns>
public static AddressFamily GetAddressFamily(IPAddress ipAddress) =>
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
ipAddress.AddressFamily;
#else #else
return (ipAddress.ToString().IndexOf(':') != -1) ? return (ipAddress.ToString().IndexOf(':') != -1) ?
AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork; AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork;
#endif #endif
}
}
/// <summary> }
/// MQTT SSL utility class
/// </summary> /// <summary>
public static class MqttSslUtility /// MQTT SSL utility class
/// </summary>
public static class MqttSslUtility {
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3 && !COMPACT_FRAMEWORK
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol) => mqttSslProtocol switch
{ {
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3 && !COMPACT_FRAMEWORK) MqttSslProtocols.None => SslProtocols.None,
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol) //MqttSslProtocols.SSLv3 => SslProtocols.Ssl3,
{ MqttSslProtocols.TLSv1_0 => SslProtocols.Tls,
switch (mqttSslProtocol) MqttSslProtocols.TLSv1_1 => SslProtocols.Tls11,
{ MqttSslProtocols.TLSv1_2 => SslProtocols.Tls12,
case MqttSslProtocols.None: _ => throw new ArgumentException("SSL/TLS protocol version not supported"),
return SslProtocols.None; };
case MqttSslProtocols.SSLv3: #elif MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3
return SslProtocols.Ssl3; public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol)
case MqttSslProtocols.TLSv1_0:
return SslProtocols.Tls;
/*case MqttSslProtocols.TLSv1_1:
return SslProtocols.Tls11;
case MqttSslProtocols.TLSv1_2:
return SslProtocols.Tls12;*/
default:
throw new ArgumentException("SSL/TLS protocol version not supported");
}
}
#elif (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
public static SslProtocols ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol)
{ {
switch (mqttSslProtocol) switch (mqttSslProtocol)
{ {
@ -468,5 +422,5 @@ namespace uPLibrary.Networking.M2Mqtt
} }
} }
#endif #endif
} }
} }

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -41,4 +41,5 @@ using System.Runtime.InteropServices;
// to avoid compilation error (AssemblyFileVersionAttribute doesn't exist) under .Net CF 3.5 // to avoid compilation error (AssemblyFileVersionAttribute doesn't exist) under .Net CF 3.5
#if !WindowsCE #if !WindowsCE
[assembly: AssemblyFileVersion("4.3.0.0")] [assembly: AssemblyFileVersion("4.3.0.0")]
#endif
#endif #endif

View File

@ -14,20 +14,18 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
namespace uPLibrary.Networking.M2Mqtt.Session using System;
{
namespace uPLibrary.Networking.M2Mqtt.Session {
/// <summary>
/// MQTT Client Session
/// </summary>
public class MqttClientSession : MqttSession {
/// <summary> /// <summary>
/// MQTT Client Session /// Constructor
/// </summary> /// </summary>
public class MqttClientSession : MqttSession /// <param name="clientId">Client Id to create session</param>
{ public MqttClientSession(String clientId) : base(clientId) {
/// <summary> }
/// Constructor }
/// </summary>
/// <param name="clientId">Client Id to create session</param>
public MqttClientSession(string clientId)
: base(clientId)
{
}
}
} }

View File

@ -14,50 +14,46 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using System.Collections; using System.Collections;
namespace uPLibrary.Networking.M2Mqtt.Session namespace uPLibrary.Networking.M2Mqtt.Session {
{ /// <summary>
/// MQTT Session base class
/// </summary>
public abstract class MqttSession {
/// <summary> /// <summary>
/// MQTT Session base class /// Client Id
/// </summary> /// </summary>
public abstract class MqttSession public String ClientId { get; set; }
{
/// <summary> /// <summary>
/// Client Id /// Messages inflight during session
/// </summary> /// </summary>
public string ClientId { get; set; } public Hashtable InflightMessages { get; set; }
/// <summary> /// <summary>
/// Messages inflight during session /// Constructor
/// </summary> /// </summary>
public Hashtable InflightMessages { get; set; } public MqttSession()
: this(null) {
/// <summary> }
/// Constructor
/// </summary> /// <summary>
public MqttSession() /// Constructor
: this(null) /// </summary>
{ /// <param name="clientId">Client Id to create session</param>
} public MqttSession(String clientId) {
this.ClientId = clientId;
/// <summary> this.InflightMessages = new Hashtable();
/// Constructor }
/// </summary>
/// <param name="clientId">Client Id to create session</param> /// <summary>
public MqttSession(string clientId) /// Clean session
{ /// </summary>
this.ClientId = clientId; public virtual void Clear() {
this.InflightMessages = new Hashtable(); this.ClientId = null;
} this.InflightMessages.Clear();
}
/// <summary> }
/// Clean session }
/// </summary>
public virtual void Clear()
{
this.ClientId = null;
this.InflightMessages.Clear();
}
}
}

View File

@ -17,34 +17,31 @@ Contributors:
using System; using System;
using System.Collections; using System.Collections;
namespace uPLibrary.Networking.M2Mqtt.Utility namespace uPLibrary.Networking.M2Mqtt.Utility {
{ /// <summary>
/// Extension class for a Queue
/// </summary>
internal static class QueueExtension {
/// <summary> /// <summary>
/// Extension class for a Queue /// Predicate for searching inside a queue
/// </summary> /// </summary>
internal static class QueueExtension /// <param name="item">Item of the queue</param>
{ /// <returns>Result of predicate</returns>
/// <summary> internal delegate Boolean QueuePredicate(Object item);
/// Predicate for searching inside a queue
/// </summary> /// <summary>
/// <param name="item">Item of the queue</param> /// Get (without removing) an item from queue based on predicate
/// <returns>Result of predicate</returns> /// </summary>
internal delegate bool QueuePredicate(object item); /// <param name="queue">Queue in which to search</param>
/// <param name="predicate">Predicate to verify to get item</param>
/// <summary> /// <returns>Item matches the predicate</returns>
/// Get (without removing) an item from queue based on predicate internal static Object Get(Queue queue, QueuePredicate predicate) {
/// </summary> foreach (Object item in queue) {
/// <param name="queue">Queue in which to search</param> if (predicate(item)) {
/// <param name="predicate">Predicate to verify to get item</param> return item;
/// <returns>Item matches the predicate</returns> }
internal static object Get(Queue queue, QueuePredicate predicate) }
{ return null;
foreach (var item in queue) }
{ }
if (predicate(item))
return item;
}
return null;
}
}
} }

View File

@ -14,73 +14,57 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
using System;
using System.Diagnostics; using System.Diagnostics;
namespace uPLibrary.Networking.M2Mqtt.Utility namespace uPLibrary.Networking.M2Mqtt.Utility {
{ /// <summary>
/// <summary> /// Tracing levels
/// Tracing levels /// </summary>
/// </summary> public enum TraceLevel {
public enum TraceLevel Error = 0x01,
{ Warning = 0x02,
Error = 0x01, Information = 0x04,
Warning = 0x02, Verbose = 0x0F,
Information = 0x04, Frame = 0x10,
Verbose = 0x0F, Queuing = 0x20
Frame = 0x10, }
Queuing = 0x20
} // delegate for writing trace
public delegate void WriteTrace(String format, params Object[] args);
// delegate for writing trace
public delegate void WriteTrace(string format, params object[] args); /// <summary>
/// Tracing class
/// <summary> /// </summary>
/// Tracing class public static class Trace {
/// </summary> public static TraceLevel TraceLevel;
public static class Trace public static WriteTrace TraceListener;
{
public static TraceLevel TraceLevel; [Conditional("DEBUG")]
public static WriteTrace TraceListener; public static void Debug(String format, params Object[] args) => TraceListener?.Invoke(format, args);
[Conditional("DEBUG")] public static void WriteLine(TraceLevel level, String format) {
public static void Debug(string format, params object[] args) if ((level & TraceLevel) > 0) {
{ TraceListener.Invoke(format);
if (TraceListener != null) }
{ }
TraceListener(format, args);
} public static void WriteLine(TraceLevel level, String format, Object arg1) {
} if ( (level & TraceLevel) > 0) {
TraceListener.Invoke(format, arg1);
public static void WriteLine(TraceLevel level, string format) }
{ }
if (TraceListener != null && (level & TraceLevel) > 0)
{ public static void WriteLine(TraceLevel level, String format, Object arg1, Object arg2) {
TraceListener(format); if ((level & TraceLevel) > 0) {
} TraceListener.Invoke(format, arg1, arg2);
} }
}
public static void WriteLine(TraceLevel level, string format, object arg1)
{ public static void WriteLine(TraceLevel level, String format, Object arg1, Object arg2, Object arg3) {
if (TraceListener != null && (level & TraceLevel) > 0) if ((level & TraceLevel) > 0) {
{ TraceListener.Invoke(format, arg1, arg2, arg3);
TraceListener(format, arg1); }
} }
} }
public static void WriteLine(TraceLevel level, string format, object arg1, object arg2)
{
if (TraceListener != null && (level & TraceLevel) > 0)
{
TraceListener(format, arg1, arg2);
}
}
public static void WriteLine(TraceLevel level, string format, object arg1, object arg2, object arg3)
{
if (TraceListener != null && (level & TraceLevel) > 0)
{
TraceListener(format, arg1, arg2, arg3);
}
}
}
} }

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -33,4 +33,5 @@ namespace uPLibrary.Networking.M2Mqtt
public static void SleepThread(int millisecondsTimeout) { Task.Delay(millisecondsTimeout).RunSynchronously(); } public static void SleepThread(int millisecondsTimeout) { Task.Delay(millisecondsTimeout).RunSynchronously(); }
} }
} }
#endif

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System.Collections.Generic; using System.Collections.Generic;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt
@ -25,3 +25,4 @@ namespace uPLibrary.Networking.M2Mqtt
{ {
} }
} }
#endif

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@ -177,3 +177,4 @@ namespace uPLibrary.Networking.M2Mqtt
} }
} }
} }
#endif

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors: Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation Paolo Patierno - initial API and implementation and/or initial documentation
*/ */
#if !NETCOREAPP
using System.Collections.Generic; using System.Collections.Generic;
namespace uPLibrary.Networking.M2Mqtt namespace uPLibrary.Networking.M2Mqtt
@ -25,3 +25,4 @@ namespace uPLibrary.Networking.M2Mqtt
{ {
} }
} }
#endif

25
M2Mqtt_Core.sln Normal file
View File

@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29519.87
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "M2Mqtt", "M2Mqtt\M2Mqtt_Core.csproj", "{18F706D2-7610-428C-8324-8327F9D7BE90}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{18F706D2-7610-428C-8324-8327F9D7BE90}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{18F706D2-7610-428C-8324-8327F9D7BE90}.Debug|Any CPU.Build.0 = Debug|Any CPU
{18F706D2-7610-428C-8324-8327F9D7BE90}.Release|Any CPU.ActiveCfg = Release|Any CPU
{18F706D2-7610-428C-8324-8327F9D7BE90}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EBFDF320-2C59-4F89-8211-5B6EF9C310ED}
EndGlobalSection
EndGlobal