diff --git a/mqtt/M2Mqtt/Exceptions/MqttClientException.cs b/mqtt/M2Mqtt/Exceptions/MqttClientException.cs deleted file mode 100644 index cd8303f..0000000 --- a/mqtt/M2Mqtt/Exceptions/MqttClientException.cs +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; - -namespace uPLibrary.Networking.M2Mqtt.Exceptions -{ - /// - /// MQTT client exception - /// - public class MqttClientException : Exception - { - /// - /// Constructor - /// - /// Error code - public MqttClientException(MqttClientErrorCode errorCode) - { - this.errorCode = errorCode; - } - - // error code - private MqttClientErrorCode errorCode; - - /// - /// Error code - /// - public MqttClientErrorCode ErrorCode - { - get { return this.errorCode; } - set { this.errorCode = value; } - } - } - - /// - /// MQTT client erroro code - /// - public enum MqttClientErrorCode - { - /// - /// Will error (topic, message or QoS level) - /// - WillWrong = 1, - - /// - /// Keep alive period too large - /// - KeepAliveWrong, - - /// - /// Topic contains wildcards - /// - TopicWildcard, - - /// - /// Topic length wrong - /// - TopicLength, - - /// - /// QoS level not allowed - /// - QosNotAllowed, - - /// - /// Topics list empty for subscribe - /// - TopicsEmpty, - - /// - /// Qos levels list empty for subscribe - /// - QosLevelsEmpty, - - /// - /// Topics / Qos Levels not match in subscribe - /// - TopicsQosLevelsNotMatch, - - /// - /// Wrong message from broker - /// - WrongBrokerMessage, - - /// - /// Wrong Message Id - /// - WrongMessageId, - - /// - /// Inflight queue is full - /// - InflightQueueFull, - - // [v3.1.1] - /// - /// Invalid flag bits received - /// - InvalidFlagBits, - - // [v3.1.1] - /// - /// Invalid connect flags received - /// - InvalidConnectFlags, - - // [v3.1.1] - /// - /// Invalid client id - /// - InvalidClientId, - - // [v3.1.1] - /// - /// Invalid protocol name - /// - InvalidProtocolName - } -} diff --git a/mqtt/M2Mqtt/Exceptions/MqttCommunicationException.cs b/mqtt/M2Mqtt/Exceptions/MqttCommunicationException.cs deleted file mode 100644 index 6b916cc..0000000 --- a/mqtt/M2Mqtt/Exceptions/MqttCommunicationException.cs +++ /dev/null @@ -1,42 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; - -namespace uPLibrary.Networking.M2Mqtt.Exceptions -{ - /// - /// Exception due to error communication with broker on socket - /// - public class MqttCommunicationException : Exception - { - /// - /// Default constructor - /// - public MqttCommunicationException() - { - } - - /// - /// Constructor - /// - /// Inner Exception - public MqttCommunicationException(Exception e) - : base(String.Empty, e) - { - } - } -} diff --git a/mqtt/M2Mqtt/Exceptions/MqttConnectionException.cs b/mqtt/M2Mqtt/Exceptions/MqttConnectionException.cs deleted file mode 100644 index 3203c7e..0000000 --- a/mqtt/M2Mqtt/Exceptions/MqttConnectionException.cs +++ /dev/null @@ -1,31 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; - -namespace uPLibrary.Networking.M2Mqtt.Exceptions -{ - /// - /// Connection to the broker exception - /// - public class MqttConnectionException : Exception - { - public MqttConnectionException(string message, Exception innerException) - : base(message, innerException) - { - } - } -} diff --git a/mqtt/M2Mqtt/Exceptions/MqttTimeoutException.cs b/mqtt/M2Mqtt/Exceptions/MqttTimeoutException.cs deleted file mode 100644 index b15e69e..0000000 --- a/mqtt/M2Mqtt/Exceptions/MqttTimeoutException.cs +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; - -namespace uPLibrary.Networking.M2Mqtt.Exceptions -{ - /// - /// Timeout on receiving from broker exception - /// - public class MqttTimeoutException : Exception - { - } -} diff --git a/mqtt/M2Mqtt/IMqttNetworkChannel.cs b/mqtt/M2Mqtt/IMqttNetworkChannel.cs deleted file mode 100644 index f4ff90f..0000000 --- a/mqtt/M2Mqtt/IMqttNetworkChannel.cs +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using System.Text; - -namespace uPLibrary.Networking.M2Mqtt -{ - /// - /// Interface for channel under MQTT library - /// - public interface IMqttNetworkChannel - { - /// - /// Data available on channel - /// - bool DataAvailable { get; } - - /// - /// Receive data from the network channel - /// - /// Data buffer for receiving data - /// Number of bytes received - int Receive(byte[] buffer); - - /// - /// Receive data from the network channel with a specified timeout - /// - /// Data buffer for receiving data - /// Timeout on receiving (in milliseconds) - /// Number of bytes received - int Receive(byte[] buffer, int timeout); - - /// - /// Send data on the network channel to the broker - /// - /// Data buffer to send - /// Number of byte sent - int Send(byte[] buffer); - - /// - /// Close the network channel - /// - void Close(); - - /// - /// Connect to remote server - /// - void Connect(); - - /// - /// Accept client connection - /// - void Accept(); - } -} diff --git a/mqtt/M2Mqtt/Internal/InternalEvent.cs b/mqtt/M2Mqtt/Internal/InternalEvent.cs deleted file mode 100644 index 7f298c7..0000000 --- a/mqtt/M2Mqtt/Internal/InternalEvent.cs +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -namespace uPLibrary.Networking.M2Mqtt.Internal -{ - /// - /// Generic internal event for dispatching - /// - public abstract class InternalEvent - { - } -} diff --git a/mqtt/M2Mqtt/Internal/MsgInternalEvent.cs b/mqtt/M2Mqtt/Internal/MsgInternalEvent.cs deleted file mode 100644 index 8cf46a4..0000000 --- a/mqtt/M2Mqtt/Internal/MsgInternalEvent.cs +++ /dev/null @@ -1,51 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using uPLibrary.Networking.M2Mqtt.Messages; - -namespace uPLibrary.Networking.M2Mqtt.Internal -{ - /// - /// Internal event with a message - /// - public class MsgInternalEvent : InternalEvent - { - #region Properties ... - - /// - /// Related message - /// - public MqttMsgBase Message - { - get { return this.msg; } - set { this.msg = value; } - } - - #endregion - - // related message - protected MqttMsgBase msg; - - /// - /// Constructor - /// - /// Related message - public MsgInternalEvent(MqttMsgBase msg) - { - this.msg = msg; - } - } -} diff --git a/mqtt/M2Mqtt/Internal/MsgPublishedInternalEvent.cs b/mqtt/M2Mqtt/Internal/MsgPublishedInternalEvent.cs deleted file mode 100644 index 5a7f182..0000000 --- a/mqtt/M2Mqtt/Internal/MsgPublishedInternalEvent.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using uPLibrary.Networking.M2Mqtt.Messages; - -namespace uPLibrary.Networking.M2Mqtt.Internal -{ - /// - /// Internal event for a published message - /// - public class MsgPublishedInternalEvent : MsgInternalEvent - { - #region Properties... - - /// - /// Message published (or failed due to retries) - /// - public bool IsPublished - { - get { return this.isPublished; } - internal set { this.isPublished = value; } - } - - #endregion - - // published flag - bool isPublished; - - /// - /// Constructor - /// - /// Message published - /// Publish flag - public MsgPublishedInternalEvent(MqttMsgBase msg, bool isPublished) - : base(msg) - { - this.isPublished = isPublished; - } - } -} diff --git a/mqtt/M2Mqtt/M2Mqtt_2.csproj b/mqtt/M2Mqtt/M2Mqtt_2.csproj deleted file mode 100644 index bc4a1d9..0000000 --- a/mqtt/M2Mqtt/M2Mqtt_2.csproj +++ /dev/null @@ -1,93 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {A11AEF5A-B246-4FE8-8330-06DB73CC8074} - Library - Properties - uPLibrary.Networking.M2Mqtt - M2Mqtt - v2.0 - 512 - - - - true - full - false - bin\Debug\2.0\ - TRACE;DEBUG - prompt - 4 - false - - - pdbonly - true - bin\Release\2.0\ - TRACE - prompt - 4 - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mqtt/M2Mqtt/M2Mqtt_4.7.1.csproj b/mqtt/M2Mqtt/M2Mqtt_4.7.1.csproj deleted file mode 100644 index 9fd2d99..0000000 --- a/mqtt/M2Mqtt/M2Mqtt_4.7.1.csproj +++ /dev/null @@ -1,93 +0,0 @@ - - - - Debug - AnyCPU - 8.0.30703 - 2.0 - {A11AEF5A-B246-4FE8-8330-06DB73CC8074} - Library - Properties - uPLibrary.Networking.M2Mqtt - M2Mqtt - v4.7.1 - 512 - - - - true - full - false - bin\Debug\4.7.1\ - TRACE;DEBUG;SSL - prompt - 4 - false - - - pdbonly - true - bin\Release\4.7.1\ - TRACE;SSL - prompt - 4 - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/mqtt/M2Mqtt/Messages/MqttMsgBase.cs b/mqtt/M2Mqtt/Messages/MqttMsgBase.cs deleted file mode 100644 index 870fe5f..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgBase.cs +++ /dev/null @@ -1,275 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using System.Text; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Base class for all MQTT messages - /// - public abstract class MqttMsgBase - { - #region Constants... - - // mask, offset and size for fixed header fields - internal const byte MSG_TYPE_MASK = 0xF0; - internal const byte MSG_TYPE_OFFSET = 0x04; - internal const byte MSG_TYPE_SIZE = 0x04; - internal const byte 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... - - /// - /// Message type - /// - public byte Type - { - get { return this.type; } - set { this.type = value; } - } - - /// - /// Duplicate message flag - /// - public bool DupFlag - { - get { return this.dupFlag; } - set { this.dupFlag = value; } - } - - /// - /// Quality of Service level - /// - public byte QosLevel - { - get { return this.qosLevel; } - set { this.qosLevel = value; } - } - - /// - /// Retain message flag - /// - public bool Retain - { - get { return this.retain; } - set { this.retain = value; } - } - - /// - /// Message identifier for the message - /// - 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; - - /// - /// Returns message bytes rapresentation - /// - /// Protocol version - /// Bytes rapresentation - public abstract byte[] GetBytes(byte protocolVersion); - - /// - /// Encode remaining length and insert it into message buffer - /// - /// Remaining length value to encode - /// Message buffer for inserting encoded value - /// Index from which insert encoded value into buffer - /// Index updated - protected int encodeRemainingLength(int remainingLength, byte[] buffer, int index) - { - int digit = 0; - do - { - digit = remainingLength % 128; - remainingLength /= 128; - if (remainingLength > 0) - digit = digit | 0x80; - buffer[index++] = (byte)digit; - } while (remainingLength > 0); - return index; - } - - /// - /// Decode remaining length reading bytes from socket - /// - /// Channel from reading bytes - /// Decoded remaining length - protected static int decodeRemainingLength(IMqttNetworkChannel channel) - { - int multiplier = 1; - int value = 0; - int digit = 0; - byte[] nextByte = new byte[1]; - do - { - // next digit from stream - channel.Receive(nextByte); - digit = nextByte[0]; - value += ((digit & 127) * multiplier); - multiplier *= 128; - } while ((digit & 128) != 0); - return value; - } - -#if TRACE - /// - /// Returns a string representation of the message for tracing - /// - /// Message name - /// Message fields name - /// Message fields value - /// String representation of the message - 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; - } -#endif - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgConnack.cs b/mqtt/M2Mqtt/Messages/MqttMsgConnack.cs deleted file mode 100644 index ae5a342..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgConnack.cs +++ /dev/null @@ -1,191 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for CONNACK message from broker to client - /// - 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 - /// - /// Session present flag - /// - public bool SessionPresent - { - get { return this.sessionPresent; } - set { this.sessionPresent = value; } - } - - /// - /// Return Code - /// - 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; - - /// - /// Constructor - /// - public MqttMsgConnack() - { - this.type = MQTT_MSG_CONNACK_TYPE; - } - - /// - /// Parse bytes for a CONNACK message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// CONNACK message instance - 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() - { -#if TRACE - return this.GetTraceString( - "CONNACK", - new object[] { "returnCode" }, - new object[] { this.returnCode }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgConnect.cs b/mqtt/M2Mqtt/Messages/MqttMsgConnect.cs deleted file mode 100644 index 382cf83..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgConnect.cs +++ /dev/null @@ -1,582 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using System.Text; -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for CONNECT message from client to broker - /// - public class MqttMsgConnect : MqttMsgBase - { - #region Constants... - - // protocol name supported - internal const string PROTOCOL_NAME_V3_1 = "MQIsdp"; - internal const string PROTOCOL_NAME_V3_1_1 = "MQTT"; // [v.3.1.1] - - // max length for client id (removed in 3.1.1) - internal const int CLIENT_ID_MAX_LENGTH = 23; - - // variable header fields - internal const byte PROTOCOL_NAME_LEN_SIZE = 2; - internal const byte PROTOCOL_NAME_V3_1_SIZE = 6; - internal const byte PROTOCOL_NAME_V3_1_1_SIZE = 4; // [v.3.1.1] - internal const byte PROTOCOL_VERSION_SIZE = 1; - internal const byte CONNECT_FLAGS_SIZE = 1; - internal const byte KEEP_ALIVE_TIME_SIZE = 2; - - internal const byte PROTOCOL_VERSION_V3_1 = 0x03; - internal const byte PROTOCOL_VERSION_V3_1_1 = 0x04; // [v.3.1.1] - internal const ushort KEEP_ALIVE_PERIOD_DEFAULT = 60; // seconds - internal const ushort MAX_KEEP_ALIVE = 65535; // 16 bit - - // connect flags - internal const byte USERNAME_FLAG_MASK = 0x80; - internal const byte USERNAME_FLAG_OFFSET = 0x07; - internal const byte USERNAME_FLAG_SIZE = 0x01; - internal const byte PASSWORD_FLAG_MASK = 0x40; - internal const byte PASSWORD_FLAG_OFFSET = 0x06; - internal const byte PASSWORD_FLAG_SIZE = 0x01; - internal const byte WILL_RETAIN_FLAG_MASK = 0x20; - internal const byte WILL_RETAIN_FLAG_OFFSET = 0x05; - internal const byte WILL_RETAIN_FLAG_SIZE = 0x01; - internal const byte WILL_QOS_FLAG_MASK = 0x18; - internal const byte WILL_QOS_FLAG_OFFSET = 0x03; - internal const byte WILL_QOS_FLAG_SIZE = 0x02; - internal const byte WILL_FLAG_MASK = 0x04; - internal const byte WILL_FLAG_OFFSET = 0x02; - internal const byte WILL_FLAG_SIZE = 0x01; - internal const byte CLEAN_SESSION_FLAG_MASK = 0x02; - internal const byte CLEAN_SESSION_FLAG_OFFSET = 0x01; - internal const byte CLEAN_SESSION_FLAG_SIZE = 0x01; - // [v.3.1.1] lsb (reserved) must be now 0 - internal const byte RESERVED_FLAG_MASK = 0x01; - internal const byte RESERVED_FLAG_OFFSET = 0x00; - internal const byte RESERVED_FLAG_SIZE = 0x01; - - #endregion - - #region Properties... - - /// - /// Protocol name - /// - public string ProtocolName - { - get { return this.protocolName; } - set { this.protocolName = value; } - } - - /// - /// Protocol version - /// - public byte ProtocolVersion - { - get { return this.protocolVersion; } - set { this.protocolVersion = value; } - } - - /// - /// Client identifier - /// - public string ClientId - { - get { return this.clientId; } - set { this.clientId = value; } - } - - /// - /// Will retain flag - /// - public bool WillRetain - { - get { return this.willRetain; } - set { this.willRetain = value; } - } - - /// - /// Will QOS level - /// - public byte WillQosLevel - { - get { return this.willQosLevel; } - set { this.willQosLevel = value; } - } - - /// - /// Will flag - /// - public bool WillFlag - { - get { return this.willFlag; } - set { this.willFlag = value; } - } - - /// - /// Will topic - /// - public string WillTopic - { - get { return this.willTopic; } - set { this.willTopic = value; } - } - - /// - /// Will message - /// - public string WillMessage - { - get { return this.willMessage; } - set { this.willMessage = value; } - } - - /// - /// Username - /// - public string Username - { - get { return this.username; } - set { this.username = value; } - } - - /// - /// Password - /// - public string Password - { - get { return this.password; } - set { this.password = value; } - } - - /// - /// Clean session flag - /// - public bool CleanSession - { - get { return this.cleanSession; } - set { this.cleanSession = value; } - } - - /// - /// Keep alive period - /// - public ushort KeepAlivePeriod - { - get { return this.keepAlivePeriod; } - set { this.keepAlivePeriod = value; } - } - - #endregion - - // protocol name - private string protocolName; - // protocol version - private byte protocolVersion; - // client identifier - private string clientId; - // will retain flag - protected bool willRetain; - // will quality of service level - protected byte willQosLevel; - // will flag - private bool willFlag; - // will topic - private string willTopic; - // will message - private string willMessage; - // username - private string username; - // password - private string password; - // clean session flag - private bool cleanSession; - // keep alive period (in sec) - private ushort keepAlivePeriod; - - /// - /// Constructor - /// - public MqttMsgConnect() - { - this.type = MQTT_MSG_CONNECT_TYPE; - } - - /// - /// Constructor - /// - /// Client identifier - public MqttMsgConnect(string clientId) : - this(clientId, null, null, false, QOS_LEVEL_AT_LEAST_ONCE, false, null, null, true, KEEP_ALIVE_PERIOD_DEFAULT, PROTOCOL_VERSION_V3_1_1) - { - } - - /// - /// Constructor - /// - /// Client identifier - /// Username - /// Password - /// Will retain flag - /// Will QOS level - /// Will flag - /// Will topic - /// Will message - /// Clean sessione flag - /// Keep alive period - /// Protocol version - public MqttMsgConnect(string clientId, - string username, - string password, - bool willRetain, - byte willQosLevel, - bool willFlag, - string willTopic, - string willMessage, - bool cleanSession, - ushort keepAlivePeriod, - byte protocolVersion - ) - { - this.type = MQTT_MSG_CONNECT_TYPE; - - this.clientId = clientId; - this.username = username; - this.password = password; - this.willRetain = willRetain; - this.willQosLevel = willQosLevel; - this.willFlag = willFlag; - this.willTopic = willTopic; - this.willMessage = willMessage; - this.cleanSession = cleanSession; - this.keepAlivePeriod = keepAlivePeriod; - // [v.3.1.1] added new protocol name and version - this.protocolVersion = protocolVersion; - this.protocolName = (this.protocolVersion == PROTOCOL_VERSION_V3_1_1) ? PROTOCOL_NAME_V3_1_1 : PROTOCOL_NAME_V3_1; - } - - /// - /// Parse bytes for a CONNECT message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// CONNECT message instance - public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel) - { - byte[] buffer; - int index = 0; - int protNameUtf8Length; - byte[] protNameUtf8; - bool isUsernameFlag; - bool isPasswordFlag; - int clientIdUtf8Length; - byte[] clientIdUtf8; - int willTopicUtf8Length; - byte[] willTopicUtf8; - int willMessageUtf8Length; - byte[] willMessageUtf8; - int usernameUtf8Length; - byte[] usernameUtf8; - int passwordUtf8Length; - byte[] passwordUtf8; - MqttMsgConnect msg = new MqttMsgConnect(); - - // get remaining length and allocate buffer - int remainingLength = MqttMsgBase.decodeRemainingLength(channel); - buffer = new byte[remainingLength]; - - // read bytes from socket... - channel.Receive(buffer); - - // protocol name - protNameUtf8Length = ((buffer[index++] << 8) & 0xFF00); - protNameUtf8Length |= buffer[index++]; - protNameUtf8 = new byte[protNameUtf8Length]; - Array.Copy(buffer, index, protNameUtf8, 0, protNameUtf8Length); - index += protNameUtf8Length; - msg.protocolName = new String(Encoding.UTF8.GetChars(protNameUtf8)); - - // [v3.1.1] wrong protocol name - if (!msg.protocolName.Equals(PROTOCOL_NAME_V3_1) && !msg.protocolName.Equals(PROTOCOL_NAME_V3_1_1)) - throw new MqttClientException(MqttClientErrorCode.InvalidProtocolName); - - // protocol version - msg.protocolVersion = buffer[index]; - index += PROTOCOL_VERSION_SIZE; - - // connect flags - // [v3.1.1] check lsb (reserved) must be 0 - if ((msg.protocolVersion == PROTOCOL_VERSION_V3_1_1) && - ((buffer[index] & RESERVED_FLAG_MASK) != 0x00)) - throw new MqttClientException(MqttClientErrorCode.InvalidConnectFlags); - - isUsernameFlag = (buffer[index] & USERNAME_FLAG_MASK) != 0x00; - isPasswordFlag = (buffer[index] & PASSWORD_FLAG_MASK) != 0x00; - msg.willRetain = (buffer[index] & WILL_RETAIN_FLAG_MASK) != 0x00; - msg.willQosLevel = (byte)((buffer[index] & WILL_QOS_FLAG_MASK) >> WILL_QOS_FLAG_OFFSET); - msg.willFlag = (buffer[index] & WILL_FLAG_MASK) != 0x00; - msg.cleanSession = (buffer[index] & CLEAN_SESSION_FLAG_MASK) != 0x00; - index += CONNECT_FLAGS_SIZE; - - // keep alive timer - msg.keepAlivePeriod = (ushort)((buffer[index++] << 8) & 0xFF00); - msg.keepAlivePeriod |= buffer[index++]; - - // client identifier [v3.1.1] it may be zero bytes long (empty string) - clientIdUtf8Length = ((buffer[index++] << 8) & 0xFF00); - clientIdUtf8Length |= buffer[index++]; - clientIdUtf8 = new byte[clientIdUtf8Length]; - Array.Copy(buffer, index, clientIdUtf8, 0, clientIdUtf8Length); - index += clientIdUtf8Length; - msg.clientId = new String(Encoding.UTF8.GetChars(clientIdUtf8)); - // [v3.1.1] if client identifier is zero bytes long, clean session must be true - if ((msg.protocolVersion == PROTOCOL_VERSION_V3_1_1) && (clientIdUtf8Length == 0) && (!msg.cleanSession)) - throw new MqttClientException(MqttClientErrorCode.InvalidClientId); - - // will topic and will message - if (msg.willFlag) - { - willTopicUtf8Length = ((buffer[index++] << 8) & 0xFF00); - willTopicUtf8Length |= buffer[index++]; - willTopicUtf8 = new byte[willTopicUtf8Length]; - Array.Copy(buffer, index, willTopicUtf8, 0, willTopicUtf8Length); - index += willTopicUtf8Length; - msg.willTopic = new String(Encoding.UTF8.GetChars(willTopicUtf8)); - - willMessageUtf8Length = ((buffer[index++] << 8) & 0xFF00); - willMessageUtf8Length |= buffer[index++]; - willMessageUtf8 = new byte[willMessageUtf8Length]; - Array.Copy(buffer, index, willMessageUtf8, 0, willMessageUtf8Length); - index += willMessageUtf8Length; - msg.willMessage = new String(Encoding.UTF8.GetChars(willMessageUtf8)); - } - - // username - if (isUsernameFlag) - { - usernameUtf8Length = ((buffer[index++] << 8) & 0xFF00); - usernameUtf8Length |= buffer[index++]; - usernameUtf8 = new byte[usernameUtf8Length]; - Array.Copy(buffer, index, usernameUtf8, 0, usernameUtf8Length); - index += usernameUtf8Length; - msg.username = new String(Encoding.UTF8.GetChars(usernameUtf8)); - } - - // password - if (isPasswordFlag) - { - passwordUtf8Length = ((buffer[index++] << 8) & 0xFF00); - passwordUtf8Length |= buffer[index++]; - passwordUtf8 = new byte[passwordUtf8Length]; - Array.Copy(buffer, index, passwordUtf8, 0, passwordUtf8Length); - index += passwordUtf8Length; - msg.password = new String(Encoding.UTF8.GetChars(passwordUtf8)); - } - - 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; - - byte[] clientIdUtf8 = Encoding.UTF8.GetBytes(this.clientId); - byte[] willTopicUtf8 = (this.willFlag && (this.willTopic != null)) ? Encoding.UTF8.GetBytes(this.willTopic) : null; - byte[] willMessageUtf8 = (this.willFlag && (this.willMessage != null)) ? Encoding.UTF8.GetBytes(this.willMessage) : null; - byte[] usernameUtf8 = ((this.username != null) && (this.username.Length > 0)) ? Encoding.UTF8.GetBytes(this.username) : null; - byte[] passwordUtf8 = ((this.password != null) && (this.password.Length > 0)) ? Encoding.UTF8.GetBytes(this.password) : null; - - // [v3.1.1] - if (this.protocolVersion == PROTOCOL_VERSION_V3_1_1) - { - // will flag set, will topic and will message MUST be present - if (this.willFlag && ((this.willQosLevel >= 0x03) || - (willTopicUtf8 == null) || (willMessageUtf8 == null) || - ((willTopicUtf8 != null) && (willTopicUtf8.Length == 0)) || - ((willMessageUtf8 != null) && (willMessageUtf8.Length == 0)))) - throw new MqttClientException(MqttClientErrorCode.WillWrong); - // willflag not set, retain must be 0 and will topic and message MUST NOT be present - else if (!this.willFlag && ((this.willRetain) || - (willTopicUtf8 != null) || (willMessageUtf8 != null) || - ((willTopicUtf8 != null) && (willTopicUtf8.Length != 0)) || - ((willMessageUtf8 != null) && (willMessageUtf8.Length != 0)))) - throw new MqttClientException(MqttClientErrorCode.WillWrong); - } - - if (this.keepAlivePeriod > MAX_KEEP_ALIVE) - throw new MqttClientException(MqttClientErrorCode.KeepAliveWrong); - - // check on will QoS Level - if ((this.willQosLevel < MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE) || - (this.willQosLevel > MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE)) - throw new MqttClientException(MqttClientErrorCode.WillWrong); - - // protocol name field size - // MQTT version 3.1 - if (this.protocolVersion == PROTOCOL_VERSION_V3_1) - { - varHeaderSize += (PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_SIZE); - } - // MQTT version 3.1.1 - else - { - varHeaderSize += (PROTOCOL_NAME_LEN_SIZE + PROTOCOL_NAME_V3_1_1_SIZE); - } - // protocol level field size - varHeaderSize += PROTOCOL_VERSION_SIZE; - // connect flags field size - varHeaderSize += CONNECT_FLAGS_SIZE; - // keep alive timer field size - varHeaderSize += KEEP_ALIVE_TIME_SIZE; - - // client identifier field size - payloadSize += clientIdUtf8.Length + 2; - // will topic field size - payloadSize += (willTopicUtf8 != null) ? (willTopicUtf8.Length + 2) : 0; - // will message field size - payloadSize += (willMessageUtf8 != null) ? (willMessageUtf8.Length + 2) : 0; - // username field size - payloadSize += (usernameUtf8 != null) ? (usernameUtf8.Length + 2) : 0; - // password field size - payloadSize += (passwordUtf8 != null) ? (passwordUtf8.Length + 2) : 0; - - 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 - buffer[index++] = (MQTT_MSG_CONNECT_TYPE << MSG_TYPE_OFFSET) | MQTT_MSG_CONNECT_FLAG_BITS; // [v.3.1.1] - - // encode remaining length - index = this.encodeRemainingLength(remainingLength, buffer, index); - - // protocol name - buffer[index++] = 0; // MSB protocol name size - // MQTT version 3.1 - if (this.protocolVersion == PROTOCOL_VERSION_V3_1) - { - buffer[index++] = PROTOCOL_NAME_V3_1_SIZE; // LSB protocol name size - Array.Copy(Encoding.UTF8.GetBytes(PROTOCOL_NAME_V3_1), 0, buffer, index, PROTOCOL_NAME_V3_1_SIZE); - index += PROTOCOL_NAME_V3_1_SIZE; - // protocol version - buffer[index++] = PROTOCOL_VERSION_V3_1; - } - // MQTT version 3.1.1 - else - { - buffer[index++] = PROTOCOL_NAME_V3_1_1_SIZE; // LSB protocol name size - Array.Copy(Encoding.UTF8.GetBytes(PROTOCOL_NAME_V3_1_1), 0, buffer, index, PROTOCOL_NAME_V3_1_1_SIZE); - index += PROTOCOL_NAME_V3_1_1_SIZE; - // protocol version - buffer[index++] = PROTOCOL_VERSION_V3_1_1; - } - - // connect flags - byte connectFlags = 0x00; - connectFlags |= (usernameUtf8 != null) ? (byte)(1 << USERNAME_FLAG_OFFSET) : (byte)0x00; - connectFlags |= (passwordUtf8 != null) ? (byte)(1 << PASSWORD_FLAG_OFFSET) : (byte)0x00; - connectFlags |= (this.willRetain) ? (byte)(1 << WILL_RETAIN_FLAG_OFFSET) : (byte)0x00; - // only if will flag is set, we have to use will QoS level (otherwise is MUST be 0) - if (this.willFlag) - connectFlags |= (byte)(this.willQosLevel << WILL_QOS_FLAG_OFFSET); - connectFlags |= (this.willFlag) ? (byte)(1 << WILL_FLAG_OFFSET) : (byte)0x00; - connectFlags |= (this.cleanSession) ? (byte)(1 << CLEAN_SESSION_FLAG_OFFSET) : (byte)0x00; - buffer[index++] = connectFlags; - - // keep alive period - buffer[index++] = (byte)((this.keepAlivePeriod >> 8) & 0x00FF); // MSB - buffer[index++] = (byte)(this.keepAlivePeriod & 0x00FF); // LSB - - // client identifier - buffer[index++] = (byte)((clientIdUtf8.Length >> 8) & 0x00FF); // MSB - buffer[index++] = (byte)(clientIdUtf8.Length & 0x00FF); // LSB - Array.Copy(clientIdUtf8, 0, buffer, index, clientIdUtf8.Length); - index += clientIdUtf8.Length; - - // will topic - if (this.willFlag && (willTopicUtf8 != null)) - { - buffer[index++] = (byte)((willTopicUtf8.Length >> 8) & 0x00FF); // MSB - buffer[index++] = (byte)(willTopicUtf8.Length & 0x00FF); // LSB - Array.Copy(willTopicUtf8, 0, buffer, index, willTopicUtf8.Length); - index += willTopicUtf8.Length; - } - - // will message - if (this.willFlag && (willMessageUtf8 != null)) - { - buffer[index++] = (byte)((willMessageUtf8.Length >> 8) & 0x00FF); // MSB - buffer[index++] = (byte)(willMessageUtf8.Length & 0x00FF); // LSB - Array.Copy(willMessageUtf8, 0, buffer, index, willMessageUtf8.Length); - index += willMessageUtf8.Length; - } - - // username - if (usernameUtf8 != null) - { - buffer[index++] = (byte)((usernameUtf8.Length >> 8) & 0x00FF); // MSB - buffer[index++] = (byte)(usernameUtf8.Length & 0x00FF); // LSB - Array.Copy(usernameUtf8, 0, buffer, index, usernameUtf8.Length); - index += usernameUtf8.Length; - } - - // password - if (passwordUtf8 != null) - { - buffer[index++] = (byte)((passwordUtf8.Length >> 8) & 0x00FF); // MSB - buffer[index++] = (byte)(passwordUtf8.Length & 0x00FF); // LSB - Array.Copy(passwordUtf8, 0, buffer, index, passwordUtf8.Length); - index += passwordUtf8.Length; - } - - return buffer; - } - - public override string ToString() - { -#if TRACE - return this.GetTraceString( - "CONNECT", - new object[] { "protocolName", "protocolVersion", "clientId", "willFlag", "willRetain", "willQosLevel", "willTopic", "willMessage", "username", "password", "cleanSession", "keepAlivePeriod" }, - new object[] { this.protocolName, this.protocolVersion, this.clientId, this.willFlag, this.willRetain, this.willQosLevel, this.willTopic, this.willMessage, this.username, this.password, this.cleanSession, this.keepAlivePeriod }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgConnectEventArgs.cs b/mqtt/M2Mqtt/Messages/MqttMsgConnectEventArgs.cs deleted file mode 100644 index ce0b3fe..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgConnectEventArgs.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) -using System; -#else -using Microsoft.SPOT; -#endif - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Event Args class for CONNECT message received from client - /// - public class MqttMsgConnectEventArgs : EventArgs - { - /// - /// Message received from client - /// - public MqttMsgConnect Message { get; private set; } - - /// - /// Constructor - /// - /// CONNECT message received from client - public MqttMsgConnectEventArgs(MqttMsgConnect connect) - { - this.Message = connect; - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgContext.cs b/mqtt/M2Mqtt/Messages/MqttMsgContext.cs deleted file mode 100644 index a2850d7..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgContext.cs +++ /dev/null @@ -1,159 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using System.Text; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Context for MQTT message - /// - public class MqttMsgContext - { - /// - /// MQTT message - /// - public MqttMsgBase Message { get; set; } - - /// - /// MQTT message state - /// - public MqttMsgState State { get; set; } - - /// - /// Flow of the message - /// - public MqttMsgFlow Flow { get; set; } - - /// - /// Timestamp in ticks (for retry) - /// - public int Timestamp { get; set; } - - /// - /// Attempt (for retry) - /// - public int Attempt { get; set; } - - /// - /// Unique key - /// - public string Key - { - get { return this.Flow + "_" + this.Message.MessageId; } - } - } - - /// - /// Flow of the message - /// - public enum MqttMsgFlow - { - /// - /// To publish to subscribers - /// - ToPublish, - - /// - /// To acknowledge to publisher - /// - ToAcknowledge - } - - /// - /// MQTT message state - /// - public enum MqttMsgState - { - /// - /// QOS = 0, Message queued - /// - QueuedQos0, - - /// - /// QOS = 1, Message queued - /// - QueuedQos1, - - /// - /// QOS = 2, Message queued - /// - QueuedQos2, - - /// - /// QOS = 1, PUBLISH sent, wait for PUBACK - /// - WaitForPuback, - - /// - /// QOS = 2, PUBLISH sent, wait for PUBREC - /// - WaitForPubrec, - - /// - /// QOS = 2, PUBREC sent, wait for PUBREL - /// - WaitForPubrel, - - /// - /// QOS = 2, PUBREL sent, wait for PUBCOMP - /// - WaitForPubcomp, - - /// - /// QOS = 2, start first phase handshake send PUBREC - /// - SendPubrec, - - /// - /// QOS = 2, start second phase handshake send PUBREL - /// - SendPubrel, - - /// - /// QOS = 2, end second phase handshake send PUBCOMP - /// - SendPubcomp, - - /// - /// QOS = 1, PUBLISH received, send PUBACK - /// - SendPuback, - - // [v3.1.1] SUBSCRIBE isn't "officially" QOS = 1 - /// - /// Send SUBSCRIBE message - /// - SendSubscribe, - - // [v3.1.1] UNSUBSCRIBE isn't "officially" QOS = 1 - /// - /// Send UNSUBSCRIBE message - /// - SendUnsubscribe, - - /// - /// (QOS = 1), SUBSCRIBE sent, wait for SUBACK - /// - WaitForSuback, - - /// - /// (QOS = 1), UNSUBSCRIBE sent, wait for UNSUBACK - /// - WaitForUnsuback - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgDisconnect.cs b/mqtt/M2Mqtt/Messages/MqttMsgDisconnect.cs deleted file mode 100644 index d918473..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgDisconnect.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for DISCONNECT message from client to broker - /// - public class MqttMsgDisconnect : MqttMsgBase - { - /// - /// Constructor - /// - public MqttMsgDisconnect() - { - this.type = MQTT_MSG_DISCONNECT_TYPE; - } - - /// - /// Parse bytes for a DISCONNECT message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// DISCONNECT message instance - 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() - { -#if TRACE - return this.GetTraceString( - "DISCONNECT", - null, - null); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgPingReq.cs b/mqtt/M2Mqtt/Messages/MqttMsgPingReq.cs deleted file mode 100644 index b46bdb6..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgPingReq.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for PINGREQ message from client to broker - /// - public class MqttMsgPingReq : MqttMsgBase - { - /// - /// Constructor - /// - 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; - } - - /// - /// Parse bytes for a PINGREQ message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// PINGREQ message instance - 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() - { -#if TRACE - return this.GetTraceString( - "PINGREQ", - null, - null); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgPingResp.cs b/mqtt/M2Mqtt/Messages/MqttMsgPingResp.cs deleted file mode 100644 index 2b028b9..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgPingResp.cs +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for PINGRESP message from client to broker - /// - public class MqttMsgPingResp : MqttMsgBase - { - /// - /// Constructor - /// - public MqttMsgPingResp() - { - this.type = MQTT_MSG_PINGRESP_TYPE; - } - - /// - /// Parse bytes for a PINGRESP message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// PINGRESP message instance - 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() - { -#if TRACE - return this.GetTraceString( - "PINGRESP", - null, - null); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgPuback.cs b/mqtt/M2Mqtt/Messages/MqttMsgPuback.cs deleted file mode 100644 index e00e37f..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgPuback.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for PUBACK message from broker to client - /// - public class MqttMsgPuback : MqttMsgBase - { - /// - /// Constructor - /// - 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; - } - - /// - /// Parse bytes for a PUBACK message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// PUBACK message instance - 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() - { -#if TRACE - return this.GetTraceString( - "PUBACK", - new object[] { "messageId" }, - new object[] { this.messageId }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgPubcomp.cs b/mqtt/M2Mqtt/Messages/MqttMsgPubcomp.cs deleted file mode 100644 index eeabd3b..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgPubcomp.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for PUBCOMP message from broker to client - /// - public class MqttMsgPubcomp : MqttMsgBase - { - /// - /// Constructor - /// - 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; - } - - /// - /// Parse bytes for a PUBCOMP message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// PUBCOMP message instance - 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() - { -#if TRACE - return this.GetTraceString( - "PUBCOMP", - new object[] { "messageId" }, - new object[] { this.messageId }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgPublish.cs b/mqtt/M2Mqtt/Messages/MqttMsgPublish.cs deleted file mode 100644 index 0809af9..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgPublish.cs +++ /dev/null @@ -1,249 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using System.Text; -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages { - /// - /// Class for PUBLISH message from client to broker - /// - public class MqttMsgPublish : MqttMsgBase { - #region Properties... - - /// - /// Message topic - /// - public String Topic { get; set; } - - /// - /// Message data - /// - public Byte[] Message { get; set; } - - #endregion - - /// - /// Constructor - /// - public MqttMsgPublish() { - this.type = MQTT_MSG_PUBLISH_TYPE; - } - - /// - /// Constructor - /// - /// Message topic - /// Message data - public MqttMsgPublish(String topic, Byte[] message) : this(topic, message, false, QOS_LEVEL_AT_MOST_ONCE, false) { - } - - /// - /// Constructor - /// - /// Message topic - /// Message data - /// Duplicate flag - /// Quality of Service level - /// Retain flag - public MqttMsgPublish(String topic, Byte[] message, Boolean dupFlag, Byte qosLevel, Boolean retain) : base() { - this.type = MQTT_MSG_PUBLISH_TYPE; - this.Topic = topic; - this.Message = message; - 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; - Byte[] buffer; - Int32 index = 0; - - // topic can't contain wildcards - 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)) { - throw new MqttClientException(MqttClientErrorCode.TopicLength); - } - - // check wrong QoS level (both bits can't be set 1) - if (this.qosLevel > QOS_LEVEL_EXACTLY_ONCE) { - throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); - } - - Byte[] topicUtf8 = Encoding.UTF8.GetBytes(this.Topic); - - // topic name - 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)) { - varHeaderSize += MESSAGE_ID_SIZE; - } - - // check on message with zero length - if (this.Message != null) { - // message data - payloadSize += this.Message.Length; - } - - remainingLength += (varHeaderSize + payloadSize); - - // first byte of fixed header - 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; - } 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; - index++; - - // encode remaining length - index = this.encodeRemainingLength(remainingLength, buffer, index); - - // topic name - buffer[index++] = (Byte)((topicUtf8.Length >> 8) & 0x00FF); // MSB - buffer[index++] = (Byte)(topicUtf8.Length & 0x00FF); // LSB - Array.Copy(topicUtf8, 0, buffer, index, topicUtf8.Length); - 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)) { - // 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 - } - - // 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; - } - - return buffer; - } - - /// - /// Parse bytes for a PUBLISH message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// PUBLISH message instance - public static MqttMsgPublish Parse(Byte fixedHeaderFirstByte, Byte protocolVersion, IMqttNetworkChannel channel) { - Byte[] buffer; - Int32 index = 0; - Byte[] topicUtf8; - Int32 topicUtf8Length; - MqttMsgPublish msg = new MqttMsgPublish(); - - // get remaining length and allocate buffer - 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++]; - topicUtf8 = new Byte[topicUtf8Length]; - Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length); - index += topicUtf8Length; - msg.Topic = new String(Encoding.UTF8.GetChars(topicUtf8)); - - // read QoS level from fixed header - 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) { - throw new MqttClientException(MqttClientErrorCode.QosNotAllowed); - } - // read DUP flag from fixed header - 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); - - // 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)) { - // message id - msg.messageId = (UInt16)((buffer[index++] << 8) & 0xFF00); - msg.messageId |= (buffer[index++]); - } - - // get payload with message data - Int32 messageSize = remainingLength - index; - Int32 remaining = messageSize; - Int32 messageOffset = 0; - msg.Message = new Byte[messageSize]; - - // BUG FIX 26/07/2013 : receiving large payload - - // copy first part of payload data received - Array.Copy(buffer, index, msg.Message, messageOffset, received - index); - remaining -= (received - index); - messageOffset += (received - index); - - // if payload isn't finished - while (remaining > 0) { - // receive other payload data - received = channel.Receive(buffer); - Array.Copy(buffer, 0, msg.Message, messageOffset, received); - remaining -= received; - messageOffset += received; - } - - return msg; - } - - public override String ToString() { -#if TRACE - return this.GetTraceString( - "PUBLISH", - new Object[] { "messageId", "topic", "message" }, - new Object[] { this.messageId, this.Topic, this.Message }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgPublishEventArgs.cs b/mqtt/M2Mqtt/Messages/MqttMsgPublishEventArgs.cs deleted file mode 100644 index efb2333..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgPublishEventArgs.cs +++ /dev/null @@ -1,111 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) -using System; -#else -using Microsoft.SPOT; -#endif - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Event Args class for PUBLISH message received from broker - /// - public class MqttMsgPublishEventArgs : EventArgs - { - #region Properties... - - /// - /// Message topic - /// - public string Topic - { - get { return this.topic; } - internal set { this.topic = value; } - } - - /// - /// Message data - /// - public byte[] Message - { - get { return this.message; } - internal set { this.message = value; } - } - - /// - /// Duplicate message flag - /// - public bool DupFlag - { - get { return this.dupFlag; } - set { this.dupFlag = value; } - } - - /// - /// Quality of Service level - /// - public byte QosLevel - { - get { return this.qosLevel; } - internal set { this.qosLevel = value; } - } - - /// - /// Retain message flag - /// - 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; - - /// - /// Constructor - /// - /// Message topic - /// Message data - /// Duplicate delivery flag - /// Quality of Service level - /// Retain flag - 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; - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgPublishedEventArgs.cs b/mqtt/M2Mqtt/Messages/MqttMsgPublishedEventArgs.cs deleted file mode 100644 index e507c38..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgPublishedEventArgs.cs +++ /dev/null @@ -1,78 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) -using System; -#else -using Microsoft.SPOT; -#endif - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Event Args class for published message - /// - public class MqttMsgPublishedEventArgs : EventArgs - { - #region Properties... - - /// - /// Message identifier - /// - public ushort MessageId - { - get { return this.messageId; } - internal set { this.messageId = value; } - } - - /// - /// Message published (or failed due to retries) - /// - public bool IsPublished - { - get { return this.isPublished; } - internal set { this.isPublished = value; } - } - - #endregion - - // message identifier - ushort messageId; - - // published flag - bool isPublished; - - /// - /// Constructor (published message) - /// - /// Message identifier published - public MqttMsgPublishedEventArgs(ushort messageId) - : this(messageId, true) - { - } - - /// - /// Constructor - /// - /// Message identifier - /// Publish flag - public MqttMsgPublishedEventArgs(ushort messageId, bool isPublished) - { - this.messageId = messageId; - this.isPublished = isPublished; - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgPubrec.cs b/mqtt/M2Mqtt/Messages/MqttMsgPubrec.cs deleted file mode 100644 index 1855bf9..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgPubrec.cs +++ /dev/null @@ -1,125 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for PUBREC message from broker to client - /// - public class MqttMsgPubrec : MqttMsgBase - { - /// - /// Constructor - /// - 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; - } - - /// - /// Parse bytes for a PUBREC message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// PUBREC message instance - 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() - { -#if TRACE - return this.GetTraceString( - "PUBREC", - new object[] { "messageId" }, - new object[] { this.messageId }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgPubrel.cs b/mqtt/M2Mqtt/Messages/MqttMsgPubrel.cs deleted file mode 100644 index e43ca91..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgPubrel.cs +++ /dev/null @@ -1,142 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for PUBREL message from client top broker - /// - public class MqttMsgPubrel : MqttMsgBase - { - /// - /// Constructor - /// - 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; - } - - /// - /// Parse bytes for a PUBREL message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// PUBREL message instance - 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() - { -#if TRACE - return this.GetTraceString( - "PUBREL", - new object[] { "messageId" }, - new object[] { this.messageId }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgSuback.cs b/mqtt/M2Mqtt/Messages/MqttMsgSuback.cs deleted file mode 100644 index 6ecfd0d..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgSuback.cs +++ /dev/null @@ -1,162 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for SUBACK message from broker to client - /// - public class MqttMsgSuback : MqttMsgBase - { - #region Properties... - - /// - /// List of granted QOS Levels - /// - public byte[] GrantedQoSLevels - { - get { return this.grantedQosLevels; } - set { this.grantedQosLevels = value; } - } - - #endregion - - // granted QOS levels - byte[] grantedQosLevels; - - /// - /// Constructor - /// - public MqttMsgSuback() - { - this.type = MQTT_MSG_SUBACK_TYPE; - } - - /// - /// Parse bytes for a SUBACK message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// SUBACK message instance - 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() - { -#if TRACE - return this.GetTraceString( - "SUBACK", - new object[] { "messageId", "grantedQosLevels" }, - new object[] { this.messageId, this.grantedQosLevels }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgSubscribe.cs b/mqtt/M2Mqtt/Messages/MqttMsgSubscribe.cs deleted file mode 100644 index 0e3927e..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgSubscribe.cs +++ /dev/null @@ -1,272 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -// if NOT .Net Micro Framework -#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 -{ - /// - /// Class for SUBSCRIBE message from client to broker - /// - public class MqttMsgSubscribe : MqttMsgBase - { - #region Properties... - - /// - /// List of topics to subscribe - /// - public string[] Topics - { - get { return this.topics; } - set { this.topics = value; } - } - - /// - /// List of QOS Levels related to topics - /// - public byte[] QoSLevels - { - get { return this.qosLevels; } - set { this.qosLevels = value; } - } - - #endregion - - // topics to subscribe - string[] topics; - // QOS levels related to topics - byte[] qosLevels; - - /// - /// Constructor - /// - public MqttMsgSubscribe() - { - this.type = MQTT_MSG_SUBSCRIBE_TYPE; - } - - /// - /// Constructor - /// - /// List of topics to subscribe - /// List of QOS Levels related to topics - 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; - } - - /// - /// Parse bytes for a SUBSCRIBE message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// SUBSCRIBE message instance - 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) - IList tmpTopics = new ArrayList(); - IList tmpQosLevels = new ArrayList(); -// else other frameworks (.Net, .Net Compact, Mono, Windows Phone) -#else - IList tmpTopics = new List(); - IList tmpQosLevels = new List(); -#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() - { -#if TRACE - return this.GetTraceString( - "SUBSCRIBE", - new object[] { "messageId", "topics", "qosLevels" }, - new object[] { this.messageId, this.topics, this.qosLevels }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgSubscribeEventArgs.cs b/mqtt/M2Mqtt/Messages/MqttMsgSubscribeEventArgs.cs deleted file mode 100644 index 91c85f9..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgSubscribeEventArgs.cs +++ /dev/null @@ -1,81 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) -using System; -#else -using Microsoft.SPOT; -#endif - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Event Args class for subscribe request on topics - /// - public class MqttMsgSubscribeEventArgs : EventArgs - { - #region Properties... - - /// - /// Message identifier - /// - public ushort MessageId - { - get { return this.messageId; } - internal set { this.messageId = value; } - } - - /// - /// Topics requested to subscribe - /// - public string[] Topics - { - get { return this.topics; } - internal set { this.topics = value; } - } - - /// - /// List of QOS Levels requested - /// - 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; - - /// - /// Constructor - /// - /// Message identifier for subscribe topics request - /// Topics requested to subscribe - /// List of QOS Levels requested - public MqttMsgSubscribeEventArgs(ushort messageId, string[] topics, byte[] qosLevels) - { - this.messageId = messageId; - this.topics = topics; - this.qosLevels = qosLevels; - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgSubscribedEventArgs.cs b/mqtt/M2Mqtt/Messages/MqttMsgSubscribedEventArgs.cs deleted file mode 100644 index 58bbb22..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgSubscribedEventArgs.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) -using System; -#else -using Microsoft.SPOT; -#endif - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Event Args class for subscribed topics - /// - public class MqttMsgSubscribedEventArgs : EventArgs - { - #region Properties... - - /// - /// Message identifier - /// - public ushort MessageId - { - get { return this.messageId; } - internal set { this.messageId = value; } - } - - /// - /// List of granted QOS Levels - /// - public byte[] GrantedQoSLevels - { - get { return this.grantedQosLevels; } - internal set { this.grantedQosLevels = value; } - } - - #endregion - - // message identifier - ushort messageId; - // granted QOS levels - byte[] grantedQosLevels; - - /// - /// Constructor - /// - /// Message identifier for subscribed topics - /// List of granted QOS Levels - public MqttMsgSubscribedEventArgs(ushort messageId, byte[] grantedQosLevels) - { - this.messageId = messageId; - this.grantedQosLevels = grantedQosLevels; - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgUnsuback.cs b/mqtt/M2Mqtt/Messages/MqttMsgUnsuback.cs deleted file mode 100644 index 8e49a06..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgUnsuback.cs +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using uPLibrary.Networking.M2Mqtt.Exceptions; - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Class for UNSUBACK message from broker to client - /// - public class MqttMsgUnsuback : MqttMsgBase - { - /// - /// Constructor - /// - public MqttMsgUnsuback() - { - this.type = MQTT_MSG_UNSUBACK_TYPE; - } - - /// - /// Parse bytes for a UNSUBACK message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// UNSUBACK message instance - 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() - { -#if TRACE - return this.GetTraceString( - "UNSUBACK", - new object[] { "messageId" }, - new object[] { this.messageId }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgUnsubscribe.cs b/mqtt/M2Mqtt/Messages/MqttMsgUnsubscribe.cs deleted file mode 100644 index e485133..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgUnsubscribe.cs +++ /dev/null @@ -1,239 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -// if NOT .Net Micro Framework -#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 -{ - /// - /// Class for UNSUBSCRIBE message from client to broker - /// - public class MqttMsgUnsubscribe : MqttMsgBase - { - #region Properties... - - /// - /// List of topics to unsubscribe - /// - public string[] Topics - { - get { return this.topics; } - set { this.topics = value; } - } - - #endregion - - // topics to unsubscribe - string[] topics; - - /// - /// Constructor - /// - public MqttMsgUnsubscribe() - { - this.type = MQTT_MSG_UNSUBSCRIBE_TYPE; - } - - /// - /// Constructor - /// - /// List of topics to unsubscribe - 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; - } - - /// - /// Parse bytes for a UNSUBSCRIBE message - /// - /// First fixed header byte - /// Protocol Version - /// Channel connected to the broker - /// UNSUBSCRIBE message instance - 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) - IList tmpTopics = new ArrayList(); -// else other frameworks (.Net, .Net Compact, Mono, Windows Phone) -#else - IList tmpTopics = new List(); -#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() - { -#if TRACE - return this.GetTraceString( - "UNSUBSCRIBE", - new object[] { "messageId", "topics" }, - new object[] { this.messageId, this.topics }); -#else - return base.ToString(); -#endif - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgUnsubscribeEventArgs.cs b/mqtt/M2Mqtt/Messages/MqttMsgUnsubscribeEventArgs.cs deleted file mode 100644 index e158783..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgUnsubscribeEventArgs.cs +++ /dev/null @@ -1,68 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) -using System; -#else -using Microsoft.SPOT; -#endif - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Event Args class for unsubscribe request on topics - /// - public class MqttMsgUnsubscribeEventArgs : EventArgs - { - #region Properties... - - /// - /// Message identifier - /// - public ushort MessageId - { - get { return this.messageId; } - internal set { this.messageId = value; } - } - - /// - /// Topics requested to subscribe - /// - public string[] Topics - { - get { return this.topics; } - internal set { this.topics = value; } - } - - #endregion - - // message identifier - ushort messageId; - // topics requested to unsubscribe - string[] topics; - - /// - /// Constructor - /// - /// Message identifier for subscribed topics - /// Topics requested to subscribe - public MqttMsgUnsubscribeEventArgs(ushort messageId, string[] topics) - { - this.messageId = messageId; - this.topics = topics; - } - } -} diff --git a/mqtt/M2Mqtt/Messages/MqttMsgUnsubscribedEventArgs.cs b/mqtt/M2Mqtt/Messages/MqttMsgUnsubscribedEventArgs.cs deleted file mode 100644 index e65c383..0000000 --- a/mqtt/M2Mqtt/Messages/MqttMsgUnsubscribedEventArgs.cs +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) -using System; -#else -using Microsoft.SPOT; -#endif - -namespace uPLibrary.Networking.M2Mqtt.Messages -{ - /// - /// Event Args class for unsubscribed topic - /// - public class MqttMsgUnsubscribedEventArgs : EventArgs - { - #region Properties... - - /// - /// Message identifier - /// - public ushort MessageId - { - get { return this.messageId; } - internal set { this.messageId = value; } - } - - #endregion - - // message identifier - ushort messageId; - - /// - /// Constructor - /// - /// Message identifier for unsubscribed topic - public MqttMsgUnsubscribedEventArgs(ushort messageId) - { - this.messageId = messageId; - } - } -} diff --git a/mqtt/M2Mqtt/MqttClient.cs b/mqtt/M2Mqtt/MqttClient.cs deleted file mode 100644 index 6daf7a2..0000000 --- a/mqtt/M2Mqtt/MqttClient.cs +++ /dev/null @@ -1,2632 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using System.Net; -#if !(WINDOWS_APP || WINDOWS_PHONE_APP) -using System.Net.Sockets; -using System.Security.Cryptography.X509Certificates; -#endif -using System.Threading; -using uPLibrary.Networking.M2Mqtt.Exceptions; -using uPLibrary.Networking.M2Mqtt.Messages; -using uPLibrary.Networking.M2Mqtt.Session; -using uPLibrary.Networking.M2Mqtt.Utility; -using uPLibrary.Networking.M2Mqtt.Internal; -// if .Net Micro Framework -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3) -using Microsoft.SPOT; -#if SSL -using Microsoft.SPOT.Net.Security; -#endif -// else other frameworks (.Net, .Net Compact, Mono, Windows Phone) -#else -using System.Collections.Generic; -#if (SSL && !(WINDOWS_APP || WINDOWS_PHONE_APP)) -using System.Security.Authentication; -using System.Net.Security; -#endif -#endif - -#if (WINDOWS_APP || WINDOWS_PHONE_APP) -using Windows.Networking.Sockets; -#endif - -using System.Collections; - -// alias needed due to Microsoft.SPOT.Trace in .Net Micro Framework -// (it's ambiguos with uPLibrary.Networking.M2Mqtt.Utility.Trace) -using MqttUtility = uPLibrary.Networking.M2Mqtt.Utility; -using System.IO; -//using System.Net.Security; - -namespace uPLibrary.Networking.M2Mqtt -{ - /// - /// MQTT Client - /// - public class MqttClient - { -#if BROKER - #region Constants ... - - // thread names - private const string RECEIVE_THREAD_NAME = "ReceiveThread"; - private const string RECEIVE_EVENT_THREAD_NAME = "DispatchEventThread"; - private const string PROCESS_INFLIGHT_THREAD_NAME = "ProcessInflightThread"; - private const string KEEP_ALIVE_THREAD = "KeepAliveThread"; - - #endregion -#endif - - /// - /// Delagate that defines event handler for PUBLISH message received - /// - public delegate void MqttMsgPublishEventHandler(object sender, MqttMsgPublishEventArgs e); - - /// - /// Delegate that defines event handler for published message - /// - public delegate void MqttMsgPublishedEventHandler(object sender, MqttMsgPublishedEventArgs e); - - /// - /// Delagate that defines event handler for subscribed topic - /// - public delegate void MqttMsgSubscribedEventHandler(object sender, MqttMsgSubscribedEventArgs e); - - /// - /// Delagate that defines event handler for unsubscribed topic - /// - public delegate void MqttMsgUnsubscribedEventHandler(object sender, MqttMsgUnsubscribedEventArgs e); - -#if BROKER - /// - /// Delagate that defines event handler for SUBSCRIBE message received - /// - public delegate void MqttMsgSubscribeEventHandler(object sender, MqttMsgSubscribeEventArgs e); - - /// - /// Delagate that defines event handler for UNSUBSCRIBE message received - /// - public delegate void MqttMsgUnsubscribeEventHandler(object sender, MqttMsgUnsubscribeEventArgs e); - - /// - /// Delagate that defines event handler for CONNECT message received - /// - public delegate void MqttMsgConnectEventHandler(object sender, MqttMsgConnectEventArgs e); - - /// - /// Delegate that defines event handler for client disconnection (DISCONNECT message or not) - /// - public delegate void MqttMsgDisconnectEventHandler(object sender, EventArgs e); -#endif - - /// - /// Delegate that defines event handler for cliet/peer disconnection - /// - public delegate void ConnectionClosedEventHandler(object sender, EventArgs e); - - // broker hostname (or ip address) and port - private string brokerHostName; - private int brokerPort; - - // running status of threads - private bool isRunning; - // event for raising received message event - private AutoResetEvent receiveEventWaitHandle; - - // event for starting process inflight queue asynchronously - private AutoResetEvent inflightWaitHandle; - - // event for signaling synchronous receive - AutoResetEvent syncEndReceiving; - // message received - MqttMsgBase msgReceived; - - // exeption thrown during receiving - Exception exReceiving; - - // keep alive period (in ms) - private int keepAlivePeriod; - // events for signaling on keep alive thread - private AutoResetEvent keepAliveEvent; - private AutoResetEvent keepAliveEventEnd; - // last communication time in ticks - private int lastCommTime; - - // event for PUBLISH message received - public event MqttMsgPublishEventHandler MqttMsgPublishReceived; - // event for published message - public event MqttMsgPublishedEventHandler MqttMsgPublished; - // event for subscribed topic - public event MqttMsgSubscribedEventHandler MqttMsgSubscribed; - // event for unsubscribed topic - public event MqttMsgUnsubscribedEventHandler MqttMsgUnsubscribed; -#if BROKER - // event for SUBSCRIBE message received - public event MqttMsgSubscribeEventHandler MqttMsgSubscribeReceived; - // event for USUBSCRIBE message received - public event MqttMsgUnsubscribeEventHandler MqttMsgUnsubscribeReceived; - // event for CONNECT message received - public event MqttMsgConnectEventHandler MqttMsgConnected; - // event for DISCONNECT message received - public event MqttMsgDisconnectEventHandler MqttMsgDisconnected; -#endif - - // event for peer/client disconnection - public event ConnectionClosedEventHandler ConnectionClosed; - - // channel to communicate over the network - private IMqttNetworkChannel channel; - - // inflight messages queue - private Queue inflightQueue; - // internal queue for received messages about inflight messages - private Queue internalQueue; - // internal queue for dispatching events - private Queue eventQueue; - // session - private MqttClientSession session; - - // reference to avoid access to singleton via property - private MqttSettings settings; - - // current message identifier generated - private ushort messageIdCounter = 0; - - // connection is closing due to peer - private bool isConnectionClosing; - - /// - /// Connection status between client and broker - /// - public bool IsConnected { get; private set; } - - /// - /// Client identifier - /// - public string ClientId { get; private set; } - - /// - /// Clean session flag - /// - public bool CleanSession { get; private set; } - - /// - /// Will flag - /// - public bool WillFlag { get; private set; } - - /// - /// Will QOS level - /// - public byte WillQosLevel { get; private set; } - - /// - /// Will topic - /// - public string WillTopic { get; private set; } - - /// - /// Will message - /// - public string WillMessage { get; private set; } - - /// - /// MQTT protocol version - /// - public MqttProtocolVersion ProtocolVersion { get; set; } - -#if BROKER - /// - /// MQTT Client Session - /// - public MqttClientSession Session - { - get { return this.session; } - set { this.session = value; } - } -#endif - - /// - /// MQTT client settings - /// - public MqttSettings Settings - { - get { return this.settings; } - } - -#if !(WINDOWS_APP || WINDOWS_PHONE_APP) - /// - /// Constructor - /// - /// Broker IP address - [Obsolete("Use this ctor MqttClient(string brokerHostName) insted")] - public MqttClient(IPAddress brokerIpAddress) : - this(brokerIpAddress, MqttSettings.MQTT_BROKER_DEFAULT_PORT, false, null, null, MqttSslProtocols.None) - { - } - - /// - /// Constructor - /// - /// Broker IP address - /// Broker port - /// Using secure connection - /// CA certificate for secure connection - /// Client certificate - /// SSL/TLS protocol version - [Obsolete("Use this ctor MqttClient(string brokerHostName, int brokerPort, bool secure, X509Certificate caCert) insted")] - public MqttClient(IPAddress brokerIpAddress, int brokerPort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol) - { -#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - this.Init(brokerIpAddress.ToString(), brokerPort, secure, caCert, clientCert, sslProtocol, null, null); -#else - this.Init(brokerIpAddress.ToString(), brokerPort, secure, caCert, clientCert, sslProtocol); -#endif - } -#endif - - /// - /// Constructor - /// - /// Broker Host Name or IP Address - public MqttClient(string brokerHostName) : -#if !(WINDOWS_APP || WINDOWS_PHONE_APP) - this(brokerHostName, MqttSettings.MQTT_BROKER_DEFAULT_PORT, false, null, null, MqttSslProtocols.None) -#else - this(brokerHostName, MqttSettings.MQTT_BROKER_DEFAULT_PORT, false, MqttSslProtocols.None) -#endif - { - } - - /// - /// Constructor - /// - /// Broker Host Name or IP Address - /// Broker port - /// Using secure connection - /// SSL/TLS protocol version -#if !(WINDOWS_APP || WINDOWS_PHONE_APP) - /// CA certificate for secure connection - /// Client certificate - public MqttClient(string brokerHostName, int brokerPort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol) -#else - public MqttClient(string brokerHostName, int brokerPort, bool secure, MqttSslProtocols sslProtocol) -#endif - { -#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK || WINDOWS_APP || WINDOWS_PHONE_APP) - this.Init(brokerHostName, brokerPort, secure, caCert, clientCert, sslProtocol, null, null); -#elif (WINDOWS_APP || WINDOWS_PHONE_APP) - this.Init(brokerHostName, brokerPort, secure, sslProtocol); -#else - this.Init(brokerHostName, brokerPort, secure, caCert, clientCert, sslProtocol); -#endif - } - - -#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK || WINDOWS_APP || WINDOWS_PHONE_APP) - - /// - /// Constructor - /// - /// Broker Host Name or IP Address - /// Broker port - /// Using secure connection - /// CA certificate for secure connection - /// Client certificate - /// SSL/TLS protocol version - /// A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party - public MqttClient(string brokerHostName, int brokerPort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol, - RemoteCertificateValidationCallback userCertificateValidationCallback) - : this(brokerHostName, brokerPort, secure, caCert, clientCert, sslProtocol, userCertificateValidationCallback, null) - { - } - - /// - /// Constructor - /// - /// Broker Host Name or IP Address - /// Broker port - /// Using secure connection - /// SSL/TLS protocol version - /// A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party - /// A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication - public MqttClient(string brokerHostName, int brokerPort, bool secure, MqttSslProtocols sslProtocol, - RemoteCertificateValidationCallback userCertificateValidationCallback, - LocalCertificateSelectionCallback userCertificateSelectionCallback) - : this(brokerHostName, brokerPort, secure, null, null, sslProtocol, userCertificateValidationCallback, userCertificateSelectionCallback) - { - } - - /// - /// Constructor - /// - /// Broker Host Name or IP Address - /// Broker port - /// Using secure connection - /// CA certificate for secure connection - /// Client certificate - /// SSL/TLS protocol version - /// A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party - /// A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication - public MqttClient(string brokerHostName, int brokerPort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol, - RemoteCertificateValidationCallback userCertificateValidationCallback, - LocalCertificateSelectionCallback userCertificateSelectionCallback) - { - this.Init(brokerHostName, brokerPort, secure, caCert, clientCert, sslProtocol, userCertificateValidationCallback, userCertificateSelectionCallback); - } -#endif - -#if BROKER - /// - /// Constructor - /// - /// Network channel for communication - public MqttClient(IMqttNetworkChannel channel) - { - // set default MQTT protocol version (default is 3.1.1) - this.ProtocolVersion = MqttProtocolVersion.Version_3_1_1; - - this.channel = channel; - - // reference to MQTT settings - this.settings = MqttSettings.Instance; - - // client not connected yet (CONNACK not send from client), some default values - this.IsConnected = false; - this.ClientId = null; - this.CleanSession = true; - - this.keepAliveEvent = new AutoResetEvent(false); - - // queue for handling inflight messages (publishing and acknowledge) - this.inflightWaitHandle = new AutoResetEvent(false); - this.inflightQueue = new Queue(); - - // queue for received message - this.receiveEventWaitHandle = new AutoResetEvent(false); - this.eventQueue = new Queue(); - this.internalQueue = new Queue(); - - // session - this.session = null; - } -#endif - - /// - /// MqttClient initialization - /// - /// Broker Host Name or IP Address - /// Broker port - /// >Using secure connection - /// CA certificate for secure connection - /// Client certificate - /// SSL/TLS protocol version -#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK || WINDOWS_APP || WINDOWS_PHONE_APP) - /// A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party - /// A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication - private void Init(string brokerHostName, int brokerPort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol, - RemoteCertificateValidationCallback userCertificateValidationCallback, - LocalCertificateSelectionCallback userCertificateSelectionCallback) -#elif (WINDOWS_APP || WINDOWS_PHONE_APP) - private void Init(string brokerHostName, int brokerPort, bool secure, MqttSslProtocols sslProtocol) -#else - private void Init(string brokerHostName, int brokerPort, bool secure, X509Certificate caCert, X509Certificate clientCert, MqttSslProtocols sslProtocol) -#endif - { - // set default MQTT protocol version (default is 3.1.1) - this.ProtocolVersion = MqttProtocolVersion.Version_3_1_1; -#if !SSL - // check security parameters - if (secure) - throw new ArgumentException("Library compiled without SSL support"); -#endif - - this.brokerHostName = brokerHostName; - this.brokerPort = brokerPort; - - // reference to MQTT settings - this.settings = MqttSettings.Instance; - // set settings port based on secure connection or not - if (!secure) - this.settings.Port = this.brokerPort; - else - this.settings.SslPort = this.brokerPort; - - this.syncEndReceiving = new AutoResetEvent(false); - this.keepAliveEvent = new AutoResetEvent(false); - - // queue for handling inflight messages (publishing and acknowledge) - this.inflightWaitHandle = new AutoResetEvent(false); - this.inflightQueue = new Queue(); - - // queue for received message - this.receiveEventWaitHandle = new AutoResetEvent(false); - this.eventQueue = new Queue(); - this.internalQueue = new Queue(); - - // session - this.session = null; - - // create network channel -#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK || WINDOWS_APP || WINDOWS_PHONE_APP) - this.channel = new MqttNetworkChannel(this.brokerHostName, this.brokerPort, secure, caCert, clientCert, sslProtocol, userCertificateValidationCallback, userCertificateSelectionCallback); -#elif (WINDOWS_APP || WINDOWS_PHONE_APP) - this.channel = new MqttNetworkChannel(this.brokerHostName, this.brokerPort, secure, sslProtocol); -#else - this.channel = new MqttNetworkChannel(this.brokerHostName, this.brokerPort, secure, caCert, clientCert, sslProtocol); -#endif - } - - /// - /// Connect to broker - /// - /// Client identifier - /// Return code of CONNACK message from broker - public byte Connect(string clientId) - { - return this.Connect(clientId, null, null, false, MqttMsgConnect.QOS_LEVEL_AT_MOST_ONCE, false, null, null, true, MqttMsgConnect.KEEP_ALIVE_PERIOD_DEFAULT); - } - - /// - /// Connect to broker - /// - /// Client identifier - /// Username - /// Password - /// Return code of CONNACK message from broker - public byte Connect(string clientId, - string username, - string password) - { - return this.Connect(clientId, username, password, false, MqttMsgConnect.QOS_LEVEL_AT_MOST_ONCE, false, null, null, true, MqttMsgConnect.KEEP_ALIVE_PERIOD_DEFAULT); - } - - /// - /// Connect to broker - /// - /// Client identifier - /// Username - /// Password - /// Clean sessione flag - /// Keep alive period - /// Return code of CONNACK message from broker - public byte Connect(string clientId, - string username, - string password, - bool cleanSession, - ushort keepAlivePeriod) - { - return this.Connect(clientId, username, password, false, MqttMsgConnect.QOS_LEVEL_AT_MOST_ONCE, false, null, null, cleanSession, keepAlivePeriod); - } - - /// - /// Connect to broker - /// - /// Client identifier - /// Username - /// Password - /// Will retain flag - /// Will QOS level - /// Will flag - /// Will topic - /// Will message - /// Clean sessione flag - /// Keep alive period - /// Return code of CONNACK message from broker - public byte Connect(string clientId, - string username, - string password, - bool willRetain, - byte willQosLevel, - bool willFlag, - string willTopic, - string willMessage, - bool cleanSession, - ushort keepAlivePeriod) - { - // create CONNECT message - MqttMsgConnect connect = new MqttMsgConnect(clientId, - username, - password, - willRetain, - willQosLevel, - willFlag, - willTopic, - willMessage, - cleanSession, - keepAlivePeriod, - (byte)this.ProtocolVersion); - - try - { - // connect to the broker - this.channel.Connect(); - } - catch (Exception ex) - { - throw new MqttConnectionException("Exception connecting to the broker", ex); - } - - this.lastCommTime = 0; - this.isRunning = true; - this.isConnectionClosing = false; - // start thread for receiving messages from broker - Fx.StartThread(this.ReceiveThread); - - MqttMsgConnack connack = (MqttMsgConnack)this.SendReceive(connect); - // if connection accepted, start keep alive timer and - if (connack.ReturnCode == MqttMsgConnack.CONN_ACCEPTED) - { - // set all client properties - this.ClientId = clientId; - this.CleanSession = cleanSession; - this.WillFlag = willFlag; - this.WillTopic = willTopic; - this.WillMessage = willMessage; - this.WillQosLevel = willQosLevel; - - this.keepAlivePeriod = keepAlivePeriod * 1000; // convert in ms - - // restore previous session - this.RestoreSession(); - - // keep alive period equals zero means turning off keep alive mechanism - if (this.keepAlivePeriod != 0) - { - // start thread for sending keep alive message to the broker - Fx.StartThread(this.KeepAliveThread); - } - - // start thread for raising received message event from broker - Fx.StartThread(this.DispatchEventThread); - - // start thread for handling inflight messages queue to broker asynchronously (publish and acknowledge) - Fx.StartThread(this.ProcessInflightThread); - - this.IsConnected = true; - } - return connack.ReturnCode; - } - - /// - /// Disconnect from broker - /// - public void Disconnect() - { - MqttMsgDisconnect disconnect = new MqttMsgDisconnect(); - this.Send(disconnect); - - // close client - this.OnConnectionClosing(); - } - -#if BROKER - /// - /// Open client communication - /// - public void Open() - { - this.isRunning = true; - - // start thread for receiving messages from client - Fx.StartThread(this.ReceiveThread); - - // start thread for raising received message event from client - Fx.StartThread(this.DispatchEventThread); - - // start thread for handling inflight messages queue to client asynchronously (publish and acknowledge) - Fx.StartThread(this.ProcessInflightThread); - } -#endif - - /// - /// Close client - /// -#if BROKER - public void Close() -#else - private void Close() -#endif - { - // stop receiving thread - this.isRunning = false; - - // wait end receive event thread - if (this.receiveEventWaitHandle != null) - this.receiveEventWaitHandle.Set(); - - // wait end process inflight thread - if (this.inflightWaitHandle != null) - this.inflightWaitHandle.Set(); - -#if BROKER - // unlock keep alive thread - this.keepAliveEvent.Set(); -#else - // unlock keep alive thread and wait - this.keepAliveEvent.Set(); - - if (this.keepAliveEventEnd != null) - this.keepAliveEventEnd.WaitOne(); -#endif - - // clear all queues - this.inflightQueue.Clear(); - this.internalQueue.Clear(); - this.eventQueue.Clear(); - - // close network channel - this.channel.Close(); - - this.IsConnected = false; - } - - /// - /// Execute ping to broker for keep alive - /// - /// PINGRESP message from broker - private MqttMsgPingResp Ping() - { - MqttMsgPingReq pingreq = new MqttMsgPingReq(); - try - { - // broker must send PINGRESP within timeout equal to keep alive period - return (MqttMsgPingResp)this.SendReceive(pingreq, this.keepAlivePeriod); - } - catch (Exception e) - { -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", e.ToString()); -#endif - - // client must close connection - this.OnConnectionClosing(); - return null; - } - } - -#if BROKER - /// - /// Send CONNACK message to the client (connection accepted or not) - /// - /// CONNECT message with all client information - /// Return code for CONNACK message - /// If not null, client id assigned by broker - /// Session present on the broker - public void Connack(MqttMsgConnect connect, byte returnCode, string clientId, bool sessionPresent) - { - this.lastCommTime = 0; - - // create CONNACK message and ... - MqttMsgConnack connack = new MqttMsgConnack(); - connack.ReturnCode = returnCode; - // [v3.1.1] session present flag - if (this.ProtocolVersion == MqttProtocolVersion.Version_3_1_1) - connack.SessionPresent = sessionPresent; - // ... send it to the client - this.Send(connack); - - // connection accepted, start keep alive thread checking - if (connack.ReturnCode == MqttMsgConnack.CONN_ACCEPTED) - { - // [v3.1.1] if client id isn't null, the CONNECT message has a cliend id with zero bytes length - // and broker assigned a unique identifier to the client - this.ClientId = (clientId == null) ? connect.ClientId : clientId; - this.CleanSession = connect.CleanSession; - this.WillFlag = connect.WillFlag; - this.WillTopic = connect.WillTopic; - this.WillMessage = connect.WillMessage; - this.WillQosLevel = connect.WillQosLevel; - - this.keepAlivePeriod = connect.KeepAlivePeriod * 1000; // convert in ms - // broker has a tolerance of 1.5 specified keep alive period - this.keepAlivePeriod += (this.keepAlivePeriod / 2); - - // start thread for checking keep alive period timeout - Fx.StartThread(this.KeepAliveThread); - - this.isConnectionClosing = false; - this.IsConnected = true; - } - // connection refused, close TCP/IP channel - else - { - this.Close(); - } - } - - /// - /// Send SUBACK message to the client - /// - /// Message Id for the SUBSCRIBE message that is being acknowledged - /// Granted QoS Levels - public void Suback(ushort messageId, byte[] grantedQosLevels) - { - MqttMsgSuback suback = new MqttMsgSuback(); - suback.MessageId = messageId; - suback.GrantedQoSLevels = grantedQosLevels; - - this.Send(suback); - } - - /// - /// Send UNSUBACK message to the client - /// - /// Message Id for the UNSUBSCRIBE message that is being acknowledged - public void Unsuback(ushort messageId) - { - MqttMsgUnsuback unsuback = new MqttMsgUnsuback(); - unsuback.MessageId = messageId; - - this.Send(unsuback); - } -#endif - - /// - /// Subscribe for message topics - /// - /// List of topics to subscribe - /// QOS levels related to topics - /// Message Id related to SUBSCRIBE message - public ushort Subscribe(string[] topics, byte[] qosLevels) - { - MqttMsgSubscribe subscribe = - new MqttMsgSubscribe(topics, qosLevels); - subscribe.MessageId = this.GetMessageId(); - - // enqueue subscribe request into the inflight queue - this.EnqueueInflight(subscribe, MqttMsgFlow.ToPublish); - - return subscribe.MessageId; - } - - /// - /// Unsubscribe for message topics - /// - /// List of topics to unsubscribe - /// Message Id in UNSUBACK message from broker - public ushort Unsubscribe(string[] topics) - { - MqttMsgUnsubscribe unsubscribe = - new MqttMsgUnsubscribe(topics); - unsubscribe.MessageId = this.GetMessageId(); - - // enqueue unsubscribe request into the inflight queue - this.EnqueueInflight(unsubscribe, MqttMsgFlow.ToPublish); - - return unsubscribe.MessageId; - } - - /// - /// Publish a message asynchronously (QoS Level 0 and not retained) - /// - /// Message topic - /// Message data (payload) - /// Message Id related to PUBLISH message - public ushort Publish(string topic, byte[] message) - { - return this.Publish(topic, message, MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE, false); - } - - /// - /// Publish a message asynchronously - /// - /// Message topic - /// Message data (payload) - /// QoS Level - /// Retain flag - /// Message Id related to PUBLISH message - public ushort Publish(string topic, byte[] message, byte qosLevel, bool retain) - { - MqttMsgPublish publish = - new MqttMsgPublish(topic, message, false, qosLevel, retain); - publish.MessageId = this.GetMessageId(); - - // enqueue message to publish into the inflight queue - bool enqueue = this.EnqueueInflight(publish, MqttMsgFlow.ToPublish); - - // message enqueued - if (enqueue) - return publish.MessageId; - // infligh queue full, message not enqueued - else - throw new MqttClientException(MqttClientErrorCode.InflightQueueFull); - } - - /// - /// Wrapper method for raising events - /// - /// Internal event - private void OnInternalEvent(InternalEvent internalEvent) - { - lock (this.eventQueue) - { - this.eventQueue.Enqueue(internalEvent); - } - - this.receiveEventWaitHandle.Set(); - } - - /// - /// Wrapper method for raising closing connection event - /// - private void OnConnectionClosing() - { - if (!this.isConnectionClosing) - { - this.isConnectionClosing = true; - this.receiveEventWaitHandle.Set(); - } - } - - /// - /// Wrapper method for raising PUBLISH message received event - /// - /// PUBLISH message received - private void OnMqttMsgPublishReceived(MqttMsgPublish publish) - { - if (this.MqttMsgPublishReceived != null) - { - this.MqttMsgPublishReceived(this, - new MqttMsgPublishEventArgs(publish.Topic, publish.Message, publish.DupFlag, publish.QosLevel, publish.Retain)); - } - } - - /// - /// Wrapper method for raising published message event - /// - /// Message identifier for published message - /// Publish flag - private void OnMqttMsgPublished(ushort messageId, bool isPublished) - { - if (this.MqttMsgPublished != null) - { - this.MqttMsgPublished(this, - new MqttMsgPublishedEventArgs(messageId, isPublished)); - } - } - - /// - /// Wrapper method for raising subscribed topic event - /// - /// SUBACK message received - private void OnMqttMsgSubscribed(MqttMsgSuback suback) - { - if (this.MqttMsgSubscribed != null) - { - this.MqttMsgSubscribed(this, - new MqttMsgSubscribedEventArgs(suback.MessageId, suback.GrantedQoSLevels)); - } - } - - /// - /// Wrapper method for raising unsubscribed topic event - /// - /// Message identifier for unsubscribed topic - private void OnMqttMsgUnsubscribed(ushort messageId) - { - if (this.MqttMsgUnsubscribed != null) - { - this.MqttMsgUnsubscribed(this, - new MqttMsgUnsubscribedEventArgs(messageId)); - } - } - -#if BROKER - /// - /// Wrapper method for raising SUBSCRIBE message event - /// - /// Message identifier for subscribe topics request - /// Topics requested to subscribe - /// List of QOS Levels requested - private void OnMqttMsgSubscribeReceived(ushort messageId, string[] topics, byte[] qosLevels) - { - if (this.MqttMsgSubscribeReceived != null) - { - this.MqttMsgSubscribeReceived(this, - new MqttMsgSubscribeEventArgs(messageId, topics, qosLevels)); - } - } - - /// - /// Wrapper method for raising UNSUBSCRIBE message event - /// - /// Message identifier for unsubscribe topics request - /// Topics requested to unsubscribe - private void OnMqttMsgUnsubscribeReceived(ushort messageId, string[] topics) - { - if (this.MqttMsgUnsubscribeReceived != null) - { - this.MqttMsgUnsubscribeReceived(this, - new MqttMsgUnsubscribeEventArgs(messageId, topics)); - } - } - - /// - /// Wrapper method for raising CONNECT message event - /// - private void OnMqttMsgConnected(MqttMsgConnect connect) - { - if (this.MqttMsgConnected != null) - { - this.ProtocolVersion = (MqttProtocolVersion)connect.ProtocolVersion; - this.MqttMsgConnected(this, new MqttMsgConnectEventArgs(connect)); - } - } - - /// - /// Wrapper method for raising DISCONNECT message event - /// - private void OnMqttMsgDisconnected() - { - if (this.MqttMsgDisconnected != null) - { - this.MqttMsgDisconnected(this, EventArgs.Empty); - } - } -#endif - - /// - /// Wrapper method for peer/client disconnection - /// - private void OnConnectionClosed() - { - if (this.ConnectionClosed != null) - { - this.ConnectionClosed(this, EventArgs.Empty); - } - } - - /// - /// Send a message - /// - /// Message bytes - private void Send(byte[] msgBytes) - { - try - { - // send message - this.channel.Send(msgBytes); - -#if !BROKER - // update last message sent ticks - this.lastCommTime = Environment.TickCount; -#endif - } - catch (Exception e) - { -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", e.ToString()); -#endif - - throw new MqttCommunicationException(e); - } - } - - /// - /// Send a message - /// - /// Message - private void Send(MqttMsgBase msg) - { -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "SEND {0}", msg); -#endif - this.Send(msg.GetBytes((byte)this.ProtocolVersion)); - } - - /// - /// Send a message to the broker and wait answer - /// - /// Message bytes - /// MQTT message response - private MqttMsgBase SendReceive(byte[] msgBytes) - { - return this.SendReceive(msgBytes, MqttSettings.MQTT_DEFAULT_TIMEOUT); - } - - /// - /// Send a message to the broker and wait answer - /// - /// Message bytes - /// Timeout for receiving answer - /// MQTT message response - private MqttMsgBase SendReceive(byte[] msgBytes, int timeout) - { - // reset handle before sending - this.syncEndReceiving.Reset(); - try - { - // send message - this.channel.Send(msgBytes); - - // update last message sent ticks - this.lastCommTime = Environment.TickCount; - } - catch (Exception e) - { -#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK || WINDOWS_APP || WINDOWS_PHONE_APP) - if (typeof(SocketException) == e.GetType()) - { - // connection reset by broker - if (((SocketException)e).SocketErrorCode == SocketError.ConnectionReset) - this.IsConnected = false; - } -#endif -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", e.ToString()); -#endif - - throw new MqttCommunicationException(e); - } - -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - // wait for answer from broker - if (this.syncEndReceiving.WaitOne(timeout, false)) -#else - // wait for answer from broker - if (this.syncEndReceiving.WaitOne(timeout)) -#endif - { - // message received without exception - if (this.exReceiving == null) - return this.msgReceived; - // receiving thread catched exception - else - throw this.exReceiving; - } - else - { - // throw timeout exception - throw new MqttCommunicationException(); - } - } - - /// - /// Send a message to the broker and wait answer - /// - /// Message - /// MQTT message response - private MqttMsgBase SendReceive(MqttMsgBase msg) - { - return this.SendReceive(msg, MqttSettings.MQTT_DEFAULT_TIMEOUT); - } - - /// - /// Send a message to the broker and wait answer - /// - /// Message - /// Timeout for receiving answer - /// MQTT message response - private MqttMsgBase SendReceive(MqttMsgBase msg, int timeout) - { -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "SEND {0}", msg); -#endif - return this.SendReceive(msg.GetBytes((byte)this.ProtocolVersion), timeout); - } - - /// - /// Enqueue a message into the inflight queue - /// - /// Message to enqueue - /// Message flow (publish, acknowledge) - /// Message enqueued or not - private bool EnqueueInflight(MqttMsgBase msg, MqttMsgFlow flow) - { - // enqueue is needed (or not) - bool enqueue = true; - - // if it is a PUBLISH message with QoS Level 2 - if ((msg.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && - (msg.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE)) - { - lock (this.inflightQueue) - { - // if it is a PUBLISH message already received (it is in the inflight queue), the publisher - // re-sent it because it didn't received the PUBREC. In this case, we have to re-send PUBREC - - // NOTE : I need to find on message id and flow because the broker could be publish/received - // to/from client and message id could be the same (one tracked by broker and the other by client) - MqttMsgContextFinder msgCtxFinder = new MqttMsgContextFinder(msg.MessageId, MqttMsgFlow.ToAcknowledge); - MqttMsgContext msgCtx = (MqttMsgContext) QueueExtension.Get(this.inflightQueue, msgCtxFinder.Find); - - // the PUBLISH message is alredy in the inflight queue, we don't need to re-enqueue but we need - // to change state to re-send PUBREC - if (msgCtx != null) - { - msgCtx.State = MqttMsgState.QueuedQos2; - msgCtx.Flow = MqttMsgFlow.ToAcknowledge; - enqueue = false; - } - } - } - - if (enqueue) - { - // set a default state - MqttMsgState state = MqttMsgState.QueuedQos0; - - // based on QoS level, the messages flow between broker and client changes - switch (msg.QosLevel) - { - // QoS Level 0 - case MqttMsgBase.QOS_LEVEL_AT_MOST_ONCE: - - state = MqttMsgState.QueuedQos0; - break; - - // QoS Level 1 - case MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE: - - state = MqttMsgState.QueuedQos1; - break; - - // QoS Level 2 - case MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE: - - state = MqttMsgState.QueuedQos2; - break; - } - - // [v3.1.1] SUBSCRIBE and UNSUBSCRIBE aren't "officially" QOS = 1 - // so QueuedQos1 state isn't valid for them - if (msg.Type == MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE) - state = MqttMsgState.SendSubscribe; - else if (msg.Type == MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE) - state = MqttMsgState.SendUnsubscribe; - - // queue message context - MqttMsgContext msgContext = new MqttMsgContext() - { - Message = msg, - State = state, - Flow = flow, - Attempt = 0 - }; - - lock (this.inflightQueue) - { - // check number of messages inside inflight queue - enqueue = (this.inflightQueue.Count < this.settings.InflightQueueSize); - - if (enqueue) - { - // enqueue message and unlock send thread - this.inflightQueue.Enqueue(msgContext); - -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "enqueued {0}", msg); -#endif - - // PUBLISH message - if (msg.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) - { - // to publish and QoS level 1 or 2 - if ((msgContext.Flow == MqttMsgFlow.ToPublish) && - ((msg.QosLevel == MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE) || - (msg.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE))) - { - if (this.session != null) - this.session.InflightMessages.Add(msgContext.Key, msgContext); - } - // to acknowledge and QoS level 2 - else if ((msgContext.Flow == MqttMsgFlow.ToAcknowledge) && - (msg.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE)) - { - if (this.session != null) - this.session.InflightMessages.Add(msgContext.Key, msgContext); - } - } - } - } - } - - this.inflightWaitHandle.Set(); - - return enqueue; - } - - /// - /// Enqueue a message into the internal queue - /// - /// Message to enqueue - private void EnqueueInternal(MqttMsgBase msg) - { - // enqueue is needed (or not) - bool enqueue = true; - - // if it is a PUBREL message (for QoS Level 2) - if (msg.Type == MqttMsgBase.MQTT_MSG_PUBREL_TYPE) - { - lock (this.inflightQueue) - { - // if it is a PUBREL but the corresponding PUBLISH isn't in the inflight queue, - // it means that we processed PUBLISH message and received PUBREL and we sent PUBCOMP - // but publisher didn't receive PUBCOMP so it re-sent PUBREL. We need only to re-send PUBCOMP. - - // NOTE : I need to find on message id and flow because the broker could be publish/received - // to/from client and message id could be the same (one tracked by broker and the other by client) - MqttMsgContextFinder msgCtxFinder = new MqttMsgContextFinder(msg.MessageId, MqttMsgFlow.ToAcknowledge); - MqttMsgContext msgCtx = (MqttMsgContext) QueueExtension.Get(this.inflightQueue,msgCtxFinder.Find); - - // the PUBLISH message isn't in the inflight queue, it was already processed so - // we need to re-send PUBCOMP only - if (msgCtx == null) - { - MqttMsgPubcomp pubcomp = new MqttMsgPubcomp(); - pubcomp.MessageId = msg.MessageId; - - this.Send(pubcomp); - - enqueue = false; - } - } - } - // if it is a PUBCOMP message (for QoS Level 2) - else if (msg.Type == MqttMsgBase.MQTT_MSG_PUBCOMP_TYPE) - { - lock (this.inflightQueue) - { - // if it is a PUBCOMP but the corresponding PUBLISH isn't in the inflight queue, - // it means that we sent PUBLISH message, sent PUBREL (after receiving PUBREC) and already received PUBCOMP - // but publisher didn't receive PUBREL so it re-sent PUBCOMP. We need only to ignore this PUBCOMP. - - // NOTE : I need to find on message id and flow because the broker could be publish/received - // to/from client and message id could be the same (one tracked by broker and the other by client) - MqttMsgContextFinder msgCtxFinder = new MqttMsgContextFinder(msg.MessageId, MqttMsgFlow.ToPublish); - MqttMsgContext msgCtx = (MqttMsgContext) QueueExtension.Get(this.inflightQueue, msgCtxFinder.Find); - - // the PUBLISH message isn't in the inflight queue, it was already sent so we need to ignore this PUBCOMP - if (msgCtx == null) - { - enqueue = false; - } - } - } - // if it is a PUBREC message (for QoS Level 2) - else if (msg.Type == MqttMsgBase.MQTT_MSG_PUBREC_TYPE) - { - lock (this.inflightQueue) - { - // if it is a PUBREC but the corresponding PUBLISH isn't in the inflight queue, - // it means that we sent PUBLISH message more times (retries) but broker didn't send PUBREC in time - // the publish is failed and we need only to ignore this PUBREC. - - // NOTE : I need to find on message id and flow because the broker could be publish/received - // to/from client and message id could be the same (one tracked by broker and the other by client) - MqttMsgContextFinder msgCtxFinder = new MqttMsgContextFinder(msg.MessageId, MqttMsgFlow.ToPublish); - MqttMsgContext msgCtx = (MqttMsgContext) QueueExtension.Get(this.inflightQueue, msgCtxFinder.Find); - - // the PUBLISH message isn't in the inflight queue, it was already sent so we need to ignore this PUBREC - if (msgCtx == null) - { - enqueue = false; - } - } - } - - if (enqueue) - { - lock (this.internalQueue) - { - this.internalQueue.Enqueue(msg); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "enqueued {0}", msg); -#endif - this.inflightWaitHandle.Set(); - } - } - } - - /// - /// Thread for receiving messages - /// - private void ReceiveThread() - { - int readBytes = 0; - byte[] fixedHeaderFirstByte = new byte[1]; - byte msgType; - - while (this.isRunning) - { - try - { - // read first byte (fixed header) - readBytes = this.channel.Receive(fixedHeaderFirstByte); - - if (readBytes > 0) - { -#if BROKER - // update last message received ticks - this.lastCommTime = Environment.TickCount; -#endif - - // extract message type from received byte - msgType = (byte)((fixedHeaderFirstByte[0] & MqttMsgBase.MSG_TYPE_MASK) >> MqttMsgBase.MSG_TYPE_OFFSET); - - switch (msgType) - { - // CONNECT message received - case MqttMsgBase.MQTT_MSG_CONNECT_TYPE: - -#if BROKER - MqttMsgConnect connect = MqttMsgConnect.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - Trace.WriteLine(TraceLevel.Frame, "RECV {0}", connect); -#endif - - // raise message received event - this.OnInternalEvent(new MsgInternalEvent(connect)); - break; -#else - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#endif - - // CONNACK message received - case MqttMsgBase.MQTT_MSG_CONNACK_TYPE: - -#if BROKER - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#else - this.msgReceived = MqttMsgConnack.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", this.msgReceived); -#endif - this.syncEndReceiving.Set(); - break; -#endif - - // PINGREQ message received - case MqttMsgBase.MQTT_MSG_PINGREQ_TYPE: - -#if BROKER - this.msgReceived = MqttMsgPingReq.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - Trace.WriteLine(TraceLevel.Frame, "RECV {0}", this.msgReceived); -#endif - - MqttMsgPingResp pingresp = new MqttMsgPingResp(); - this.Send(pingresp); - - break; -#else - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#endif - - // PINGRESP message received - case MqttMsgBase.MQTT_MSG_PINGRESP_TYPE: - -#if BROKER - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#else - this.msgReceived = MqttMsgPingResp.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", this.msgReceived); -#endif - this.syncEndReceiving.Set(); - break; -#endif - - // SUBSCRIBE message received - case MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE: - -#if BROKER - MqttMsgSubscribe subscribe = MqttMsgSubscribe.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - Trace.WriteLine(TraceLevel.Frame, "RECV {0}", subscribe); -#endif - - // raise message received event - this.OnInternalEvent(new MsgInternalEvent(subscribe)); - - break; -#else - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#endif - - // SUBACK message received - case MqttMsgBase.MQTT_MSG_SUBACK_TYPE: - -#if BROKER - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#else - // enqueue SUBACK message received (for QoS Level 1) into the internal queue - MqttMsgSuback suback = MqttMsgSuback.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", suback); -#endif - - // enqueue SUBACK message into the internal queue - this.EnqueueInternal(suback); - - break; -#endif - - // PUBLISH message received - case MqttMsgBase.MQTT_MSG_PUBLISH_TYPE: - - MqttMsgPublish publish = MqttMsgPublish.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", publish); -#endif - - // enqueue PUBLISH message to acknowledge into the inflight queue - this.EnqueueInflight(publish, MqttMsgFlow.ToAcknowledge); - - break; - - // PUBACK message received - case MqttMsgBase.MQTT_MSG_PUBACK_TYPE: - - // enqueue PUBACK message received (for QoS Level 1) into the internal queue - MqttMsgPuback puback = MqttMsgPuback.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", puback); -#endif - - // enqueue PUBACK message into the internal queue - this.EnqueueInternal(puback); - - break; - - // PUBREC message received - case MqttMsgBase.MQTT_MSG_PUBREC_TYPE: - - // enqueue PUBREC message received (for QoS Level 2) into the internal queue - MqttMsgPubrec pubrec = MqttMsgPubrec.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", pubrec); -#endif - - // enqueue PUBREC message into the internal queue - this.EnqueueInternal(pubrec); - - break; - - // PUBREL message received - case MqttMsgBase.MQTT_MSG_PUBREL_TYPE: - - // enqueue PUBREL message received (for QoS Level 2) into the internal queue - MqttMsgPubrel pubrel = MqttMsgPubrel.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", pubrel); -#endif - - // enqueue PUBREL message into the internal queue - this.EnqueueInternal(pubrel); - - break; - - // PUBCOMP message received - case MqttMsgBase.MQTT_MSG_PUBCOMP_TYPE: - - // enqueue PUBCOMP message received (for QoS Level 2) into the internal queue - MqttMsgPubcomp pubcomp = MqttMsgPubcomp.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", pubcomp); -#endif - - // enqueue PUBCOMP message into the internal queue - this.EnqueueInternal(pubcomp); - - break; - - // UNSUBSCRIBE message received - case MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE: - -#if BROKER - MqttMsgUnsubscribe unsubscribe = MqttMsgUnsubscribe.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - Trace.WriteLine(TraceLevel.Frame, "RECV {0}", unsubscribe); -#endif - - // raise message received event - this.OnInternalEvent(new MsgInternalEvent(unsubscribe)); - - break; -#else - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#endif - - // UNSUBACK message received - case MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE: - -#if BROKER - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#else - // enqueue UNSUBACK message received (for QoS Level 1) into the internal queue - MqttMsgUnsuback unsuback = MqttMsgUnsuback.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", unsuback); -#endif - - // enqueue UNSUBACK message into the internal queue - this.EnqueueInternal(unsuback); - - break; -#endif - - // DISCONNECT message received - case MqttMsgDisconnect.MQTT_MSG_DISCONNECT_TYPE: - -#if BROKER - MqttMsgDisconnect disconnect = MqttMsgDisconnect.Parse(fixedHeaderFirstByte[0], (byte)this.ProtocolVersion, this.channel); -#if TRACE - Trace.WriteLine(TraceLevel.Frame, "RECV {0}", disconnect); -#endif - - // raise message received event - this.OnInternalEvent(new MsgInternalEvent(disconnect)); - - break; -#else - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#endif - - default: - - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); - } - - this.exReceiving = null; - } - // zero bytes read, peer gracefully closed socket - else - { - // wake up thread that will notify connection is closing - this.OnConnectionClosing(); - } - } - catch (Exception e) - { -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", e.ToString()); -#endif - this.exReceiving = new MqttCommunicationException(e); - - bool close = false; - if (e.GetType() == typeof(MqttClientException)) - { - // [v3.1.1] scenarios the receiver MUST close the network connection - MqttClientException ex = e as MqttClientException; - close = ((ex.ErrorCode == MqttClientErrorCode.InvalidFlagBits) || - (ex.ErrorCode == MqttClientErrorCode.InvalidProtocolName) || - (ex.ErrorCode == MqttClientErrorCode.InvalidConnectFlags)); - } -#if !(WINDOWS_APP || WINDOWS_PHONE_APP) - else if ((e.GetType() == typeof(IOException)) || (e.GetType() == typeof(SocketException)) || - ((e.InnerException != null) && (e.InnerException.GetType() == typeof(SocketException)))) // added for SSL/TLS incoming connection that use SslStream that wraps SocketException - { - close = true; - } -#endif - - if (close) - { - // wake up thread that will notify connection is closing - this.OnConnectionClosing(); - } - } - } - } - - /// - /// Thread for handling keep alive message - /// - private void KeepAliveThread() - { - int delta = 0; - int wait = this.keepAlivePeriod; - - // create event to signal that current thread is end - this.keepAliveEventEnd = new AutoResetEvent(false); - - while (this.isRunning) - { -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - // waiting... - this.keepAliveEvent.WaitOne(wait, false); -#else - // waiting... - this.keepAliveEvent.WaitOne(wait); -#endif - - if (this.isRunning) - { - delta = Environment.TickCount - this.lastCommTime; - - // if timeout exceeded ... - if (delta >= this.keepAlivePeriod) - { -#if BROKER - // client must close connection - this.OnConnectionClosing(); -#else - // ... send keep alive - this.Ping(); - wait = this.keepAlivePeriod; -#endif - } - else - { - // update waiting time - wait = this.keepAlivePeriod - delta; - } - } - } - - // signal thread end - this.keepAliveEventEnd.Set(); - } - - /// - /// Thread for raising event - /// - private void DispatchEventThread() - { - while (this.isRunning) - { -#if BROKER - if ((this.eventQueue.Count == 0) && !this.isConnectionClosing) - { - // broker need to receive the first message (CONNECT) - // within a reasonable amount of time after TCP/IP connection - if (!this.IsConnected) - { - // wait on receiving message from client with a connection timeout - if (!this.receiveEventWaitHandle.WaitOne(this.settings.TimeoutOnConnection)) - { - // client must close connection - this.Close(); - - // client raw disconnection - this.OnConnectionClosed(); - } - } - else - { - // wait on receiving message from client - this.receiveEventWaitHandle.WaitOne(); - } - } -#else - if ((this.eventQueue.Count == 0) && !this.isConnectionClosing) - // wait on receiving message from client - this.receiveEventWaitHandle.WaitOne(); -#endif - - // check if it is running or we are closing client - if (this.isRunning) - { - // get event from queue - InternalEvent internalEvent = null; - lock (this.eventQueue) - { - if (this.eventQueue.Count > 0) - internalEvent = (InternalEvent)this.eventQueue.Dequeue(); - } - - // it's an event with a message inside - if (internalEvent != null) - { - MqttMsgBase msg = ((MsgInternalEvent)internalEvent).Message; - - if (msg != null) - { - switch (msg.Type) - { - // CONNECT message received - case MqttMsgBase.MQTT_MSG_CONNECT_TYPE: - -#if BROKER - // raise connected client event (CONNECT message received) - this.OnMqttMsgConnected((MqttMsgConnect)msg); - break; -#else - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#endif - - // SUBSCRIBE message received - case MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE: - -#if BROKER - MqttMsgSubscribe subscribe = (MqttMsgSubscribe)msg; - // raise subscribe topic event (SUBSCRIBE message received) - this.OnMqttMsgSubscribeReceived(subscribe.MessageId, subscribe.Topics, subscribe.QoSLevels); - break; -#else - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#endif - - // SUBACK message received - case MqttMsgBase.MQTT_MSG_SUBACK_TYPE: - - // raise subscribed topic event (SUBACK message received) - this.OnMqttMsgSubscribed((MqttMsgSuback)msg); - break; - - // PUBLISH message received - case MqttMsgBase.MQTT_MSG_PUBLISH_TYPE: - - // PUBLISH message received in a published internal event, no publish succeeded - if (internalEvent.GetType() == typeof(MsgPublishedInternalEvent)) - this.OnMqttMsgPublished(msg.MessageId, false); - else - // raise PUBLISH message received event - this.OnMqttMsgPublishReceived((MqttMsgPublish)msg); - break; - - // PUBACK message received - case MqttMsgBase.MQTT_MSG_PUBACK_TYPE: - - // raise published message event - // (PUBACK received for QoS Level 1) - this.OnMqttMsgPublished(msg.MessageId, true); - break; - - // PUBREL message received - case MqttMsgBase.MQTT_MSG_PUBREL_TYPE: - - // raise message received event - // (PUBREL received for QoS Level 2) - this.OnMqttMsgPublishReceived((MqttMsgPublish)msg); - break; - - // PUBCOMP message received - case MqttMsgBase.MQTT_MSG_PUBCOMP_TYPE: - - // raise published message event - // (PUBCOMP received for QoS Level 2) - this.OnMqttMsgPublished(msg.MessageId, true); - break; - - // UNSUBSCRIBE message received from client - case MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE: - -#if BROKER - MqttMsgUnsubscribe unsubscribe = (MqttMsgUnsubscribe)msg; - // raise unsubscribe topic event (UNSUBSCRIBE message received) - this.OnMqttMsgUnsubscribeReceived(unsubscribe.MessageId, unsubscribe.Topics); - break; -#else - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#endif - - // UNSUBACK message received - case MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE: - - // raise unsubscribed topic event - this.OnMqttMsgUnsubscribed(msg.MessageId); - break; - - // DISCONNECT message received from client - case MqttMsgDisconnect.MQTT_MSG_DISCONNECT_TYPE: - -#if BROKER - // raise disconnected client event (DISCONNECT message received) - this.OnMqttMsgDisconnected(); - break; -#else - throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage); -#endif - } - } - } - - // all events for received messages dispatched, check if there is closing connection - if ((this.eventQueue.Count == 0) && this.isConnectionClosing) - { - // client must close connection - this.Close(); - - // client raw disconnection - this.OnConnectionClosed(); - } - } - } - } - - /// - /// Process inflight messages queue - /// - private void ProcessInflightThread() - { - MqttMsgContext msgContext = null; - MqttMsgBase msgInflight = null; - MqttMsgBase msgReceived = null; - InternalEvent internalEvent = null; - bool acknowledge = false; - int timeout = Timeout.Infinite; - int delta; - bool msgReceivedProcessed = false; - - try - { - while (this.isRunning) - { -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - // wait on message queueud to inflight - this.inflightWaitHandle.WaitOne(timeout, false); -#else - // wait on message queueud to inflight - this.inflightWaitHandle.WaitOne(timeout); -#endif - - // it could be unblocked because Close() method is joining - if (this.isRunning) - { - lock (this.inflightQueue) - { - // message received and peeked from internal queue is processed - // NOTE : it has the corresponding message in inflight queue based on messageId - // (ex. a PUBREC for a PUBLISH, a SUBACK for a SUBSCRIBE, ...) - // if it's orphan we need to remove from internal queue - msgReceivedProcessed = false; - acknowledge = false; - msgReceived = null; - - // set timeout tu MaxValue instead of Infinte (-1) to perform - // compare with calcultad current msgTimeout - timeout = Int32.MaxValue; - - // a message inflight could be re-enqueued but we have to - // analyze it only just one time for cycle - int count = this.inflightQueue.Count; - // process all inflight queued messages - while (count > 0) - { - count--; - acknowledge = false; - msgReceived = null; - - // check to be sure that client isn't closing and all queues are now empty ! - if (!this.isRunning) - break; - - // dequeue message context from queue - msgContext = (MqttMsgContext)this.inflightQueue.Dequeue(); - - // get inflight message - msgInflight = (MqttMsgBase)msgContext.Message; - - switch (msgContext.State) - { - case MqttMsgState.QueuedQos0: - - // QoS 0, PUBLISH message to send to broker, no state change, no acknowledge - if (msgContext.Flow == MqttMsgFlow.ToPublish) - { - this.Send(msgInflight); - } - // QoS 0, no need acknowledge - else if (msgContext.Flow == MqttMsgFlow.ToAcknowledge) - { - internalEvent = new MsgInternalEvent(msgInflight); - // notify published message from broker (no need acknowledged) - this.OnInternalEvent(internalEvent); - } - -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "processed {0}", msgInflight); -#endif - break; - - case MqttMsgState.QueuedQos1: - // [v3.1.1] SUBSCRIBE and UNSIBSCRIBE aren't "officially" QOS = 1 - case MqttMsgState.SendSubscribe: - case MqttMsgState.SendUnsubscribe: - - // QoS 1, PUBLISH or SUBSCRIBE/UNSUBSCRIBE message to send to broker, state change to wait PUBACK or SUBACK/UNSUBACK - if (msgContext.Flow == MqttMsgFlow.ToPublish) - { - msgContext.Timestamp = Environment.TickCount; - msgContext.Attempt++; - - if (msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) - { - // PUBLISH message to send, wait for PUBACK - msgContext.State = MqttMsgState.WaitForPuback; - // retry ? set dup flag [v3.1.1] only for PUBLISH message - if (msgContext.Attempt > 1) - msgInflight.DupFlag = true; - } - else if (msgInflight.Type == MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE) - // SUBSCRIBE message to send, wait for SUBACK - msgContext.State = MqttMsgState.WaitForSuback; - else if (msgInflight.Type == MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE) - // UNSUBSCRIBE message to send, wait for UNSUBACK - msgContext.State = MqttMsgState.WaitForUnsuback; - - this.Send(msgInflight); - - // update timeout : minimum between delay (based on current message sent) or current timeout - timeout = (this.settings.DelayOnRetry < timeout) ? this.settings.DelayOnRetry : timeout; - - // re-enqueue message (I have to re-analyze for receiving PUBACK, SUBACK or UNSUBACK) - this.inflightQueue.Enqueue(msgContext); - } - // QoS 1, PUBLISH message received from broker to acknowledge, send PUBACK - else if (msgContext.Flow == MqttMsgFlow.ToAcknowledge) - { - MqttMsgPuback puback = new MqttMsgPuback(); - puback.MessageId = msgInflight.MessageId; - - this.Send(puback); - - internalEvent = new MsgInternalEvent(msgInflight); - // notify published message from broker and acknowledged - this.OnInternalEvent(internalEvent); - -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "processed {0}", msgInflight); -#endif - } - break; - - case MqttMsgState.QueuedQos2: - - // QoS 2, PUBLISH message to send to broker, state change to wait PUBREC - if (msgContext.Flow == MqttMsgFlow.ToPublish) - { - msgContext.Timestamp = Environment.TickCount; - msgContext.Attempt++; - msgContext.State = MqttMsgState.WaitForPubrec; - // retry ? set dup flag - if (msgContext.Attempt > 1) - msgInflight.DupFlag = true; - - this.Send(msgInflight); - - // update timeout : minimum between delay (based on current message sent) or current timeout - timeout = (this.settings.DelayOnRetry < timeout) ? this.settings.DelayOnRetry : timeout; - - // re-enqueue message (I have to re-analyze for receiving PUBREC) - this.inflightQueue.Enqueue(msgContext); - } - // QoS 2, PUBLISH message received from broker to acknowledge, send PUBREC, state change to wait PUBREL - else if (msgContext.Flow == MqttMsgFlow.ToAcknowledge) - { - MqttMsgPubrec pubrec = new MqttMsgPubrec(); - pubrec.MessageId = msgInflight.MessageId; - - msgContext.State = MqttMsgState.WaitForPubrel; - - this.Send(pubrec); - - // re-enqueue message (I have to re-analyze for receiving PUBREL) - this.inflightQueue.Enqueue(msgContext); - } - break; - - case MqttMsgState.WaitForPuback: - case MqttMsgState.WaitForSuback: - case MqttMsgState.WaitForUnsuback: - - // QoS 1, waiting for PUBACK of a PUBLISH message sent or - // waiting for SUBACK of a SUBSCRIBE message sent or - // waiting for UNSUBACK of a UNSUBSCRIBE message sent or - if (msgContext.Flow == MqttMsgFlow.ToPublish) - { - acknowledge = false; - lock (this.internalQueue) - { - if (this.internalQueue.Count > 0) - msgReceived = (MqttMsgBase)this.internalQueue.Peek(); - } - - // it is a PUBACK message or a SUBACK/UNSUBACK message - if (msgReceived != null) - { - // PUBACK message or SUBACK/UNSUBACK message for the current message - if (((msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBACK_TYPE) && (msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && (msgReceived.MessageId == msgInflight.MessageId)) || - ((msgReceived.Type == MqttMsgBase.MQTT_MSG_SUBACK_TYPE) && (msgInflight.Type == MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE) && (msgReceived.MessageId == msgInflight.MessageId)) || - ((msgReceived.Type == MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE) && (msgInflight.Type == MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE) && (msgReceived.MessageId == msgInflight.MessageId))) - { - lock (this.internalQueue) - { - // received message processed - this.internalQueue.Dequeue(); - acknowledge = true; - msgReceivedProcessed = true; -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "dequeued {0}", msgReceived); -#endif - } - - // if PUBACK received, confirm published with flag - if (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBACK_TYPE) - internalEvent = new MsgPublishedInternalEvent(msgReceived, true); - else - internalEvent = new MsgInternalEvent(msgReceived); - - // notify received acknowledge from broker of a published message or subscribe/unsubscribe message - this.OnInternalEvent(internalEvent); - - // PUBACK received for PUBLISH message with QoS Level 1, remove from session state - if ((msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && - (this.session != null) && -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - (this.session.InflightMessages.Contains(msgContext.Key))) -#else - (this.session.InflightMessages.ContainsKey(msgContext.Key))) -#endif - { - this.session.InflightMessages.Remove(msgContext.Key); - } - -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "processed {0}", msgInflight); -#endif - } - } - - // current message not acknowledged, no PUBACK or SUBACK/UNSUBACK or not equal messageid - if (!acknowledge) - { - delta = Environment.TickCount - msgContext.Timestamp; - // check timeout for receiving PUBACK since PUBLISH was sent or - // for receiving SUBACK since SUBSCRIBE was sent or - // for receiving UNSUBACK since UNSUBSCRIBE was sent - if (delta >= this.settings.DelayOnRetry) - { - // max retry not reached, resend - if (msgContext.Attempt < this.settings.AttemptsOnRetry) - { - msgContext.State = MqttMsgState.QueuedQos1; - - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - - // update timeout (0 -> reanalyze queue immediately) - timeout = 0; - } - else - { - // if PUBACK for a PUBLISH message not received after retries, raise event for not published - if (msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) - { - // PUBACK not received in time, PUBLISH retries failed, need to remove from session inflight messages too - if ((this.session != null) && -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - (this.session.InflightMessages.Contains(msgContext.Key))) -#else - (this.session.InflightMessages.ContainsKey(msgContext.Key))) -#endif - { - this.session.InflightMessages.Remove(msgContext.Key); - } - - internalEvent = new MsgPublishedInternalEvent(msgInflight, false); - - // notify not received acknowledge from broker and message not published - this.OnInternalEvent(internalEvent); - } - // NOTE : not raise events for SUBACK or UNSUBACK not received - // for the user no event raised means subscribe/unsubscribe failed - } - } - else - { - // re-enqueue message (I have to re-analyze for receiving PUBACK, SUBACK or UNSUBACK) - this.inflightQueue.Enqueue(msgContext); - - // update timeout - int msgTimeout = (this.settings.DelayOnRetry - delta); - timeout = (msgTimeout < timeout) ? msgTimeout : timeout; - } - } - } - break; - - case MqttMsgState.WaitForPubrec: - - // QoS 2, waiting for PUBREC of a PUBLISH message sent - if (msgContext.Flow == MqttMsgFlow.ToPublish) - { - acknowledge = false; - lock (this.internalQueue) - { - if (this.internalQueue.Count > 0) - msgReceived = (MqttMsgBase)this.internalQueue.Peek(); - } - - // it is a PUBREC message - if ((msgReceived != null) && (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBREC_TYPE)) - { - // PUBREC message for the current PUBLISH message, send PUBREL, wait for PUBCOMP - if (msgReceived.MessageId == msgInflight.MessageId) - { - lock (this.internalQueue) - { - // received message processed - this.internalQueue.Dequeue(); - acknowledge = true; - msgReceivedProcessed = true; -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "dequeued {0}", msgReceived); -#endif - } - - MqttMsgPubrel pubrel = new MqttMsgPubrel(); - pubrel.MessageId = msgInflight.MessageId; - - msgContext.State = MqttMsgState.WaitForPubcomp; - msgContext.Timestamp = Environment.TickCount; - msgContext.Attempt = 1; - - this.Send(pubrel); - - // update timeout : minimum between delay (based on current message sent) or current timeout - timeout = (this.settings.DelayOnRetry < timeout) ? this.settings.DelayOnRetry : timeout; - - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - } - } - - // current message not acknowledged - if (!acknowledge) - { - delta = Environment.TickCount - msgContext.Timestamp; - // check timeout for receiving PUBREC since PUBLISH was sent - if (delta >= this.settings.DelayOnRetry) - { - // max retry not reached, resend - if (msgContext.Attempt < this.settings.AttemptsOnRetry) - { - msgContext.State = MqttMsgState.QueuedQos2; - - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - - // update timeout (0 -> reanalyze queue immediately) - timeout = 0; - } - else - { - // PUBREC not received in time, PUBLISH retries failed, need to remove from session inflight messages too - if ((this.session != null) && -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - (this.session.InflightMessages.Contains(msgContext.Key))) -#else - (this.session.InflightMessages.ContainsKey(msgContext.Key))) -#endif - { - this.session.InflightMessages.Remove(msgContext.Key); - } - - // if PUBREC for a PUBLISH message not received after retries, raise event for not published - internalEvent = new MsgPublishedInternalEvent(msgInflight, false); - // notify not received acknowledge from broker and message not published - this.OnInternalEvent(internalEvent); - } - } - else - { - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - - // update timeout - int msgTimeout = (this.settings.DelayOnRetry - delta); - timeout = (msgTimeout < timeout) ? msgTimeout : timeout; - } - } - } - break; - - case MqttMsgState.WaitForPubrel: - - // QoS 2, waiting for PUBREL of a PUBREC message sent - if (msgContext.Flow == MqttMsgFlow.ToAcknowledge) - { - lock (this.internalQueue) - { - if (this.internalQueue.Count > 0) - msgReceived = (MqttMsgBase)this.internalQueue.Peek(); - } - - // it is a PUBREL message - if ((msgReceived != null) && (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBREL_TYPE)) - { - // PUBREL message for the current message, send PUBCOMP - if (msgReceived.MessageId == msgInflight.MessageId) - { - lock (this.internalQueue) - { - // received message processed - this.internalQueue.Dequeue(); - msgReceivedProcessed = true; -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "dequeued {0}", msgReceived); -#endif - } - - MqttMsgPubcomp pubcomp = new MqttMsgPubcomp(); - pubcomp.MessageId = msgInflight.MessageId; - - this.Send(pubcomp); - - internalEvent = new MsgInternalEvent(msgInflight); - // notify published message from broker and acknowledged - this.OnInternalEvent(internalEvent); - - // PUBREL received (and PUBCOMP sent) for PUBLISH message with QoS Level 2, remove from session state - if ((msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && - (this.session != null) && -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - (this.session.InflightMessages.Contains(msgContext.Key))) -#else - (this.session.InflightMessages.ContainsKey(msgContext.Key))) -#endif - { - this.session.InflightMessages.Remove(msgContext.Key); - } - -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "processed {0}", msgInflight); -#endif - } - else - { - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - } - } - else - { - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - } - } - break; - - case MqttMsgState.WaitForPubcomp: - - // QoS 2, waiting for PUBCOMP of a PUBREL message sent - if (msgContext.Flow == MqttMsgFlow.ToPublish) - { - acknowledge = false; - lock (this.internalQueue) - { - if (this.internalQueue.Count > 0) - msgReceived = (MqttMsgBase)this.internalQueue.Peek(); - } - - // it is a PUBCOMP message - if ((msgReceived != null) && (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBCOMP_TYPE)) - { - // PUBCOMP message for the current message - if (msgReceived.MessageId == msgInflight.MessageId) - { - lock (this.internalQueue) - { - // received message processed - this.internalQueue.Dequeue(); - acknowledge = true; - msgReceivedProcessed = true; -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "dequeued {0}", msgReceived); -#endif - } - - internalEvent = new MsgPublishedInternalEvent(msgReceived, true); - // notify received acknowledge from broker of a published message - this.OnInternalEvent(internalEvent); - - // PUBCOMP received for PUBLISH message with QoS Level 2, remove from session state - if ((msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && - (this.session != null) && -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - (this.session.InflightMessages.Contains(msgContext.Key))) -#else - (this.session.InflightMessages.ContainsKey(msgContext.Key))) -#endif - { - this.session.InflightMessages.Remove(msgContext.Key); - } - -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "processed {0}", msgInflight); -#endif - } - } - // it is a PUBREC message - else if ((msgReceived != null) && (msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBREC_TYPE)) - { - // another PUBREC message for the current message due to a retransmitted PUBLISH - // I'm in waiting for PUBCOMP, so I can discard this PUBREC - if (msgReceived.MessageId == msgInflight.MessageId) - { - lock (this.internalQueue) - { - // received message processed - this.internalQueue.Dequeue(); - acknowledge = true; - msgReceivedProcessed = true; -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "dequeued {0}", msgReceived); -#endif - - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - } - } - } - - // current message not acknowledged - if (!acknowledge) - { - delta = Environment.TickCount - msgContext.Timestamp; - // check timeout for receiving PUBCOMP since PUBREL was sent - if (delta >= this.settings.DelayOnRetry) - { - // max retry not reached, resend - if (msgContext.Attempt < this.settings.AttemptsOnRetry) - { - msgContext.State = MqttMsgState.SendPubrel; - - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - - // update timeout (0 -> reanalyze queue immediately) - timeout = 0; - } - else - { - // PUBCOMP not received, PUBREL retries failed, need to remove from session inflight messages too - if ((this.session != null) && -#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - (this.session.InflightMessages.Contains(msgContext.Key))) -#else - (this.session.InflightMessages.ContainsKey(msgContext.Key))) -#endif - { - this.session.InflightMessages.Remove(msgContext.Key); - } - - // if PUBCOMP for a PUBLISH message not received after retries, raise event for not published - internalEvent = new MsgPublishedInternalEvent(msgInflight, false); - // notify not received acknowledge from broker and message not published - this.OnInternalEvent(internalEvent); - } - } - else - { - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - - // update timeout - int msgTimeout = (this.settings.DelayOnRetry - delta); - timeout = (msgTimeout < timeout) ? msgTimeout : timeout; - } - } - } - break; - - case MqttMsgState.SendPubrec: - - // TODO : impossible ? --> QueuedQos2 ToAcknowledge - break; - - case MqttMsgState.SendPubrel: - - // QoS 2, PUBREL message to send to broker, state change to wait PUBCOMP - if (msgContext.Flow == MqttMsgFlow.ToPublish) - { - MqttMsgPubrel pubrel = new MqttMsgPubrel(); - pubrel.MessageId = msgInflight.MessageId; - - msgContext.State = MqttMsgState.WaitForPubcomp; - msgContext.Timestamp = Environment.TickCount; - msgContext.Attempt++; - // retry ? set dup flag [v3.1.1] no needed - if (this.ProtocolVersion == MqttProtocolVersion.Version_3_1) - { - if (msgContext.Attempt > 1) - pubrel.DupFlag = true; - } - - this.Send(pubrel); - - // update timeout : minimum between delay (based on current message sent) or current timeout - timeout = (this.settings.DelayOnRetry < timeout) ? this.settings.DelayOnRetry : timeout; - - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - } - break; - - case MqttMsgState.SendPubcomp: - // TODO : impossible ? - break; - case MqttMsgState.SendPuback: - // TODO : impossible ? --> QueuedQos1 ToAcknowledge - break; - default: - break; - } - } - - // if calculated timeout is MaxValue, it means that must be Infinite (-1) - if (timeout == Int32.MaxValue) - timeout = Timeout.Infinite; - - // if message received is orphan, no corresponding message in inflight queue - // based on messageId, we need to remove from the queue - if ((msgReceived != null) && !msgReceivedProcessed) - { - this.internalQueue.Dequeue(); -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Queuing, "dequeued {0} orphan", msgReceived); -#endif - } - } - } - } - } - catch (MqttCommunicationException e) - { - // possible exception on Send, I need to re-enqueue not sent message - if (msgContext != null) - // re-enqueue message - this.inflightQueue.Enqueue(msgContext); - -#if TRACE - MqttUtility.Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", e.ToString()); -#endif - - // raise disconnection client event - this.OnConnectionClosing(); - } - } - - /// - /// Restore session - /// - private void RestoreSession() - { - // if not clean session - if (!this.CleanSession) - { - // there is a previous session - if (this.session != null) - { - lock (this.inflightQueue) - { - foreach (MqttMsgContext msgContext in this.session.InflightMessages.Values) - { - this.inflightQueue.Enqueue(msgContext); - - // if it is a PUBLISH message to publish - if ((msgContext.Message.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && - (msgContext.Flow == MqttMsgFlow.ToPublish)) - { - // it's QoS 1 and we haven't received PUBACK - if ((msgContext.Message.QosLevel == MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE) && - (msgContext.State == MqttMsgState.WaitForPuback)) - { - // we haven't received PUBACK, we need to resend PUBLISH message - msgContext.State = MqttMsgState.QueuedQos1; - } - // it's QoS 2 - else if (msgContext.Message.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE) - { - // we haven't received PUBREC, we need to resend PUBLISH message - if (msgContext.State == MqttMsgState.WaitForPubrec) - { - msgContext.State = MqttMsgState.QueuedQos2; - } - // we haven't received PUBCOMP, we need to resend PUBREL for it - else if (msgContext.State == MqttMsgState.WaitForPubcomp) - { - msgContext.State = MqttMsgState.SendPubrel; - } - } - } - } - } - - // unlock process inflight queue - this.inflightWaitHandle.Set(); - } - else - { - // create new session - this.session = new MqttClientSession(this.ClientId); - } - } - // clean any previous session - else - { - if (this.session != null) - this.session.Clear(); - } - } - -#if BROKER - - /// - /// Load a given session - /// - /// MQTT Client session to load - public void LoadSession(MqttClientSession session) - { - // if not clean session - if (!this.CleanSession) - { - // set the session ... - this.session = session; - // ... and restore it - this.RestoreSession(); - } - } -#endif - - /// - /// Generate the next message identifier - /// - /// Message identifier - private ushort GetMessageId() - { - // if 0 or max UInt16, it becomes 1 (first valid messageId) - this.messageIdCounter = ((this.messageIdCounter % UInt16.MaxValue) != 0) ? (ushort)(this.messageIdCounter + 1) : (ushort)1; - return this.messageIdCounter; - } - - /// - /// Finder class for PUBLISH message inside a queue - /// - internal class MqttMsgContextFinder - { - // PUBLISH message id - internal ushort MessageId { get; set; } - // message flow into inflight queue - internal MqttMsgFlow Flow { get; set; } - - /// - /// Constructor - /// - /// Message Id - /// Message flow inside inflight queue - internal MqttMsgContextFinder(ushort messageId, MqttMsgFlow flow) - { - this.MessageId = messageId; - this.Flow = flow; - } - - internal bool Find(object item) - { - MqttMsgContext msgCtx = (MqttMsgContext)item; - return ((msgCtx.Message.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && - (msgCtx.Message.MessageId == this.MessageId) && - msgCtx.Flow == this.Flow); - - } - } - } - - /// - /// MQTT protocol version - /// - public enum MqttProtocolVersion - { - Version_3_1 = MqttMsgConnect.PROTOCOL_VERSION_V3_1, - Version_3_1_1 = MqttMsgConnect.PROTOCOL_VERSION_V3_1_1 - } -} diff --git a/mqtt/M2Mqtt/MqttSecurity.cs b/mqtt/M2Mqtt/MqttSecurity.cs deleted file mode 100644 index b19f108..0000000 --- a/mqtt/M2Mqtt/MqttSecurity.cs +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -namespace uPLibrary.Networking.M2Mqtt -{ - /// - /// Supported SSL/TLS protocol versions - /// - public enum MqttSslProtocols - { - None, - SSLv3, - TLSv1_0, - TLSv1_1, - TLSv1_2 - } -} diff --git a/mqtt/M2Mqtt/MqttSettings.cs b/mqtt/M2Mqtt/MqttSettings.cs deleted file mode 100644 index 994f622..0000000 --- a/mqtt/M2Mqtt/MqttSettings.cs +++ /dev/null @@ -1,104 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -namespace uPLibrary.Networking.M2Mqtt -{ - /// - /// Settings class for the MQTT broker - /// - 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; - - /// - /// Listening connection port - /// - public int Port { get; internal set; } - - /// - /// Listening connection SSL port - /// - public int SslPort { get; internal set; } - - /// - /// Timeout on client connection (before receiving CONNECT message) - /// - public int TimeoutOnConnection { get; internal set; } - - /// - /// Timeout on receiving - /// - public int TimeoutOnReceiving { get; internal set; } - - /// - /// Attempts on retry - /// - public int AttemptsOnRetry { get; internal set; } - - /// - /// Delay on retry - /// - public int DelayOnRetry { get; internal set; } - - /// - /// Inflight queue size - /// - public int InflightQueueSize { get; set; } - - /// - /// Singleton instance of settings - /// - public static MqttSettings Instance - { - get - { - if (instance == null) - instance = new MqttSettings(); - return instance; - } - } - - // singleton instance - private static MqttSettings instance; - - /// - /// Constructor - /// - 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; - } - } -} diff --git a/mqtt/M2Mqtt/Net/Fx.cs b/mqtt/M2Mqtt/Net/Fx.cs deleted file mode 100644 index 3fcc505..0000000 --- a/mqtt/M2Mqtt/Net/Fx.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System.Threading; - -namespace uPLibrary.Networking.M2Mqtt -{ - /// - /// Support methods fos specific framework - /// - public class Fx - { - public static void StartThread(ThreadStart threadStart) - { - new Thread(threadStart).Start(); - } - - public static void SleepThread(int millisecondsTimeout) - { - Thread.Sleep(millisecondsTimeout); - } - } -} diff --git a/mqtt/M2Mqtt/Net/MqttNetworkChannel.cs b/mqtt/M2Mqtt/Net/MqttNetworkChannel.cs deleted file mode 100644 index c98879a..0000000 --- a/mqtt/M2Mqtt/Net/MqttNetworkChannel.cs +++ /dev/null @@ -1,472 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -#if SSL -#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; -#endif -#endif -using System.Net.Sockets; -using System.Net; -using System.Security.Cryptography.X509Certificates; -using System; -//using System.Security.Authentication; -//using System.Net.Security; - -namespace uPLibrary.Networking.M2Mqtt -{ - /// - /// Channel to communicate over the network - /// - 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; -#endif - // remote host information - private string remoteHostName; - private IPAddress remoteIpAddress; - private int remotePort; - - // socket for communication - private Socket socket; - // using SSL - private bool secure; - - // CA certificate (on client) - private X509Certificate caCert; - // Server certificate (on broker) - private X509Certificate serverCert; - // client certificate (on client) - private X509Certificate clientCert; - - // SSL/TLS protocol version - private MqttSslProtocols sslProtocol; - - /// - /// Remote host name - /// - public string RemoteHostName { get { return this.remoteHostName; } } - - /// - /// Remote IP address - /// - public IPAddress RemoteIpAddress { get { return this.remoteIpAddress; } } - - /// - /// Remote port - /// - public int RemotePort { get { return this.remotePort; } } - -#if SSL - // SSL stream - private SslStream sslStream; -#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) - private NetworkStream netStream; -#endif -#endif - - /// - /// Data available on the channel - /// - public bool DataAvailable - { - get - { -#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); -#else - if (secure) - return this.netStream.DataAvailable; - else - return (this.socket.Available > 0); -#endif -#else - return (this.socket.Available > 0); -#endif - } - } - - /// - /// Constructor - /// - /// Socket opened with the client - 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 - : this(socket, false, null, MqttSslProtocols.None) -#endif - { - - } - - /// - /// Constructor - /// - /// Socket opened with the client - /// Secure connection (SSL/TLS) - /// Server X509 certificate for secure connection - /// SSL/TLS protocol version -#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - /// A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party - /// A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication - public MqttNetworkChannel(Socket socket, bool 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; -#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - this.userCertificateValidationCallback = userCertificateValidationCallback; - this.userCertificateSelectionCallback = userCertificateSelectionCallback; -#endif - } - - /// - /// Constructor - /// - /// Remote Host name - /// Remote port - public MqttNetworkChannel(string remoteHostName, int 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 - { - } - - /// - /// Constructor - /// - /// Remote Host name - /// Remote port - /// Using SSL - /// CA certificate - /// Client certificate - /// SSL/TLS protocol version -#if !(MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || COMPACT_FRAMEWORK) - /// A RemoteCertificateValidationCallback delegate responsible for validating the certificate supplied by the remote party - /// A LocalCertificateSelectionCallback delegate responsible for selecting the certificate used for authentication - public MqttNetworkChannel(string remoteHostName, int remotePort, bool 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 - { - } - - // 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"); - } - } - - 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 - } - - /// - /// Connect to remote server - /// - 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) - this.sslStream = new SslStream(this.socket); -#else - 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) - 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 - } - - /// - /// Send data on the network channel - /// - /// Data buffer to send - /// Number of byte sent - public int 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); -#else - return this.socket.Send(buffer, 0, buffer.Length, SocketFlags.None); -#endif - } - - /// - /// Receive data from the network - /// - /// Data buffer for receiving data - /// Number of bytes received - public int 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; - } -#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; -#endif - } - - /// - /// Receive data from the network channel with a specified timeout - /// - /// Data buffer for receiving data - /// Timeout on receiving (in milliseconds) - /// Number of bytes received - 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; - } - } - - /// - /// Close the network channel - /// - 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 - } - - /// - /// Accept connection from a remote client - /// - 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 - } - } - - /// - /// IPAddress Utility class - /// - public static class IPAddressUtility - { - /// - /// Return AddressFamily for the IP address - /// - /// IP address to check - /// Address family - public static AddressFamily GetAddressFamily(IPAddress ipAddress) - { -#if (!MF_FRAMEWORK_VERSION_V4_2 && !MF_FRAMEWORK_VERSION_V4_3) - return ipAddress.AddressFamily; -#else - return (ipAddress.ToString().IndexOf(':') != -1) ? - AddressFamily.InterNetworkV6 : AddressFamily.InterNetwork; -#endif - } - } - - /// - /// MQTT SSL utility class - /// - public static class MqttSslUtility - { -#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) - { - switch (mqttSslProtocol) - { - case MqttSslProtocols.None: - return SslProtocols.None; - case MqttSslProtocols.SSLv3: - return SslProtocols.SSLv3; - case MqttSslProtocols.TLSv1_0: - return SslProtocols.TLSv1; - case MqttSslProtocols.TLSv1_1: - case MqttSslProtocols.TLSv1_2: - default: - throw new ArgumentException("SSL/TLS protocol version not supported"); - } - } -#endif - } -} diff --git a/mqtt/M2Mqtt/Properties/AssemblyInfo.cs b/mqtt/M2Mqtt/Properties/AssemblyInfo.cs deleted file mode 100644 index b218618..0000000 --- a/mqtt/M2Mqtt/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("M2Mqtt")] -[assembly: AssemblyDescription("MQTT Client Library for M2M communication")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Paolo Patierno")] -[assembly: AssemblyProduct("M2Mqtt")] -[assembly: AssemblyCopyright("Copyright © Paolo Patierno 2014")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -[assembly: AssemblyVersion("4.3.0.0")] -// to avoid compilation error (AssemblyFileVersionAttribute doesn't exist) under .Net CF 3.5 -#if !WindowsCE -[assembly: AssemblyFileVersion("4.3.0.0")] -#endif \ No newline at end of file diff --git a/mqtt/M2Mqtt/Session/MqttBrokerSession.cs b/mqtt/M2Mqtt/Session/MqttBrokerSession.cs deleted file mode 100644 index 859213c..0000000 --- a/mqtt/M2Mqtt/Session/MqttBrokerSession.cs +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -#if BROKER -using System.Collections; -using System.Collections.Generic; -using uPLibrary.Networking.M2Mqtt.Managers; -using uPLibrary.Networking.M2Mqtt.Messages; - -namespace uPLibrary.Networking.M2Mqtt.Session -{ - /// - /// MQTT Broker Session - /// - public class MqttBrokerSession : MqttSession - { - /// - /// Client related to the subscription - /// - public MqttClient Client { get; set; } - - /// - /// Subscriptions for the client session - /// - public List Subscriptions; - - /// - /// Outgoing messages to publish - /// - public Queue OutgoingMessages; - - /// - /// Constructor - /// - public MqttBrokerSession() - : base() - { - this.Client = null; - this.Subscriptions = new List(); - this.OutgoingMessages = new Queue(); - } - - public override void Clear() - { - base.Clear(); - this.Client = null; - this.Subscriptions.Clear(); - this.OutgoingMessages.Clear(); - } - } -} -#endif \ No newline at end of file diff --git a/mqtt/M2Mqtt/Session/MqttClientSession.cs b/mqtt/M2Mqtt/Session/MqttClientSession.cs deleted file mode 100644 index 7613880..0000000 --- a/mqtt/M2Mqtt/Session/MqttClientSession.cs +++ /dev/null @@ -1,33 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -namespace uPLibrary.Networking.M2Mqtt.Session -{ - /// - /// MQTT Client Session - /// - public class MqttClientSession : MqttSession - { - /// - /// Constructor - /// - /// Client Id to create session - public MqttClientSession(string clientId) - : base(clientId) - { - } - } -} diff --git a/mqtt/M2Mqtt/Session/MqttSession.cs b/mqtt/M2Mqtt/Session/MqttSession.cs deleted file mode 100644 index 712a854..0000000 --- a/mqtt/M2Mqtt/Session/MqttSession.cs +++ /dev/null @@ -1,63 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System.Collections; - -namespace uPLibrary.Networking.M2Mqtt.Session -{ - /// - /// MQTT Session base class - /// - public abstract class MqttSession - { - /// - /// Client Id - /// - public string ClientId { get; set; } - - /// - /// Messages inflight during session - /// - public Hashtable InflightMessages { get; set; } - - /// - /// Constructor - /// - public MqttSession() - : this(null) - { - } - - /// - /// Constructor - /// - /// Client Id to create session - public MqttSession(string clientId) - { - this.ClientId = clientId; - this.InflightMessages = new Hashtable(); - } - - /// - /// Clean session - /// - public virtual void Clear() - { - this.ClientId = null; - this.InflightMessages.Clear(); - } - } -} diff --git a/mqtt/M2Mqtt/Utility/QueueExtension.cs b/mqtt/M2Mqtt/Utility/QueueExtension.cs deleted file mode 100644 index 70175c3..0000000 --- a/mqtt/M2Mqtt/Utility/QueueExtension.cs +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using System.Collections; - -namespace uPLibrary.Networking.M2Mqtt.Utility -{ - /// - /// Extension class for a Queue - /// - internal static class QueueExtension - { - /// - /// Predicate for searching inside a queue - /// - /// Item of the queue - /// Result of predicate - internal delegate bool QueuePredicate(object item); - - /// - /// Get (without removing) an item from queue based on predicate - /// - /// Queue in which to search - /// Predicate to verify to get item - /// Item matches the predicate - internal static object Get(Queue queue, QueuePredicate predicate) - { - foreach (var item in queue) - { - if (predicate(item)) - return item; - } - return null; - } - } -} diff --git a/mqtt/M2Mqtt/Utility/Trace.cs b/mqtt/M2Mqtt/Utility/Trace.cs deleted file mode 100644 index c299ebe..0000000 --- a/mqtt/M2Mqtt/Utility/Trace.cs +++ /dev/null @@ -1,86 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System.Diagnostics; - -namespace uPLibrary.Networking.M2Mqtt.Utility -{ - /// - /// Tracing levels - /// - 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); - - /// - /// Tracing class - /// - 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); - } - } - } -} \ No newline at end of file diff --git a/mqtt/M2Mqtt/WinRT/Fx.cs b/mqtt/M2Mqtt/WinRT/Fx.cs deleted file mode 100644 index 6d62d28..0000000 --- a/mqtt/M2Mqtt/WinRT/Fx.cs +++ /dev/null @@ -1,36 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System.Threading; -using System.Threading.Tasks; - -namespace uPLibrary.Networking.M2Mqtt -{ - /// - /// Support methods fos specific framework - /// - public class Fx - { - - public delegate void ThreadStart(); - public static void StartThread(ThreadStart threadStart) - { - Task.Factory.StartNew(o => ((ThreadStart)o)(), threadStart); - } - - public static void SleepThread(int millisecondsTimeout) { Task.Delay(millisecondsTimeout).RunSynchronously(); } - } -} diff --git a/mqtt/M2Mqtt/WinRT/Hashtable.cs b/mqtt/M2Mqtt/WinRT/Hashtable.cs deleted file mode 100644 index a42532b..0000000 --- a/mqtt/M2Mqtt/WinRT/Hashtable.cs +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System.Collections.Generic; - -namespace uPLibrary.Networking.M2Mqtt -{ - /// - /// Wrapper Hashtable class for generic Dictionary (the only available in WinRT) - /// - public class Hashtable : Dictionary - { - } -} diff --git a/mqtt/M2Mqtt/WinRT/MqttNetworkChannel.cs b/mqtt/M2Mqtt/WinRT/MqttNetworkChannel.cs deleted file mode 100644 index 305992c..0000000 --- a/mqtt/M2Mqtt/WinRT/MqttNetworkChannel.cs +++ /dev/null @@ -1,179 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using Windows.Networking; -using Windows.Networking.Sockets; -using System.Runtime.InteropServices.WindowsRuntime; -using Windows.Storage.Streams; -using System.Threading; - -namespace uPLibrary.Networking.M2Mqtt -{ - public class MqttNetworkChannel : IMqttNetworkChannel - { - // stream socket for communication - private StreamSocket socket; - - // remote host information - private HostName remoteHostName; - private int remotePort; - - // using SSL - private bool secure; - - // SSL/TLS protocol version - private MqttSslProtocols sslProtocol; - - /// - /// Constructor - /// - /// Socket opened with the client - public MqttNetworkChannel(StreamSocket socket) - { - this.socket = socket; - this.sslProtocol = MqttSslProtocols.None; - } - - /// - /// Constructor - /// - /// Remote Host name - /// Remote port - /// Using SSL - /// SSL/TLS protocol version - public MqttNetworkChannel(string remoteHostName, int remotePort, bool secure, MqttSslProtocols sslProtocol) - { - this.remoteHostName = new HostName(remoteHostName); - this.remotePort = remotePort; - this.secure = secure; - this.sslProtocol = sslProtocol; - - if (secure && (sslProtocol == MqttSslProtocols.None)) - throw new ArgumentException("For secure connection, an SSL/TLS protocol version is needed"); - } - - public bool DataAvailable - { - get { return true; } - } - - public int Receive(byte[] buffer) - { - IBuffer result; - - // read all data needed (until fill buffer) - int idx = 0; - while (idx < buffer.Length) - { - // fixed scenario with socket closed gracefully by peer/broker and - // Read return 0. Avoid infinite loop. - - // read is executed synchronously - result = this.socket.InputStream.ReadAsync(buffer.AsBuffer(), (uint)buffer.Length, InputStreamOptions.None).AsTask().Result; - if (result.Length == 0) - return 0; - idx += (int)result.Length; - } - return buffer.Length; - } - - public int Receive(byte[] buffer, int timeout) - { - CancellationTokenSource cts = new CancellationTokenSource(timeout); - - try - { - IBuffer result; - - // read all data needed (until fill buffer) - int idx = 0; - while (idx < buffer.Length) - { - // fixed scenario with socket closed gracefully by peer/broker and - // Read return 0. Avoid infinite loop. - - // read is executed synchronously - result = this.socket.InputStream.ReadAsync(buffer.AsBuffer(), (uint)buffer.Length, InputStreamOptions.None).AsTask(cts.Token).Result; - if (result.Length == 0) - return 0; - idx += (int)result.Length; - } - return buffer.Length; - } - catch (TaskCanceledException) - { - return 0; - } - } - - public int Send(byte[] buffer) - { - // send is executed synchronously - return (int)this.socket.OutputStream.WriteAsync(buffer.AsBuffer()).AsTask().Result; - } - - public void Close() - { - this.socket.Dispose(); - } - - public void Connect() - { - this.socket = new StreamSocket(); - - // connection is executed synchronously - this.socket.ConnectAsync(this.remoteHostName, - this.remotePort.ToString(), - MqttSslUtility.ToSslPlatformEnum(this.sslProtocol)).AsTask().Wait(); - } - - public void Accept() - { - // TODO : SSL support with StreamSocket / StreamSocketListener seems to be NOT supported - return; - } - } - - /// - /// MQTT SSL utility class - /// - public static class MqttSslUtility - { - public static SocketProtectionLevel ToSslPlatformEnum(MqttSslProtocols mqttSslProtocol) - { - switch (mqttSslProtocol) - { - case MqttSslProtocols.None: - return SocketProtectionLevel.PlainSocket; - case MqttSslProtocols.SSLv3: - return SocketProtectionLevel.SslAllowNullEncryption; - case MqttSslProtocols.TLSv1_0: - return SocketProtectionLevel.Tls10; - case MqttSslProtocols.TLSv1_1: - return SocketProtectionLevel.Tls11; - case MqttSslProtocols.TLSv1_2: - return SocketProtectionLevel.Tls12; - default: - throw new ArgumentException("SSL/TLS protocol version not supported"); - } - } - } -} diff --git a/mqtt/M2Mqtt/WinRT/Queue.cs b/mqtt/M2Mqtt/WinRT/Queue.cs deleted file mode 100644 index bc6728f..0000000 --- a/mqtt/M2Mqtt/WinRT/Queue.cs +++ /dev/null @@ -1,27 +0,0 @@ -/* -Copyright (c) 2013, 2014 Paolo Patierno - -All rights reserved. This program and the accompanying materials -are made available under the terms of the Eclipse Public License v1.0 -and Eclipse Distribution License v1.0 which accompany this distribution. - -The Eclipse Public License is available at - http://www.eclipse.org/legal/epl-v10.html -and the Eclipse Distribution License is available at - http://www.eclipse.org/org/documents/edl-v10.php. - -Contributors: - Paolo Patierno - initial API and implementation and/or initial documentation -*/ - -using System.Collections.Generic; - -namespace uPLibrary.Networking.M2Mqtt -{ - /// - /// Wrapper Queue class for generic Queue (the only available in WinRT) - /// - public class Queue : Queue - { - } -} diff --git a/mqtt/M2Mqtt_2.sln b/mqtt/M2Mqtt_2.sln deleted file mode 100644 index aa2f81e..0000000 --- a/mqtt/M2Mqtt_2.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2010 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "M2Mqtt_2", "M2Mqtt\M2Mqtt_2.csproj", "{A11AEF5A-B246-4FE8-8330-06DB73CC8074}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {135814CF-A469-4436-9C51-3CFE4B93D2FE} - EndGlobalSection -EndGlobal diff --git a/mqtt/M2Mqtt_4.7.1.sln b/mqtt/M2Mqtt_4.7.1.sln deleted file mode 100644 index c30b7f6..0000000 --- a/mqtt/M2Mqtt_4.7.1.sln +++ /dev/null @@ -1,25 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 15 -VisualStudioVersion = 15.0.27004.2010 -MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "M2Mqtt", "M2Mqtt\M2Mqtt_4.7.1.csproj", "{A11AEF5A-B246-4FE8-8330-06DB73CC8074}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A11AEF5A-B246-4FE8-8330-06DB73CC8074}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {135814CF-A469-4436-9C51-3CFE4B93D2FE} - EndGlobalSection -EndGlobal