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

View File

@ -16,27 +16,23 @@ Contributors:
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>
/// Exception due to error communication with broker on socket
/// Default constructor
/// </summary>
public class MqttCommunicationException : Exception
{
/// <summary>
/// Default constructor
/// </summary>
public MqttCommunicationException()
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="e">Inner Exception</param>
public MqttCommunicationException(Exception e)
: base(String.Empty, e)
{
}
}
public MqttCommunicationException() {
}
/// <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;
namespace uPLibrary.Networking.M2Mqtt.Exceptions
{
/// <summary>
/// Connection to the broker exception
/// </summary>
public class MqttConnectionException : Exception
{
public MqttConnectionException(string message, Exception innerException)
: base(message, innerException)
{
}
}
namespace uPLibrary.Networking.M2Mqtt.Exceptions {
/// <summary>
/// Connection to the broker exception
/// </summary>
public class MqttConnectionException : Exception {
public MqttConnectionException(String message, Exception innerException)
: base(message, innerException) {
}
}
}

View File

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

View File

@ -15,55 +15,52 @@ Contributors:
*/
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>
/// Interface for channel under MQTT library
/// Data available on channel
/// </summary>
public interface IMqttNetworkChannel
{
/// <summary>
/// Data available on channel
/// </summary>
bool DataAvailable { get; }
/// <summary>
/// Receive data from the network channel
/// </summary>
/// <param name="buffer">Data buffer for receiving data</param>
/// <returns>Number of bytes received</returns>
int Receive(byte[] buffer);
/// <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>
int Receive(byte[] buffer, int timeout);
/// <summary>
/// Send data on the network channel to the broker
/// </summary>
/// <param name="buffer">Data buffer to send</param>
/// <returns>Number of byte sent</returns>
int Send(byte[] buffer);
/// <summary>
/// Close the network channel
/// </summary>
void Close();
/// <summary>
/// Connect to remote server
/// </summary>
void Connect();
/// <summary>
/// Accept client connection
/// </summary>
void Accept();
}
Boolean DataAvailable { get; }
/// <summary>
/// Receive data from the network channel
/// </summary>
/// <param name="buffer">Data buffer for receiving data</param>
/// <returns>Number of bytes received</returns>
Int32 Receive(Byte[] buffer);
/// <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>
Int32 Receive(Byte[] buffer, Int32 timeout);
/// <summary>
/// Send data on the network channel to the broker
/// </summary>
/// <param name="buffer">Data buffer to send</param>
/// <returns>Number of byte sent</returns>
Int32 Send(Byte[] buffer);
/// <summary>
/// Close the network channel
/// </summary>
void Close();
/// <summary>
/// Connect to remote server
/// </summary>
void Connect();
/// <summary>
/// Accept client connection
/// </summary>
void Accept();
}
}

View File

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

View File

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

View File

@ -14,40 +14,31 @@ Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
using System;
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>
/// Internal event for a published message
/// Message published (or failed due to retries)
/// </summary>
public class MsgPublishedInternalEvent : MsgInternalEvent
{
#region Properties...
/// <summary>
/// Message published (or failed due to retries)
/// </summary>
public bool IsPublished
{
get { return this.isPublished; }
internal set { this.isPublished = value; }
}
#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;
}
}
public Boolean IsPublished { get; internal set; }
#endregion
// published flag
/// <summary>
/// Constructor
/// </summary>
/// <param name="msg">Message published</param>
/// <param name="isPublished">Publish flag</param>
public MsgPublishedInternalEvent(MqttMsgBase msg, Boolean 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.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>
/// Base class for all MQTT messages
/// Message type
/// </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 ushort MAX_TOPIC_LENGTH = 65535;
internal const ushort MIN_TOPIC_LENGTH = 1;
internal const byte MESSAGE_ID_SIZE = 2;
#endregion
#region Properties...
/// <summary>
/// Message type
/// </summary>
public byte Type
{
get { return this.type; }
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;
}
public Byte Type { get; set; }
/// <summary>
/// Duplicate message flag
/// </summary>
public Boolean DupFlag { get; set; }
/// <summary>
/// Quality of Service level
/// </summary>
public Byte QosLevel { get; set; }
/// <summary>
/// Retain message flag
/// </summary>
public Boolean Retain { get; set; }
/// <summary>
/// Message identifier for the message
/// </summary>
public UInt16 MessageId { get; set; }
#endregion
// message type
// duplicate delivery
// quality of service level
// retain flag
// message identifier
/// <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 Int32 EncodeRemainingLength(Int32 remainingLength, Byte[] buffer, Int32 index) {
do {
Int32 digit = remainingLength % 128;
remainingLength /= 128;
if (remainingLength > 0) {
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 Int32 DecodeRemainingLength(IMqttNetworkChannel channel) {
Int32 multiplier = 1;
Int32 value = 0;
Byte[] nextByte = new Byte[1];
Int32 digit;
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
/// <summary>
/// Returns a string representation of the message for tracing
/// </summary>
/// <param name="name">Message name</param>
/// <param name="fieldNames">Message fields name</param>
/// <param name="fieldValues">Message fields value</param>
/// <returns>String representation of the message</returns>
protected string GetTraceString(string name, object[] fieldNames, object[] fieldValues)
{
StringBuilder sb = new StringBuilder();
sb.Append(name);
if ((fieldNames != null) && (fieldValues != null))
{
sb.Append("(");
bool addComma = false;
for (int i = 0; i < fieldValues.Length; i++)
{
if (fieldValues[i] != null)
{
if (addComma)
{
sb.Append(",");
}
sb.Append(fieldNames[i]);
sb.Append(":");
sb.Append(GetStringObject(fieldValues[i]));
addComma = true;
}
}
sb.Append(")");
}
return sb.ToString();
}
object GetStringObject(object value)
{
byte[] binary = value as byte[];
if (binary != null)
{
string hexChars = "0123456789ABCDEF";
StringBuilder sb = new StringBuilder(binary.Length * 2);
for (int i = 0; i < binary.Length; ++i)
{
sb.Append(hexChars[binary[i] >> 4]);
sb.Append(hexChars[binary[i] & 0x0F]);
}
return sb.ToString();
}
object[] list = value as object[];
if (list != null)
{
StringBuilder sb = new StringBuilder();
sb.Append('[');
for (int i = 0; i < list.Length; ++i)
{
if (i > 0) sb.Append(',');
sb.Append(list[i]);
}
sb.Append(']');
return sb.ToString();
}
return value;
}
/// <summary>
/// Returns a string representation of the message for tracing
/// </summary>
/// <param name="name">Message name</param>
/// <param name="fieldNames">Message fields name</param>
/// <param name="fieldValues">Message fields value</param>
/// <returns>String representation of the message</returns>
protected String GetTraceString(String name, Object[] fieldNames, Object[] fieldValues) {
StringBuilder sb = new StringBuilder();
_ = sb.Append(name);
if (fieldNames != null && fieldValues != null) {
_ = sb.Append("(");
Boolean addComma = false;
for (Int32 i = 0; i < fieldValues.Length; i++) {
if (fieldValues[i] != null) {
if (addComma) {
_ = sb.Append(",");
}
_ = sb.Append(fieldNames[i]);
_ = sb.Append(":");
_ = sb.Append(this.GetStringObject(fieldValues[i]));
addComma = true;
}
}
_ = sb.Append(")");
}
return sb.ToString();
}
Object GetStringObject(Object value) {
if (value is Byte[] binary) {
String hexChars = "0123456789ABCDEF";
StringBuilder sb = new StringBuilder(binary.Length * 2);
for (Int32 i = 0; i < binary.Length; ++i) {
_ = sb.Append(hexChars[binary[i] >> 4]);
_ = sb.Append(hexChars[binary[i] & 0x0F]);
}
return sb.ToString();
}
if (value is Object[] list) {
StringBuilder sb = new StringBuilder();
_ = sb.Append('[');
for (Int32 i = 0; i < list.Length; ++i) {
if (i > 0) {
_ = sb.Append(',');
}
_ = sb.Append(list[i]);
}
_ = sb.Append(']');
return sb.ToString();
}
return value;
}
#endif
}
}
}

View File

@ -17,175 +17,153 @@ Contributors:
using System;
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>
/// Class for CONNACK message from broker to client
/// Session present flag
/// </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>
/// Session present flag
/// </summary>
public bool SessionPresent
{
get { return this.sessionPresent; }
set { this.sessionPresent = value; }
}
/// <summary>
/// Return Code
/// </summary>
public byte ReturnCode
{
get { return this.returnCode; }
set { this.returnCode = value; }
}
#endregion
// [v3.1.1] session present flag
private bool sessionPresent;
// return code for CONNACK message
private byte returnCode;
/// <summary>
/// Constructor
/// </summary>
public MqttMsgConnack()
{
this.type = MQTT_MSG_CONNACK_TYPE;
}
/// <summary>
/// Parse bytes for a CONNACK message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>CONNACK message instance</returns>
public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
MqttMsgConnack msg = new MqttMsgConnack();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// read bytes from socket...
channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] ... set session present flag ...
msg.sessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00;
}
// ...and set return code from broker
msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];
return msg;
}
public override byte[] GetBytes(byte ProtocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
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()
{
public Boolean SessionPresent { get; set; }
/// <summary>
/// Return Code
/// </summary>
public Byte ReturnCode { get; set; }
#endregion
// [v3.1.1] session present flag
/// <summary>
/// Constructor
/// </summary>
public MqttMsgConnack() => this.Type = MQTT_MSG_CONNACK_TYPE;
/// <summary>
/// Parse bytes for a CONNACK message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>CONNACK message instance</returns>
public static MqttMsgConnack Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
Byte[] buffer;
MqttMsgConnack msg = new MqttMsgConnack();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
}
// get remaining length and allocate buffer
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new Byte[remainingLength];
// read bytes from socket...
_ = channel.Receive(buffer);
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] ... set session present flag ...
msg.SessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00;
}
// ...and set return code from broker
msg.ReturnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];
return msg;
}
public override Byte[] GetBytes(Byte ProtocolVersion) {
Int32 varHeaderSize = 0;
Int32 payloadSize = 0;
Int32 remainingLength = 0;
Byte[] buffer;
Int32 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
Int32 fixedHeaderSize = 1;
Int32 temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do {
fixedHeaderSize++;
temp /= 128;
} while (temp > 0);
// allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
buffer[index++] = ProtocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
? (Byte)((MQTT_MSG_CONNACK_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNACK_FLAG_BITS)
: (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
return this.GetTraceString(
"CONNACK",
new object[] { "returnCode" },
new object[] { this.returnCode });
this.GetTraceString(
"CONNACK",
new Object[] { "returnCode" },
new Object[] { this.ReturnCode });
#else
return base.ToString();
base.ToString();
#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
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System;
#else
using Microsoft.SPOT;
#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>
/// Event Args class for CONNECT message received from client
/// Message received from client
/// </summary>
public class MqttMsgConnectEventArgs : EventArgs
{
/// <summary>
/// Message received from client
/// </summary>
public MqttMsgConnect Message { get; private set; }
/// <summary>
/// Constructor
/// </summary>
/// <param name="msg">CONNECT message received from client</param>
public MqttMsgConnectEventArgs(MqttMsgConnect connect)
{
this.Message = connect;
}
}
}
public MqttMsgConnect Message { get; private set; }
/// <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.Text;
namespace uPLibrary.Networking.M2Mqtt.Messages
{
namespace uPLibrary.Networking.M2Mqtt.Messages {
/// <summary>
/// Context for MQTT message
/// </summary>
public class MqttMsgContext {
/// <summary>
/// Context for MQTT message
/// MQTT message
/// </summary>
public class MqttMsgContext
{
/// <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
}
public MqttMsgBase Message { get; set; }
/// <summary>
/// MQTT message state
/// </summary>
public enum MqttMsgState
{
/// <summary>
/// QOS = 0, Message queued
/// </summary>
QueuedQos0,
/// <summary>
/// QOS = 1, Message queued
/// </summary>
QueuedQos1,
/// <summary>
/// QOS = 2, Message queued
/// </summary>
QueuedQos2,
/// <summary>
/// QOS = 1, PUBLISH sent, wait for PUBACK
/// </summary>
WaitForPuback,
/// <summary>
/// QOS = 2, PUBLISH sent, wait for PUBREC
/// </summary>
WaitForPubrec,
/// <summary>
/// QOS = 2, PUBREC sent, wait for PUBREL
/// </summary>
WaitForPubrel,
/// <summary>
/// QOS = 2, PUBREL sent, wait for PUBCOMP
/// </summary>
WaitForPubcomp,
/// <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
}
public MqttMsgState State { get; set; }
/// <summary>
/// Flow of the message
/// </summary>
public MqttMsgFlow Flow { get; set; }
/// <summary>
/// Timestamp in ticks (for retry)
/// </summary>
public Int32 Timestamp { get; set; }
/// <summary>
/// Attempt (for retry)
/// </summary>
public Int32 Attempt { get; set; }
/// <summary>
/// Unique key
/// </summary>
public String Key => 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>
/// MQTT message state
/// </summary>
public enum MqttMsgState {
/// <summary>
/// QOS = 0, Message queued
/// </summary>
QueuedQos0,
/// <summary>
/// QOS = 1, Message queued
/// </summary>
QueuedQos1,
/// <summary>
/// QOS = 2, Message queued
/// </summary>
QueuedQos2,
/// <summary>
/// QOS = 1, PUBLISH sent, wait for PUBACK
/// </summary>
WaitForPuback,
/// <summary>
/// QOS = 2, PUBLISH sent, wait for PUBREC
/// </summary>
WaitForPubrec,
/// <summary>
/// QOS = 2, PUBREC sent, wait for PUBREL
/// </summary>
WaitForPubrel,
/// <summary>
/// QOS = 2, PUBREL sent, wait for PUBCOMP
/// </summary>
WaitForPubcomp,
/// <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
*/
using System;
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>
/// Class for DISCONNECT message from client to broker
/// Constructor
/// </summary>
public class MqttMsgDisconnect : MqttMsgBase
{
/// <summary>
/// Constructor
/// </summary>
public MqttMsgDisconnect()
{
this.type = MQTT_MSG_DISCONNECT_TYPE;
}
/// <summary>
/// Parse bytes for a DISCONNECT message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>DISCONNECT message instance</returns>
public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
MqttMsgDisconnect msg = new MqttMsgDisconnect();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
// NOTE : remainingLength must be 0
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
byte[] buffer = new byte[2];
int index = 0;
// first fixed header byte
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()
{
public MqttMsgDisconnect() => this.Type = MQTT_MSG_DISCONNECT_TYPE;
/// <summary>
/// Parse bytes for a DISCONNECT message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>DISCONNECT message instance</returns>
public static MqttMsgDisconnect Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
MqttMsgDisconnect msg = new MqttMsgDisconnect();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
}
// get remaining length and allocate buffer
_ = DecodeRemainingLength(channel);
// NOTE : remainingLength must be 0
return msg;
}
public override Byte[] GetBytes(Byte protocolVersion) {
Byte[] buffer = new Byte[2];
Int32 index = 0;
// first fixed header byte
buffer[index++] = protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1
? (Byte)((MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_DISCONNECT_FLAG_BITS)
: (Byte)(MQTT_MSG_DISCONNECT_TYPE << MSG_TYPE_OFFSET);
buffer[index++] = 0x00;
return buffer;
}
public override String ToString() =>
#if TRACE
return this.GetTraceString(
"DISCONNECT",
null,
null);
this.GetTraceString(
"DISCONNECT",
null,
null);
#else
return base.ToString();
base.ToString();
#endif
}
}
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,98 +14,66 @@ Contributors:
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;
#else
using Microsoft.SPOT;
#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>
/// Event Args class for PUBLISH message received from broker
/// Message topic
/// </summary>
public class MqttMsgPublishEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message topic
/// </summary>
public string Topic
{
get { return this.topic; }
internal set { this.topic = value; }
}
/// <summary>
/// Message data
/// </summary>
public byte[] Message
{
get { return this.message; }
internal set { this.message = 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; }
internal set { this.qosLevel = value; }
}
/// <summary>
/// Retain message flag
/// </summary>
public bool 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;
}
}
public String Topic { get; internal set; }
/// <summary>
/// Message data
/// </summary>
public Byte[] Message { get; internal set; }
/// <summary>
/// Duplicate message flag
/// </summary>
public Boolean DupFlag { get; set; }
/// <summary>
/// Quality of Service level
/// </summary>
public Byte QosLevel { get; internal set; }
/// <summary>
/// Retain message flag
/// </summary>
public Boolean Retain { get; internal set; }
#endregion
// message topic
/// <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,
Boolean dupFlag,
Byte qosLevel,
Boolean 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
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System;
#else
using Microsoft.SPOT;
#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>
/// Event Args class for published message
/// Message identifier
/// </summary>
public class MqttMsgPublishedEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary>
/// Message published (or failed due to retries)
/// </summary>
public bool IsPublished
{
get { return this.isPublished; }
internal set { this.isPublished = value; }
}
#endregion
// message identifier
ushort messageId;
// 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;
}
}
public UInt16 MessageId { get; internal set; }
/// <summary>
/// Message published (or failed due to retries)
/// </summary>
public Boolean IsPublished { get; internal set; }
#endregion
// message identifier
/// <summary>
/// Constructor (published message)
/// </summary>
/// <param name="messageId">Message identifier published</param>
public MqttMsgPublishedEventArgs(UInt16 messageId)
: this(messageId, true) {
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier</param>
/// <param name="isPublished">Publish flag</param>
public MqttMsgPublishedEventArgs(UInt16 messageId, Boolean isPublished) {
this.MessageId = messageId;
this.IsPublished = isPublished;
}
}
}

View File

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

View File

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

View File

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

View File

@ -16,257 +16,234 @@ Contributors:
using System;
// 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;
#endif
using System.Collections;
using System.Text;
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>
/// Class for SUBSCRIBE message from client to broker
/// List of topics to subscribe
/// </summary>
public class MqttMsgSubscribe : MqttMsgBase
{
#region Properties...
/// <summary>
/// List of topics to subscribe
/// </summary>
public string[] Topics
{
get { return this.topics; }
set { this.topics = value; }
}
/// <summary>
/// List of QOS Levels related to topics
/// </summary>
public byte[] QoSLevels
{
get { return this.qosLevels; }
set { this.qosLevels = value; }
}
#endregion
// topics to subscribe
string[] topics;
// QOS levels related to topics
byte[] qosLevels;
/// <summary>
/// Constructor
/// </summary>
public MqttMsgSubscribe()
{
this.type = MQTT_MSG_SUBSCRIBE_TYPE;
}
/// <summary>
/// Constructor
/// </summary>
/// <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)
{
this.type = MQTT_MSG_SUBSCRIBE_TYPE;
this.topics = topics;
this.qosLevels = qosLevels;
// SUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE;
}
/// <summary>
/// Parse bytes for a SUBSCRIBE message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>SUBSCRIBE message instance</returns>
public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
byte[] topicUtf8;
int topicUtf8Length;
MqttMsgSubscribe msg = new MqttMsgSubscribe();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// 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)
public String[] Topics { get; set; }
/// <summary>
/// List of QOS Levels related to topics
/// </summary>
public Byte[] QoSLevels { get; set; }
#endregion
// topics to subscribe
/// <summary>
/// Constructor
/// </summary>
public MqttMsgSubscribe() => this.Type = MQTT_MSG_SUBSCRIBE_TYPE;
/// <summary>
/// Constructor
/// </summary>
/// <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) {
this.Type = MQTT_MSG_SUBSCRIBE_TYPE;
this.Topics = topics;
this.QoSLevels = qosLevels;
// SUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
}
/// <summary>
/// Parse bytes for a SUBSCRIBE message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>SUBSCRIBE message instance</returns>
public static MqttMsgSubscribe Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
Byte[] buffer;
Int32 index = 0;
Byte[] topicUtf8;
Int32 topicUtf8Length;
MqttMsgSubscribe msg = new MqttMsgSubscribe();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
}
// get remaining length and allocate buffer
Int32 remainingLength = MqttMsgBase.DecodeRemainingLength(channel);
buffer = new Byte[remainingLength];
// read bytes from socket...
Int32 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 = (UInt16)((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 tmpQosLevels = new ArrayList();
// else other frameworks (.Net, .Net Compact, Mono, Windows Phone)
#else
IList<String> tmpTopics = new List<String>();
IList<byte> tmpQosLevels = new List<byte>();
IList<String> tmpTopics = new List<String>();
IList<Byte> tmpQosLevels = new List<Byte>();
#endif
do
{
// topic name
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
topicUtf8Length |= buffer[index++];
topicUtf8 = new byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
index += topicUtf8Length;
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
// QoS level
tmpQosLevels.Add(buffer[index++]);
} while (index < remainingLength);
// copy from list to array
msg.topics = new string[tmpTopics.Count];
msg.qosLevels = new byte[tmpQosLevels.Count];
for (int i = 0; i < tmpTopics.Count; i++)
{
msg.topics[i] = (string)tmpTopics[i];
msg.qosLevels[i] = (byte)tmpQosLevels[i];
}
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// topics list empty
if ((this.topics == null) || (this.topics.Length == 0))
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
// 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)
throw new MqttClientException(MqttClientErrorCode.TopicsQosLevelsNotMatch);
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
int topicIdx = 0;
byte[][] topicsUtf8 = new byte[this.topics.Length][];
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))
throw new MqttClientException(MqttClientErrorCode.TopicLength);
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.topics[topicIdx]);
payloadSize += 2; // topic size (MSB, LSB)
payloadSize += topicsUtf8[topicIdx].Length;
payloadSize++; // byte for QoS
}
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_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBSCRIBE_FLAG_BITS; // [v.3.1.1]
else
{
buffer[index] = (byte)((MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
(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);
// 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)((messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(messageId & 0x00FF); // LSB
topicIdx = 0;
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
{
// topic name
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
index += topicsUtf8[topicIdx].Length;
// requested QoS
buffer[index++] = this.qosLevels[topicIdx];
}
return buffer;
}
public override string ToString()
{
do {
// topic name
topicUtf8Length = (buffer[index++] << 8) & 0xFF00;
topicUtf8Length |= buffer[index++];
topicUtf8 = new Byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
index += topicUtf8Length;
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
// QoS level
tmpQosLevels.Add(buffer[index++]);
} while (index < remainingLength);
// copy from list to array
msg.Topics = new String[tmpTopics.Count];
msg.QoSLevels = new Byte[tmpQosLevels.Count];
for (Int32 i = 0; i < tmpTopics.Count; i++) {
msg.Topics[i] = (String)tmpTopics[i];
msg.QoSLevels[i] = (Byte)tmpQosLevels[i];
}
return msg;
}
public override Byte[] GetBytes(Byte protocolVersion) {
Int32 varHeaderSize = 0;
Int32 payloadSize = 0;
Int32 remainingLength = 0;
Byte[] buffer;
Int32 index = 0;
// topics list empty
if (this.Topics == null || this.Topics.Length == 0) {
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
}
// 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) {
throw new MqttClientException(MqttClientErrorCode.TopicsQosLevelsNotMatch);
}
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
Byte[][] topicsUtf8 = new Byte[this.Topics.Length][];
Int32 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) {
throw new MqttClientException(MqttClientErrorCode.TopicLength);
}
topicsUtf8[topicIdx] = Encoding.UTF8.GetBytes(this.Topics[topicIdx]);
payloadSize += 2; // topic size (MSB, LSB)
payloadSize += topicsUtf8[topicIdx].Length;
payloadSize++; // byte for QoS
}
remainingLength += varHeaderSize + payloadSize;
// first byte of fixed header
Int32 fixedHeaderSize = 1;
Int32 temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do {
fixedHeaderSize++;
temp /= 128;
} while (temp > 0);
// allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
buffer[index++] = (MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_SUBSCRIBE_FLAG_BITS; // [v.3.1.1]
} else {
buffer[index] = (Byte)((MQTT_MSG_SUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
(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);
// 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)(this.MessageId & 0x00FF); // LSB
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
// topic name
buffer[index++] = (Byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
index += topicsUtf8[topicIdx].Length;
// requested QoS
buffer[index++] = this.QoSLevels[topicIdx];
}
return buffer;
}
public override String ToString() =>
#if TRACE
return this.GetTraceString(
"SUBSCRIBE",
new object[] { "messageId", "topics", "qosLevels" },
new object[] { this.messageId, this.topics, this.qosLevels });
this.GetTraceString(
"SUBSCRIBE",
new Object[] { "messageId", "topics", "qosLevels" },
new Object[] { this.MessageId, this.Topics, this.QoSLevels });
#else
return base.ToString();
base.ToString();
#endif
}
}
}
}

View File

@ -14,68 +14,48 @@ Contributors:
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;
#else
using Microsoft.SPOT;
#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>
/// Event Args class for subscribe request on topics
/// Message identifier
/// </summary>
public class MqttMsgSubscribeEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary>
/// Topics requested to subscribe
/// </summary>
public string[] Topics
{
get { return this.topics; }
internal set { this.topics = value; }
}
/// <summary>
/// List of QOS Levels requested
/// </summary>
public byte[] 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;
}
}
public UInt16 MessageId { get; internal set; }
/// <summary>
/// Topics requested to subscribe
/// </summary>
public String[] Topics { get; internal set; }
/// <summary>
/// List of QOS Levels requested
/// </summary>
public Byte[] QoSLevels { get; internal set; }
#endregion
// message identifier
/// <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(UInt16 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
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System;
#else
using Microsoft.SPOT;
#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>
/// Event Args class for subscribed topics
/// Message identifier
/// </summary>
public class MqttMsgSubscribedEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary>
/// List of granted QOS Levels
/// </summary>
public byte[] GrantedQoSLevels
{
get { return this.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;
}
}
public UInt16 MessageId { get; internal set; }
/// <summary>
/// List of granted QOS Levels
/// </summary>
public Byte[] GrantedQoSLevels { get; internal set; }
#endregion
// message identifier
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for subscribed topics</param>
/// <param name="grantedQosLevels">List of granted QOS Levels</param>
public MqttMsgSubscribedEventArgs(UInt16 messageId, Byte[] grantedQosLevels) {
this.MessageId = messageId;
this.GrantedQoSLevels = grantedQosLevels;
}
}
}

View File

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

View File

@ -16,224 +16,205 @@ Contributors:
using System;
// 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;
#endif
using System.Collections;
using System.Text;
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>
/// Class for UNSUBSCRIBE message from client to broker
/// List of topics to unsubscribe
/// </summary>
public class MqttMsgUnsubscribe : MqttMsgBase
{
#region Properties...
/// <summary>
/// List of topics to unsubscribe
/// </summary>
public string[] Topics
{
get { return this.topics; }
set { this.topics = value; }
}
#endregion
// topics to unsubscribe
string[] topics;
/// <summary>
/// Constructor
/// </summary>
public MqttMsgUnsubscribe()
{
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE;
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="topics">List of topics to unsubscribe</param>
public MqttMsgUnsubscribe(string[] topics)
{
this.type = MQTT_MSG_UNSUBSCRIBE_TYPE;
this.topics = topics;
// UNSUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
this.qosLevel = QOS_LEVEL_AT_LEAST_ONCE;
}
/// <summary>
/// Parse bytes for a UNSUBSCRIBE message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>UNSUBSCRIBE message instance</returns>
public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
{
byte[] buffer;
int index = 0;
byte[] topicUtf8;
int topicUtf8Length;
MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
{
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS)
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
// get remaining length and allocate buffer
int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
buffer = new byte[remainingLength];
// 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
// 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)
public String[] Topics { get; set; }
#endregion
// topics to unsubscribe
/// <summary>
/// Constructor
/// </summary>
public MqttMsgUnsubscribe() => this.Type = MQTT_MSG_UNSUBSCRIBE_TYPE;
/// <summary>
/// Constructor
/// </summary>
/// <param name="topics">List of topics to unsubscribe</param>
public MqttMsgUnsubscribe(String[] topics) {
this.Type = MQTT_MSG_UNSUBSCRIBE_TYPE;
this.Topics = topics;
// UNSUBSCRIBE message uses QoS Level 1 (not "officially" in 3.1.1)
this.QosLevel = QOS_LEVEL_AT_LEAST_ONCE;
}
/// <summary>
/// Parse bytes for a UNSUBSCRIBE message
/// </summary>
/// <param name="fixedHeaderFirstByte">First fixed header byte</param>
/// <param name="protocolVersion">Protocol Version</param>
/// <param name="channel">Channel connected to the broker</param>
/// <returns>UNSUBSCRIBE message instance</returns>
public static MqttMsgUnsubscribe Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) {
Byte[] buffer;
Int32 index = 0;
Byte[] topicUtf8;
Int32 topicUtf8Length;
MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe();
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
// [v3.1.1] check flag bits
if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_UNSUBSCRIBE_FLAG_BITS) {
throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
}
}
// get remaining length and allocate buffer
Int32 remainingLength = DecodeRemainingLength(channel);
buffer = new Byte[remainingLength];
// read bytes from socket...
Int32 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 = (UInt16)((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();
// else other frameworks (.Net, .Net Compact, Mono, Windows Phone)
#else
IList<String> tmpTopics = new List<String>();
IList<String> tmpTopics = new List<String>();
#endif
do
{
// topic name
topicUtf8Length = ((buffer[index++] << 8) & 0xFF00);
topicUtf8Length |= buffer[index++];
topicUtf8 = new byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
index += topicUtf8Length;
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
} while (index < remainingLength);
// copy from list to array
msg.topics = new string[tmpTopics.Count];
for (int i = 0; i < tmpTopics.Count; i++)
{
msg.topics[i] = (string)tmpTopics[i];
}
return msg;
}
public override byte[] GetBytes(byte protocolVersion)
{
int fixedHeaderSize = 0;
int varHeaderSize = 0;
int payloadSize = 0;
int remainingLength = 0;
byte[] buffer;
int index = 0;
// topics list empty
if ((this.topics == null) || (this.topics.Length == 0))
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
int topicIdx = 0;
byte[][] topicsUtf8 = new byte[this.topics.Length][];
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))
throw new MqttClientException(MqttClientErrorCode.TopicLength);
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
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_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBSCRIBE_FLAG_BITS; // [v.3.1.1]
else
{
buffer[index] = (byte)((MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
(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);
// check message identifier assigned
if (this.messageId == 0)
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
buffer[index++] = (byte)((messageId >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(messageId & 0x00FF); // LSB
topicIdx = 0;
for (topicIdx = 0; topicIdx < this.topics.Length; topicIdx++)
{
// topic name
buffer[index++] = (byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
buffer[index++] = (byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
index += topicsUtf8[topicIdx].Length;
}
return buffer;
}
public override string ToString()
{
do {
// topic name
topicUtf8Length = (buffer[index++] << 8) & 0xFF00;
topicUtf8Length |= buffer[index++];
topicUtf8 = new Byte[topicUtf8Length];
Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
index += topicUtf8Length;
tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
} while (index < remainingLength);
// copy from list to array
msg.Topics = new String[tmpTopics.Count];
for (Int32 i = 0; i < tmpTopics.Count; i++) {
msg.Topics[i] = (String)tmpTopics[i];
}
return msg;
}
public override Byte[] GetBytes(Byte protocolVersion) {
Int32 varHeaderSize = 0;
Int32 payloadSize = 0;
Int32 remainingLength = 0;
Byte[] buffer;
Int32 index = 0;
// topics list empty
if (this.Topics == null || this.Topics.Length == 0) {
throw new MqttClientException(MqttClientErrorCode.TopicsEmpty);
}
// message identifier
varHeaderSize += MESSAGE_ID_SIZE;
Byte[][] topicsUtf8 = new Byte[this.Topics.Length][];
Int32 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) {
throw new MqttClientException(MqttClientErrorCode.TopicLength);
}
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
Int32 fixedHeaderSize = 1;
Int32 temp = remainingLength;
// increase fixed header size based on remaining length
// (each remaining length byte can encode until 128)
do {
fixedHeaderSize++;
temp /= 128;
} while (temp > 0);
// allocate buffer for message
buffer = new Byte[fixedHeaderSize + varHeaderSize + payloadSize];
// first fixed header byte
if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1) {
buffer[index++] = (MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_UNSUBSCRIBE_FLAG_BITS; // [v.3.1.1]
} else {
buffer[index] = (Byte)((MQTT_MSG_UNSUBSCRIBE_TYPE << MSG_TYPE_OFFSET) |
(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);
// check message identifier assigned
if (this.MessageId == 0) {
throw new MqttClientException(MqttClientErrorCode.WrongMessageId);
}
buffer[index++] = (Byte)((this.MessageId >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(this.MessageId & 0x00FF); // LSB
for (topicIdx = 0; topicIdx < this.Topics.Length; topicIdx++) {
// topic name
buffer[index++] = (Byte)((topicsUtf8[topicIdx].Length >> 8) & 0x00FF); // MSB
buffer[index++] = (Byte)(topicsUtf8[topicIdx].Length & 0x00FF); // LSB
Array.Copy(topicsUtf8[topicIdx], 0, buffer, index, topicsUtf8[topicIdx].Length);
index += topicsUtf8[topicIdx].Length;
}
return buffer;
}
public override String ToString() =>
#if TRACE
return this.GetTraceString(
"UNSUBSCRIBE",
new object[] { "messageId", "topics" },
new object[] { this.messageId, this.topics });
this.GetTraceString(
"UNSUBSCRIBE",
new Object[] { "messageId", "topics" },
new Object[] { this.MessageId, this.Topics });
#else
return base.ToString();
base.ToString();
#endif
}
}
}
}

View File

@ -14,55 +14,41 @@ Contributors:
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;
#else
using Microsoft.SPOT;
#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>
/// Event Args class for unsubscribe request on topics
/// Message identifier
/// </summary>
public class MqttMsgUnsubscribeEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
/// <summary>
/// Topics requested to subscribe
/// </summary>
public string[] Topics
{
get { return this.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;
}
}
public UInt16 MessageId { get; internal set; }
/// <summary>
/// Topics requested to subscribe
/// </summary>
public String[] Topics { get; internal set; }
#endregion
// message identifier
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for subscribed topics</param>
/// <param name="topics">Topics requested to subscribe</param>
public MqttMsgUnsubscribeEventArgs(UInt16 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
*/
#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3)
#if !MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3
using System;
#else
using Microsoft.SPOT;
#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>
/// Event Args class for unsubscribed topic
/// Message identifier
/// </summary>
public class MqttMsgUnsubscribedEventArgs : EventArgs
{
#region Properties...
/// <summary>
/// Message identifier
/// </summary>
public ushort MessageId
{
get { return this.messageId; }
internal set { this.messageId = value; }
}
#endregion
// message identifier
ushort messageId;
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for unsubscribed topic</param>
public MqttMsgUnsubscribedEventArgs(ushort messageId)
{
this.messageId = messageId;
}
}
public UInt16 MessageId { get; internal set; }
#endregion
// message identifier
/// <summary>
/// Constructor
/// </summary>
/// <param name="messageId">Message identifier for unsubscribed topic</param>
public MqttMsgUnsubscribedEventArgs(UInt16 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
*/
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Supported SSL/TLS protocol versions
/// </summary>
public enum MqttSslProtocols
{
None,
SSLv3,
TLSv1_0,
TLSv1_1,
TLSv1_2
}
namespace uPLibrary.Networking.M2Mqtt {
/// <summary>
/// Supported SSL/TLS protocol versions
/// </summary>
public enum MqttSslProtocols {
None,
SSLv3,
TLSv1_0,
TLSv1_1,
TLSv1_2
}
}

View File

@ -14,91 +14,90 @@ Contributors:
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>
/// Settings class for the MQTT broker
/// Listening connection port
/// </summary>
public class MqttSettings
{
// default port for MQTT protocol
public const int MQTT_BROKER_DEFAULT_PORT = 1883;
public const int MQTT_BROKER_DEFAULT_SSL_PORT = 8883;
// default timeout on receiving from client
public const int MQTT_DEFAULT_TIMEOUT = 30000;
// max publish, subscribe and unsubscribe retry for QoS Level 1 or 2
public const int MQTT_ATTEMPTS_RETRY = 3;
// delay for retry publish, subscribe and unsubscribe for QoS Level 1 or 2
public const int MQTT_DELAY_RETRY = 10000;
// broker need to receive the first message (CONNECT)
// within a reasonable amount of time after TCP/IP connection
public const int MQTT_CONNECT_TIMEOUT = 30000;
// default inflight queue size
public const int MQTT_MAX_INFLIGHT_QUEUE_SIZE = int.MaxValue;
/// <summary>
/// Listening connection port
/// </summary>
public int Port { get; internal set; }
/// <summary>
/// Listening connection SSL port
/// </summary>
public int SslPort { get; internal set; }
/// <summary>
/// Timeout on client connection (before receiving CONNECT message)
/// </summary>
public int TimeoutOnConnection { get; internal set; }
/// <summary>
/// Timeout on receiving
/// </summary>
public int TimeoutOnReceiving { get; internal set; }
/// <summary>
/// Attempts on retry
/// </summary>
public int AttemptsOnRetry { get; internal set; }
/// <summary>
/// Delay on retry
/// </summary>
public int DelayOnRetry { get; internal set; }
/// <summary>
/// Inflight queue size
/// </summary>
public int InflightQueueSize { get; set; }
/// <summary>
/// Singleton instance of settings
/// </summary>
public static MqttSettings Instance
{
get
{
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;
}
}
public Int32 Port { get; internal set; }
/// <summary>
/// Listening connection SSL port
/// </summary>
public Int32 SslPort { get; internal set; }
/// <summary>
/// Timeout on client connection (before receiving CONNECT message)
/// </summary>
public Int32 TimeoutOnConnection { get; internal set; }
/// <summary>
/// Timeout on receiving
/// </summary>
public Int32 TimeoutOnReceiving { get; internal set; }
/// <summary>
/// Attempts on retry
/// </summary>
public Int32 AttemptsOnRetry { get; internal set; }
/// <summary>
/// Delay on retry
/// </summary>
public Int32 DelayOnRetry { get; internal set; }
/// <summary>
/// Inflight queue size
/// </summary>
public Int32 InflightQueueSize { get; set; }
/// <summary>
/// Singleton instance of settings
/// </summary>
public static MqttSettings Instance {
get {
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
*/
using System;
using System.Threading;
namespace uPLibrary.Networking.M2Mqtt
{
/// <summary>
/// Support methods fos specific framework
/// </summary>
public class Fx
{
public static void StartThread(ThreadStart threadStart)
{
new Thread(threadStart).Start();
}
public static void SleepThread(int millisecondsTimeout)
{
Thread.Sleep(millisecondsTimeout);
}
}
namespace uPLibrary.Networking.M2Mqtt {
/// <summary>
/// Support methods fos specific framework
/// </summary>
public class Fx {
public static void StartThread(ThreadStart threadStart) => new Thread(threadStart).Start();
public static void SleepThread(Int32 millisecondsTimeout) => Thread.Sleep(millisecondsTimeout);
}
}

View File

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

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if !NETCOREAPP
using System.Reflection;
using System.Runtime.CompilerServices;
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
#if !WindowsCE
[assembly: AssemblyFileVersion("4.3.0.0")]
#endif
#endif

View File

@ -14,20 +14,18 @@ Contributors:
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>
/// MQTT Client Session
/// Constructor
/// </summary>
public class MqttClientSession : MqttSession
{
/// <summary>
/// Constructor
/// </summary>
/// <param name="clientId">Client Id to create session</param>
public MqttClientSession(string clientId)
: base(clientId)
{
}
}
/// <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
*/
using System;
using System.Collections;
namespace uPLibrary.Networking.M2Mqtt.Session
{
namespace uPLibrary.Networking.M2Mqtt.Session {
/// <summary>
/// MQTT Session base class
/// </summary>
public abstract class MqttSession {
/// <summary>
/// MQTT Session base class
/// Client Id
/// </summary>
public abstract class MqttSession
{
/// <summary>
/// Client Id
/// </summary>
public string ClientId { get; set; }
/// <summary>
/// Messages inflight during session
/// </summary>
public Hashtable InflightMessages { get; set; }
/// <summary>
/// Constructor
/// </summary>
public MqttSession()
: this(null)
{
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="clientId">Client Id to create session</param>
public MqttSession(string clientId)
{
this.ClientId = clientId;
this.InflightMessages = new Hashtable();
}
/// <summary>
/// Clean session
/// </summary>
public virtual void Clear()
{
this.ClientId = null;
this.InflightMessages.Clear();
}
}
}
public String ClientId { get; set; }
/// <summary>
/// Messages inflight during session
/// </summary>
public Hashtable InflightMessages { get; set; }
/// <summary>
/// Constructor
/// </summary>
public MqttSession()
: this(null) {
}
/// <summary>
/// Constructor
/// </summary>
/// <param name="clientId">Client Id to create session</param>
public MqttSession(String clientId) {
this.ClientId = clientId;
this.InflightMessages = new Hashtable();
}
/// <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.Collections;
namespace uPLibrary.Networking.M2Mqtt.Utility
{
namespace uPLibrary.Networking.M2Mqtt.Utility {
/// <summary>
/// Extension class for a Queue
/// </summary>
internal static class QueueExtension {
/// <summary>
/// Extension class for a Queue
/// Predicate for searching inside a queue
/// </summary>
internal static class QueueExtension
{
/// <summary>
/// Predicate for searching inside a queue
/// </summary>
/// <param name="item">Item of the queue</param>
/// <returns>Result of predicate</returns>
internal delegate bool QueuePredicate(object item);
/// <summary>
/// Get (without removing) an item from queue based on predicate
/// </summary>
/// <param name="queue">Queue in which to search</param>
/// <param name="predicate">Predicate to verify to get item</param>
/// <returns>Item matches the predicate</returns>
internal static object Get(Queue queue, QueuePredicate predicate)
{
foreach (var item in queue)
{
if (predicate(item))
return item;
}
return null;
}
}
/// <param name="item">Item of the queue</param>
/// <returns>Result of predicate</returns>
internal delegate Boolean QueuePredicate(Object item);
/// <summary>
/// Get (without removing) an item from queue based on predicate
/// </summary>
/// <param name="queue">Queue in which to search</param>
/// <param name="predicate">Predicate to verify to get item</param>
/// <returns>Item matches the predicate</returns>
internal static Object Get(Queue queue, QueuePredicate predicate) {
foreach (Object 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
*/
using System;
using System.Diagnostics;
namespace uPLibrary.Networking.M2Mqtt.Utility
{
/// <summary>
/// Tracing levels
/// </summary>
public enum TraceLevel
{
Error = 0x01,
Warning = 0x02,
Information = 0x04,
Verbose = 0x0F,
Frame = 0x10,
Queuing = 0x20
}
// delegate for writing trace
public delegate void WriteTrace(string format, params object[] args);
/// <summary>
/// Tracing class
/// </summary>
public static class Trace
{
public static TraceLevel TraceLevel;
public static WriteTrace TraceListener;
[Conditional("DEBUG")]
public static void Debug(string format, params object[] args)
{
if (TraceListener != null)
{
TraceListener(format, args);
}
}
public static void WriteLine(TraceLevel level, string format)
{
if (TraceListener != null && (level & TraceLevel) > 0)
{
TraceListener(format);
}
}
public static void WriteLine(TraceLevel level, string format, object arg1)
{
if (TraceListener != null && (level & TraceLevel) > 0)
{
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);
}
}
}
namespace uPLibrary.Networking.M2Mqtt.Utility {
/// <summary>
/// Tracing levels
/// </summary>
public enum TraceLevel {
Error = 0x01,
Warning = 0x02,
Information = 0x04,
Verbose = 0x0F,
Frame = 0x10,
Queuing = 0x20
}
// delegate for writing trace
public delegate void WriteTrace(String format, params Object[] args);
/// <summary>
/// Tracing class
/// </summary>
public static class Trace {
public static TraceLevel TraceLevel;
public static WriteTrace TraceListener;
[Conditional("DEBUG")]
public static void Debug(String format, params Object[] args) => TraceListener?.Invoke(format, args);
public static void WriteLine(TraceLevel level, String format) {
if ((level & TraceLevel) > 0) {
TraceListener.Invoke(format);
}
}
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, Object arg1, Object arg2) {
if ((level & TraceLevel) > 0) {
TraceListener.Invoke(format, arg1, arg2);
}
}
public static void WriteLine(TraceLevel level, String format, Object arg1, Object arg2, Object arg3) {
if ((level & TraceLevel) > 0) {
TraceListener.Invoke(format, arg1, arg2, arg3);
}
}
}
}

View File

@ -13,7 +13,7 @@ and the Eclipse Distribution License is available at
Contributors:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if !NETCOREAPP
using System.Threading;
using System.Threading.Tasks;
@ -33,4 +33,5 @@ namespace uPLibrary.Networking.M2Mqtt
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:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if !NETCOREAPP
using System.Collections.Generic;
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:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if !NETCOREAPP
using System;
using System.Collections.Generic;
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:
Paolo Patierno - initial API and implementation and/or initial documentation
*/
#if !NETCOREAPP
using System.Collections.Generic;
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