/// <summary>
        /// Parse bytes for a CONNACK message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>CONNACK message instance</returns>
        public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[]         buffer;
            MqttMsgConnack msg = new MqttMsgConnack();

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] check flag bits
                if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_CONNACK_FLAG_BITS)
                {
                    throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
                }
            }

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            channel.Receive(buffer);
            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] ... set session present flag ...
                msg.sessionPresent = (buffer[CONN_ACK_FLAGS_BYTE_OFFSET] & SESSION_PRESENT_FLAG_MASK) != 0x00;
            }
            // ...and set return code from broker
            msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];

            return(msg);
        }
        public static MqttMsgPuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            int           num1           = 0;
            MqttMsgPuback mqttMsgPuback1 = new MqttMsgPuback();

            if (protocolVersion == (byte)4 && ((uint)fixedHeaderFirstByte & 15U) > 0U)
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
            }
            byte[] buffer = new byte[MqttMsgBase.decodeRemainingLength(channel)];
            channel.Receive(buffer);
            MqttMsgPuback mqttMsgPuback2 = mqttMsgPuback1;

            byte[] numArray1 = buffer;
            int    index1    = num1;
            int    num2      = checked (index1 + 1);
            int    num3      = (int)checked ((ushort)((int)numArray1[index1] << 8 & 65280));

            mqttMsgPuback2.messageId = (ushort)num3;
            MqttMsgPuback mqttMsgPuback3 = mqttMsgPuback1;
            int           messageId      = (int)mqttMsgPuback3.messageId;

            byte[] numArray2 = buffer;
            int    index2    = num2;
            int    num4      = checked (index2 + 1);
            int    num5      = (int)numArray2[index2];

            mqttMsgPuback3.messageId = (ushort)(messageId | num5);
            return(mqttMsgPuback1);
        }
示例#3
0
        /// <summary>
        /// Parse bytes for a SUBACK message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>SUBACK message instance</returns>
        public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel)
        {
            byte[]        buffer;
            int           index = 0;
            MqttMsgSuback msg   = new MqttMsgSuback();

            // 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);
        }
        /// <summary>
        /// Parse bytes for a PUBREC message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBREC message instance</returns>
        public static MqttMsgPubrec Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[]        buffer;
            int           index = 0;
            MqttMsgPubrec msg   = new MqttMsgPubrec();

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] check flag bits
                if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREC_FLAG_BITS)
                {
                    throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
                }
            }

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            channel.Receive(buffer);

            // message id
            msg.messageId  = (ushort)((buffer[index++] << 8) & 0xFF00);
            msg.messageId |= (buffer[index++]);

            return(msg);
        }
示例#5
0
        /// <summary>
        /// Parse bytes for a PUBREL message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="socket">Socket connected to the broker</param>
        /// <returns>PUBREL message instance</returns>
        public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, Socket socket)
        {
            byte[]        buffer;
            int           index = 0;
            MqttMsgPubrel msg   = new MqttMsgPubrel();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(socket);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            socket.Receive(buffer);

            // 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);
        }
示例#6
0
        public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            int           num1           = 0;
            MqttMsgPubrel mqttMsgPubrel1 = new MqttMsgPubrel();

            if (protocolVersion == (byte)4 && ((int)fixedHeaderFirstByte & 15) != 2)
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
            }
            byte[] buffer = new byte[MqttMsgBase.decodeRemainingLength(channel)];
            channel.Receive(buffer);
            if (protocolVersion == (byte)3)
            {
                mqttMsgPubrel1.qosLevel = checked ((byte)(((int)fixedHeaderFirstByte & 6) >> 1));
                mqttMsgPubrel1.dupFlag  = ((int)fixedHeaderFirstByte & 8) >> 3 == 1;
            }
            MqttMsgPubrel mqttMsgPubrel2 = mqttMsgPubrel1;

            byte[] numArray1 = buffer;
            int    index1    = num1;
            int    num2      = checked (index1 + 1);
            int    num3      = (int)checked ((ushort)((int)numArray1[index1] << 8 & 65280));

            mqttMsgPubrel2.messageId = (ushort)num3;
            MqttMsgPubrel mqttMsgPubrel3 = mqttMsgPubrel1;
            int           messageId      = (int)mqttMsgPubrel3.messageId;

            byte[] numArray2 = buffer;
            int    index2    = num2;
            int    num4      = checked (index2 + 1);
            int    num5      = (int)numArray2[index2];

            mqttMsgPubrel3.messageId = (ushort)(messageId | num5);
            return(mqttMsgPubrel1);
        }
示例#7
0
        /// <summary>
        /// Parse bytes for a UNSUBSCRIBE message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>UNSUBSCRIBE message instance</returns>
        public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int    index = 0;

            byte[]             topicUtf8;
            int                topicUtf8Length;
            MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            //int received = channel.Receive(buffer);
            channel.Receive(buffer);

            // 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 <String> tmpTopics = new List <String>();
#endif
            do
            {
                // topic name
                topicUtf8Length  = ((buffer[index++] << 8) & 0xFF00);
                topicUtf8Length |= buffer[index++];
                topicUtf8        = new byte[topicUtf8Length];
                Array.Copy(buffer, index, topicUtf8, 0, topicUtf8Length);
                index += topicUtf8Length;
                tmpTopics.Add(new String(Encoding.UTF8.GetChars(topicUtf8)));
            } while (index < remainingLength);

            // copy from list to array
            msg.topics = new string[tmpTopics.Count];
            for (int i = 0; i < tmpTopics.Count; i++)
            {
                msg.topics[i] = (string)tmpTopics[i];
            }

            return(msg);
        }
示例#8
0
        /// <summary>
        /// Parse bytes for a PINGRESP message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="socket">Socket connected to the broker</param>
        /// <returns>PINGRESP message instance</returns>
        public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, Socket socket)
        {
            MqttMsgPingResp msg = new MqttMsgPingResp();

            // already know remaininglength is zero (MQTT specification),
            // so it isn't necessary to read other data from socket
            int remainingLength = MqttMsgBase.decodeRemainingLength(socket);

            return(msg);
        }
        public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            MqttMsgPingResp mqttMsgPingResp = new MqttMsgPingResp();

            if (protocolVersion == (byte)4 && ((uint)fixedHeaderFirstByte & 15U) > 0U)
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
            }
            MqttMsgBase.decodeRemainingLength(channel);
            return(mqttMsgPingResp);
        }
示例#10
0
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, Socket socket)
        {
            byte[] buffer;
            int    index = 0;

            byte[]         topicUtf8;
            int            topicUtf8Length;
            MqttMsgPublish msg = new MqttMsgPublish();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(socket);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            socket.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);
            // 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  = (ushort)((buffer[index++] << 8) & 0xFF00);
                msg.messageId |= (buffer[index++]);
            }

            // get payload with message data
            msg.message = new byte[remainingLength - index];
            Array.Copy(buffer, index, msg.message, 0, msg.message.Length);

            return(msg);
        }
        /// <summary>
        /// Parse bytes for a CONNACK message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>CONNACK message instance</returns>
        public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel)
        {
            byte[]         buffer;
            MqttMsgConnack msg = new MqttMsgConnack();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            channel.Receive(buffer);
            // ...and set return code from broker
            msg.returnCode = buffer[CONN_RETURN_CODE_BYTE_OFFSET];

            return(msg);
        }
示例#12
0
        public static MqttMsgConnack Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            MqttMsgConnack mqttMsgConnack = new MqttMsgConnack();

            if (protocolVersion == (byte)4 && ((uint)fixedHeaderFirstByte & 15U) > 0U)
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
            }
            byte[] buffer = new byte[MqttMsgBase.decodeRemainingLength(channel)];
            channel.Receive(buffer);
            if (protocolVersion == (byte)4)
            {
                mqttMsgConnack.sessionPresent = ((uint)buffer[0] & 1U) > 0U;
            }
            mqttMsgConnack.returnCode = buffer[1];
            return(mqttMsgConnack);
        }
示例#13
0
        /// <summary>
        /// Parse bytes for a DISCONNECT message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>DISCONNECT message instance</returns>
        public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            MqttMsgDisconnect msg = new MqttMsgDisconnect();

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] check flag bits
                if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS)
                {
                    throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
                }
            }

            // get remaining length and allocate buffer
            MqttMsgBase.decodeRemainingLength(channel);
            // NOTE : remainingLength must be 0

            return(msg);
        }
示例#14
0
        /// <summary>
        /// Parse bytes for a PINGRESP message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PINGRESP message instance</returns>
        public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            MqttMsgPingResp msg = new MqttMsgPingResp();

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] check flag bits
                if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PINGRESP_FLAG_BITS)
                {
                    throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
                }
            }

            // already know remaininglength is zero (MQTT specification),
            // so it isn't necessary to read other data from socket
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            return(msg);
        }
示例#15
0
        /// <summary>
        /// Parse bytes for a UNSUBACK message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="socket">Socket connected to the broker</param>
        /// <returns>UNSUBACK message instance</returns>
        public static MqttMsgUnsuback Parse(byte fixedHeaderFirstByte, Socket socket)
        {
            byte[]          buffer;
            int             index = 0;
            MqttMsgUnsuback msg   = new MqttMsgUnsuback();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(socket);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            socket.Receive(buffer);

            // message id
            msg.messageId  = (ushort)((buffer[index++] << 8) & 0xFF00);
            msg.messageId |= (buffer[index++]);

            return(msg);
        }
示例#16
0
        /// <summary>
        /// Parse bytes for a PUBREL message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBREL message instance</returns>
        public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[]        buffer;
            int           index = 0;
            MqttMsgPubrel msg   = new MqttMsgPubrel();

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] check flag bits
                if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_PUBREL_FLAG_BITS)
                {
                    throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
                }
            }

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            channel.Receive(buffer);

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
            {
                // only 3.1.0

                // read QoS level from fixed header (would be QoS Level 1)
                msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
                // read DUP flag from fixed header
                msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
            }

            // message id
            msg.messageId  = (ushort)((buffer[index++] << 8) & 0xFF00);
            msg.messageId |= (buffer[index++]);

            return(msg);
        }
示例#17
0
        /// <summary>
        /// Parse bytes for a SUBACK message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>SUBACK message instance</returns>
        public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[]        buffer;
            int           index = 0;
            MqttMsgSuback msg   = new MqttMsgSuback();

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] check flag bits
                if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBACK_FLAG_BITS)
                {
                    throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
                }
            }

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            channel.Receive(buffer);

            // message id
            msg.messageId  = (ushort)((buffer[index++] << 8) & 0xFF00);
            msg.messageId |= (buffer[index++]);

            // payload contains QoS levels granted
            msg.grantedQosLevels = new byte[remainingLength - MESSAGE_ID_SIZE];
            int qosIdx = 0;

            do
            {
                msg.grantedQosLevels[qosIdx++] = buffer[index++];
            } while (index < remainingLength);

            return(msg);
        }
示例#18
0
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            int            num1            = 0;
            MqttMsgPublish mqttMsgPublish1 = new MqttMsgPublish();
            int            length1         = MqttMsgBase.decodeRemainingLength(channel);

            byte[] buffer = new byte[length1];
            int    num2   = channel.Receive(buffer);

            byte[] numArray1 = buffer;
            int    index1    = num1;
            int    num3      = checked (index1 + 1);
            int    num4      = (int)numArray1[index1] << 8 & 65280;

            byte[] numArray2    = buffer;
            int    index2       = num3;
            int    sourceIndex1 = checked (index2 + 1);
            int    num5         = (int)numArray2[index2];
            int    length2      = num4 | num5;

            byte[] bytes = new byte[length2];
            Array.Copy((Array)buffer, sourceIndex1, (Array)bytes, 0, length2);
            int sourceIndex2 = checked (sourceIndex1 + length2);

            mqttMsgPublish1.topic    = new string(Encoding.UTF8.GetChars(bytes));
            mqttMsgPublish1.qosLevel = checked ((byte)(((int)fixedHeaderFirstByte & 6) >> 1));
            if (mqttMsgPublish1.qosLevel > (byte)2)
            {
                throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
            }
            mqttMsgPublish1.dupFlag = ((int)fixedHeaderFirstByte & 8) >> 3 == 1;
            mqttMsgPublish1.retain  = ((int)fixedHeaderFirstByte & 1) == 1;
            if (mqttMsgPublish1.qosLevel == (byte)1 || mqttMsgPublish1.qosLevel == (byte)2)
            {
                MqttMsgPublish mqttMsgPublish2 = mqttMsgPublish1;
                byte[]         numArray3       = buffer;
                int            index3          = sourceIndex2;
                int            num6            = checked (index3 + 1);
                int            num7            = (int)checked ((ushort)((int)numArray3[index3] << 8 & 65280));
                mqttMsgPublish2.messageId = (ushort)num7;
                MqttMsgPublish mqttMsgPublish3 = mqttMsgPublish1;
                int            messageId       = (int)mqttMsgPublish3.messageId;
                byte[]         numArray4       = buffer;
                int            index4          = num6;
                sourceIndex2 = checked (index4 + 1);
                int num8 = (int)numArray4[index4];
                mqttMsgPublish3.messageId = (ushort)(messageId | num8);
            }
            int length3           = checked (length1 - sourceIndex2);
            int num9              = length3;
            int destinationIndex1 = 0;

            mqttMsgPublish1.message = new byte[length3];
            Array.Copy((Array)buffer, sourceIndex2, (Array)mqttMsgPublish1.message, destinationIndex1, checked (num2 - sourceIndex2));
            int num10             = checked (num9 - num2 - sourceIndex2);
            int destinationIndex2 = checked (destinationIndex1 + num2 - sourceIndex2);

            while (num10 > 0)
            {
                int length4 = channel.Receive(buffer);
                Array.Copy((Array)buffer, 0, (Array)mqttMsgPublish1.message, destinationIndex2, length4);
                checked { num10 -= length4; }
                checked { destinationIndex2 += length4; }
            }
            return(mqttMsgPublish1);
        }
        /// <summary>
        /// Parse bytes for a SUBSCRIBE message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>SUBSCRIBE message instance</returns>
        public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int    index = 0;

            byte[]           topicUtf8;
            int              topicUtf8Length;
            MqttMsgSubscribe msg = new MqttMsgSubscribe();

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1_1)
            {
                // [v3.1.1] check flag bits
                if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_SUBSCRIBE_FLAG_BITS)
                {
                    throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
                }
            }

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            int received = channel.Receive(buffer);

            if (protocolVersion == MqttMsgConnect.PROTOCOL_VERSION_V3_1)
            {
                // only 3.1.0

                // read QoS level from fixed header
                msg.qosLevel = (byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
                // read DUP flag from fixed header
                msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
                // retain flag not used
                msg.retain = false;
            }

            // message id
            msg.messageId  = (ushort)((buffer[index++] << 8) & 0xFF00);
            msg.messageId |= (buffer[index++]);

            // payload contains topics and QoS levels
            // NOTE : before, I don't know how many topics will be in the payload (so use List)

// if .Net Micro Framework
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
            IList tmpTopics    = new ArrayList();
            IList tmpQosLevels = new ArrayList();
// else other frameworks (.Net, .Net Compact, Mono, Windows Phone)
#else
            IList <String> tmpTopics    = new List <String>();
            IList <byte>   tmpQosLevels = new List <byte>();
#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);
        }
示例#20
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="msg">Related message</param>
 public MsgInternalEvent(MqttMsgBase msg)
 {
     this.msg = msg;
 }
示例#21
0
        /// <summary>
        /// Enqueue a message into the inflight queue
        /// </summary>
        /// <param name="msg">Message to enqueue</param>
        /// <param name="flow">Message flow (publish, acknowledge)</param>
        private void 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(((MqttMsgPublish)msg).MessageId, MqttMsgFlow.ToAcknowledge);
                    MqttMsgContext msgCtx = (MqttMsgContext)this.inflightQueue.Get(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;
                }

                // queue message context
                MqttMsgContext msgContext = new MqttMsgContext()
                {
                    Message = msg,
                    State = state,
                    Flow = flow,
                    Attempt = 0
                };

                lock (this.inflightQueue)
                {
                    // enqueue message and unlock send thread
                    this.inflightQueue.Enqueue(msgContext);
                }
            }

            this.inflightWaitHandle.Set();
        }
示例#22
0
        /// <summary>
        /// Parse bytes for a CONNECT message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>CONNECT message instance</returns>
        public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, 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));

            // protocol version
            msg.protocolVersion = buffer[index];
            index += PROTOCOL_VERSION_NUMBER_SIZE;

            // connect flags
            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
            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));

            // 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);
        }
示例#23
0
        public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            int            num1            = 0;
            MqttMsgConnect mqttMsgConnect1 = new MqttMsgConnect();

            byte[] buffer = new byte[MqttMsgBase.decodeRemainingLength(channel)];
            channel.Receive(buffer);
            byte[] numArray1 = buffer;
            int    index1    = num1;
            int    num2      = checked (index1 + 1);
            int    num3      = (int)numArray1[index1] << 8 & 65280;

            byte[] numArray2    = buffer;
            int    index2       = num2;
            int    sourceIndex1 = checked (index2 + 1);
            int    num4         = (int)numArray2[index2];
            int    length1      = num3 | num4;

            byte[] bytes1 = new byte[length1];
            Array.Copy((Array)buffer, sourceIndex1, (Array)bytes1, 0, length1);
            int index3 = checked (sourceIndex1 + length1);

            mqttMsgConnect1.protocolName = new string(Encoding.UTF8.GetChars(bytes1));
            if (!mqttMsgConnect1.protocolName.Equals("MQIsdp") && !mqttMsgConnect1.protocolName.Equals("MQTT"))
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidProtocolName);
            }
            mqttMsgConnect1.protocolVersion = buffer[index3];
            int index4 = checked (index3 + 1);

            if (mqttMsgConnect1.protocolVersion == (byte)4 && ((uint)buffer[index4] & 1U) > 0U)
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidConnectFlags);
            }
            bool flag1 = ((uint)buffer[index4] & 128U) > 0U;
            bool flag2 = ((uint)buffer[index4] & 64U) > 0U;

            mqttMsgConnect1.willRetain   = ((uint)buffer[index4] & 32U) > 0U;
            mqttMsgConnect1.willQosLevel = checked ((byte)(((int)buffer[index4] & 24) >> 3));
            mqttMsgConnect1.willFlag     = ((uint)buffer[index4] & 4U) > 0U;
            mqttMsgConnect1.cleanSession = ((uint)buffer[index4] & 2U) > 0U;
            int            num5            = checked (index4 + 1);
            MqttMsgConnect mqttMsgConnect2 = mqttMsgConnect1;

            byte[] numArray3 = buffer;
            int    index5    = num5;
            int    num6      = checked (index5 + 1);
            int    num7      = (int)checked ((ushort)((int)numArray3[index5] << 8 & 65280));

            mqttMsgConnect2.keepAlivePeriod = (ushort)num7;
            MqttMsgConnect mqttMsgConnect3 = mqttMsgConnect1;
            int            keepAlivePeriod = (int)mqttMsgConnect3.keepAlivePeriod;

            byte[] numArray4 = buffer;
            int    index6    = num6;
            int    num8      = checked (index6 + 1);
            int    num9      = (int)numArray4[index6];

            mqttMsgConnect3.keepAlivePeriod = (ushort)(keepAlivePeriod | num9);
            byte[] numArray5 = buffer;
            int    index7    = num8;
            int    num10     = checked (index7 + 1);
            int    num11     = (int)numArray5[index7] << 8 & 65280;

            byte[] numArray6    = buffer;
            int    index8       = num10;
            int    sourceIndex2 = checked (index8 + 1);
            int    num12        = (int)numArray6[index8];
            int    length2      = num11 | num12;

            byte[] bytes2 = new byte[length2];
            Array.Copy((Array)buffer, sourceIndex2, (Array)bytes2, 0, length2);
            int num13 = checked (sourceIndex2 + length2);

            mqttMsgConnect1.clientId = new string(Encoding.UTF8.GetChars(bytes2));
            if (mqttMsgConnect1.protocolVersion == (byte)4 && length2 == 0 && !mqttMsgConnect1.cleanSession)
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidClientId);
            }
            if (mqttMsgConnect1.willFlag)
            {
                byte[] numArray7    = buffer;
                int    index9       = num13;
                int    num14        = checked (index9 + 1);
                int    num15        = (int)numArray7[index9] << 8 & 65280;
                byte[] numArray8    = buffer;
                int    index10      = num14;
                int    sourceIndex3 = checked (index10 + 1);
                int    num16        = (int)numArray8[index10];
                int    length3      = num15 | num16;
                byte[] bytes3       = new byte[length3];
                Array.Copy((Array)buffer, sourceIndex3, (Array)bytes3, 0, length3);
                int num17 = checked (sourceIndex3 + length3);
                mqttMsgConnect1.willTopic = new string(Encoding.UTF8.GetChars(bytes3));
                byte[] numArray9    = buffer;
                int    index11      = num17;
                int    num18        = checked (index11 + 1);
                int    num19        = (int)numArray9[index11] << 8 & 65280;
                byte[] numArray10   = buffer;
                int    index12      = num18;
                int    sourceIndex4 = checked (index12 + 1);
                int    num20        = (int)numArray10[index12];
                int    length4      = num19 | num20;
                byte[] bytes4       = new byte[length4];
                Array.Copy((Array)buffer, sourceIndex4, (Array)bytes4, 0, length4);
                num13 = checked (sourceIndex4 + length4);
                mqttMsgConnect1.willMessage = new string(Encoding.UTF8.GetChars(bytes4));
            }
            if (flag1)
            {
                byte[] numArray7    = buffer;
                int    index9       = num13;
                int    num14        = checked (index9 + 1);
                int    num15        = (int)numArray7[index9] << 8 & 65280;
                byte[] numArray8    = buffer;
                int    index10      = num14;
                int    sourceIndex3 = checked (index10 + 1);
                int    num16        = (int)numArray8[index10];
                int    length3      = num15 | num16;
                byte[] bytes3       = new byte[length3];
                Array.Copy((Array)buffer, sourceIndex3, (Array)bytes3, 0, length3);
                num13 = checked (sourceIndex3 + length3);
                mqttMsgConnect1.username = new string(Encoding.UTF8.GetChars(bytes3));
            }
            if (flag2)
            {
                byte[] numArray7    = buffer;
                int    index9       = num13;
                int    num14        = checked (index9 + 1);
                int    num15        = (int)numArray7[index9] << 8 & 65280;
                byte[] numArray8    = buffer;
                int    index10      = num14;
                int    sourceIndex3 = checked (index10 + 1);
                int    num16        = (int)numArray8[index10];
                int    length3      = num15 | num16;
                byte[] bytes3       = new byte[length3];
                Array.Copy((Array)buffer, sourceIndex3, (Array)bytes3, 0, length3);
                int num17 = checked (sourceIndex3 + length3);
                mqttMsgConnect1.password = new string(Encoding.UTF8.GetChars(bytes3));
            }
            return(mqttMsgConnect1);
        }
示例#24
0
        /// <summary>
        /// Thread for receiving messages from broker
        /// </summary>
        private void ReceiveThread()
        {
            int readBytes;
            byte[] fixedHeaderFirstByte = new byte[1];
            byte msgType;

            while (this.isRunning)
            {
                try
                {
                    // read first byte (fixed header)
                    readBytes = this.socket.Receive(fixedHeaderFirstByte);

                    if (readBytes > 0)
                    {
                        // extract message type from received byte
                        msgType = (byte)((fixedHeaderFirstByte[0] & MqttMsgBase.MSG_TYPE_MASK) >> MqttMsgBase.MSG_TYPE_OFFSET);

                        switch (msgType)
                        {
                            // impossible, broker can't send CONNECT message
                            case MqttMsgBase.MQTT_MSG_CONNECT_TYPE:

                                throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage);

                            // CONNACK message received from broker
                            case MqttMsgBase.MQTT_MSG_CONNACK_TYPE:

                                this.msgReceived = MqttMsgConnack.Parse(fixedHeaderFirstByte[0], this.socket);
                                this.endReceiving.Set();
                                break;

                            // impossible, broker can't send PINGREQ message
                            case MqttMsgBase.MQTT_MSG_PINGREQ_TYPE:

                                throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage);

                            // CONNACK message received from broker
                            case MqttMsgBase.MQTT_MSG_PINGRESP_TYPE:

                                this.msgReceived = MqttMsgPingResp.Parse(fixedHeaderFirstByte[0], this.socket);
                                this.endReceiving.Set();
                                break;

                            // impossible, broker can't send SUBSCRIBE message
                            case MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE:

                                throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage);

                            // SUBACK message received from broker
                            case MqttMsgBase.MQTT_MSG_SUBACK_TYPE:

                                this.msgReceived = MqttMsgSuback.Parse(fixedHeaderFirstByte[0], this.socket);
                                this.endReceiving.Set();

                                // raise subscribed topic event (SUBACK message received)
                                this.OnMqttMsgSubscribed((MqttMsgSuback)this.msgReceived);

                                break;

                            // PUBLISH message received from broker
                            case MqttMsgBase.MQTT_MSG_PUBLISH_TYPE:

                                MqttMsgPublish msgReceived = MqttMsgPublish.Parse(fixedHeaderFirstByte[0], this.socket);

                                // for QoS Level 1 and 2, client sends PUBACK message to broker
                                if ((this.msgReceived.QosLevel == MqttMsgBase.QOS_LEVEL_AT_LEAST_ONCE) ||
                                    (this.msgReceived.QosLevel == MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE))
                                {
                                    MqttMsgPuback puback = new MqttMsgPuback();
                                    puback.MessageId = (msgReceived).MessageId;
                                    this.Send(puback.GetBytes());
                                }

                                // raise PUBLISH message received event
                                this.OnMqttMsgPublishReceived(msgReceived);

                                break;

                            // PUBACK message received from broker
                            case MqttMsgBase.MQTT_MSG_PUBACK_TYPE:

                                this.msgReceived = MqttMsgPuback.Parse(fixedHeaderFirstByte[0], this.socket);
                                this.endReceiving.Set();

                                // raise published message event
                                // (PUBACK received for QoS Level 1)
                                this.OnMqttMsgPublished(((MqttMsgPuback)this.msgReceived).MessageId);

                                break;

                            // PUBREC message received from broker
                            case MqttMsgBase.MQTT_MSG_PUBREC_TYPE:

                                this.msgReceived = MqttMsgPubrec.Parse(fixedHeaderFirstByte[0], this.socket);
                                this.endReceiving.Set();
                                break;

                            // impossible, broker can't send PUBREL message
                            case MqttMsgBase.MQTT_MSG_PUBREL_TYPE:

                                throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage);

                            // PUBCOMP message received from broker
                            case MqttMsgBase.MQTT_MSG_PUBCOMP_TYPE:

                                this.msgReceived = MqttMsgPubcomp.Parse(fixedHeaderFirstByte[0], this.socket);
                                this.endReceiving.Set();

                                // raise published message event
                                // (PUBCOMP received for QoS Level 2)
                                this.OnMqttMsgPublished(((MqttMsgPuback)this.msgReceived).MessageId);

                                break;

                            // impossible, broker can't send UNSUBSCRIBE message
                            case MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE:

                                throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage);

                            // UNSUBACK message received from broker
                            case MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE:

                                this.msgReceived = MqttMsgUnsuback.Parse(fixedHeaderFirstByte[0], this.socket);
                                this.endReceiving.Set();

                                // raise unsubscribed topic event
                                this.OnMqttMsgUnsubscribed(((MqttMsgUnsuback)this.msgReceived).MessageId);

                                break;

                            default:

                                throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage);
                        }

                        this.exReceiving = null;
                    }
                }
                catch (Exception)
                {
                    this.exReceiving = new MqttCommunicationException();
                }
            }
        }
示例#25
0
        /// <summary>
        /// Thread for receiving messages
        /// </summary>
        private void ReceiveThread()
        {
            int readBytes = 0;
            byte[] fixedHeaderFirstByte = new byte[1];
            byte msgType;
            
#if BROKER
            long now = 0;

            // receive thread started, broker need to receive the first message
            // (CONNECT) within a reasonable amount of time after TCP/IP connection 
            long connectTime = Environment.TickCount;
#endif

            while (this.isRunning)
            {
                try
                {
                    if (this.channel.DataAvailable)
                        // read first byte (fixed header)
                        readBytes = this.channel.Receive(fixedHeaderFirstByte);
                    else
                    {
#if BROKER
                        // client not connected (client didn't send CONNECT yet)
                        if (!this.IsConnected)
                        {
                            now = Environment.TickCount;

                            // if connect timeout exceeded ... 
                            if ((now - connectTime) >= this.settings.TimeoutOnConnection)
                            {
                                // client must close connection
                                this.Close();

                                // client raw disconnection
                                this.OnMqttMsgDisconnected();
                            }
                        }
#endif
                        // no bytes available, sleep before retry
                        readBytes = 0;
                        Thread.Sleep(10);
                    }

                    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], this.channel);
                                Trace.WriteLine(TraceLevel.Frame, "RECV {0}", connect);

                                // raise message received event
                                this.OnMqttMsgReceived(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], this.channel);
                                MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", this.msgReceived);
                                this.syncEndReceiving.Set();
                                break;
#endif

                            // PINGREQ message received
                            case MqttMsgBase.MQTT_MSG_PINGREQ_TYPE:

#if BROKER
                                this.msgReceived = MqttMsgPingReq.Parse(fixedHeaderFirstByte[0], this.channel);
                                Trace.WriteLine(TraceLevel.Frame, "RECV {0}", this.msgReceived);

                                MqttMsgPingResp pingresp = new MqttMsgPingResp();
                                this.Send(pingresp);

                                // raise message received event
                                //this.OnMqttMsgReceived(this.msgReceived);
                                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], this.channel);
                                MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", this.msgReceived);
                                this.syncEndReceiving.Set();
                                break;
#endif

                            // SUBSCRIBE message received
                            case MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE:

#if BROKER
                                MqttMsgSubscribe subscribe = MqttMsgSubscribe.Parse(fixedHeaderFirstByte[0], this.channel);
                                Trace.WriteLine(TraceLevel.Frame, "RECV {0}", subscribe);

                                // raise message received event
                                this.OnMqttMsgReceived(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], this.channel);
                                MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", suback);

                                // 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], this.channel);
                                MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", publish);

                                // 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], this.channel);
                                MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", puback);

                                // 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], this.channel);
                                MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", pubrec);

                                // 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], this.channel);
                                MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", pubrel);

                                // 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], this.channel);
                                MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", pubcomp);

                                // 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], this.channel);
                                Trace.WriteLine(TraceLevel.Frame, "RECV {0}", unsubscribe);

                                // raise message received event
                                this.OnMqttMsgReceived(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], this.channel);
                                MqttUtility.Trace.WriteLine(TraceLevel.Frame, "RECV {0}", unsuback);

                                // 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], this.channel);
                                Trace.WriteLine(TraceLevel.Frame, "RECV {0}", disconnect);

                                // raise message received event
                                this.OnMqttMsgReceived(disconnect);

                                break;
#else
                                throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage);
#endif

                            default:

                                throw new MqttClientException(MqttClientErrorCode.WrongBrokerMessage);
                        }

                        this.exReceiving = null;
                    }

                }
                catch (Exception e)
                {
                    MqttUtility.Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", e.ToString());
                    this.exReceiving = new MqttCommunicationException(e);
                }
            }
        }
示例#26
0
        /// <summary>
        /// Enqueue a message into the internal queue
        /// </summary>
        /// <param name="msg">Message to enqueue</param>
        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(((MqttMsgPubrel)msg).MessageId, MqttMsgFlow.ToAcknowledge);
                    MqttMsgContext msgCtx = (MqttMsgContext)this.inflightQueue.Get(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 = ((MqttMsgPubrel)msg).MessageId;

                        this.Send(pubcomp);

                        enqueue = false;
                    }
                }
            }

            if (enqueue)
            {
                lock (this.internalQueue)
                {
                    this.internalQueue.Enqueue(msg);
                    this.inflightWaitHandle.Set();
                }
            }
        }
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="msg">Message published</param>
 /// <param name="isPublished">Publish flag</param>
 public MsgPublishedInternalEvent(MqttMsgBase msg, bool isPublished) 
     : base(msg)
 {
     this.isPublished = isPublished;
 }
示例#28
0
        /// <summary>
        /// Wrapper method for raising message received event
        /// </summary>
        /// <param name="msg">Message received</param>
        private void OnMqttMsgReceived(MqttMsgBase msg)
        {
            lock (this.receiveQueue)
            {
                this.receiveQueue.Enqueue(msg);
            }

            this.receiveEventWaitHandle.Set();
        }
示例#29
0
 /// <summary>
 /// Send a message
 /// </summary>
 /// <param name="msg">Message</param>
 private void Send(MqttMsgBase msg)
 {
     MqttUtility.Trace.WriteLine(TraceLevel.Frame, "SEND {0}", msg);
     this.Send(msg.GetBytes());
 }
示例#30
0
        public static MqttMsgSubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            int num1 = 0;
            MqttMsgSubscribe mqttMsgSubscribe1 = new MqttMsgSubscribe();

            if (protocolVersion == (byte)4 && ((int)fixedHeaderFirstByte & 15) != 2)
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
            }
            int length1 = MqttMsgBase.decodeRemainingLength(channel);

            byte[] buffer = new byte[length1];
            channel.Receive(buffer);
            if (protocolVersion == (byte)3)
            {
                mqttMsgSubscribe1.qosLevel = checked ((byte)(((int)fixedHeaderFirstByte & 6) >> 1));
                mqttMsgSubscribe1.dupFlag  = ((int)fixedHeaderFirstByte & 8) >> 3 == 1;
                mqttMsgSubscribe1.retain   = false;
            }
            MqttMsgSubscribe mqttMsgSubscribe2 = mqttMsgSubscribe1;

            byte[] numArray1 = buffer;
            int    index1    = num1;
            int    num2      = checked (index1 + 1);
            int    num3      = (int)checked ((ushort)((int)numArray1[index1] << 8 & 65280));

            mqttMsgSubscribe2.messageId = (ushort)num3;
            MqttMsgSubscribe mqttMsgSubscribe3 = mqttMsgSubscribe1;
            int messageId = (int)mqttMsgSubscribe3.messageId;

            byte[] numArray2 = buffer;
            int    index2    = num2;
            int    num4      = checked (index2 + 1);
            int    num5      = (int)numArray2[index2];

            mqttMsgSubscribe3.messageId = (ushort)(messageId | num5);
            IList <string> stringList = (IList <string>) new List <string>();
            IList <byte>   byteList1  = (IList <byte>) new List <byte>();

            do
            {
                byte[] numArray3   = buffer;
                int    index3      = num4;
                int    num6        = checked (index3 + 1);
                int    num7        = (int)numArray3[index3] << 8 & 65280;
                byte[] numArray4   = buffer;
                int    index4      = num6;
                int    sourceIndex = checked (index4 + 1);
                int    num8        = (int)numArray4[index4];
                int    length2     = num7 | num8;
                byte[] bytes       = new byte[length2];
                Array.Copy((Array)buffer, sourceIndex, (Array)bytes, 0, length2);
                int num9 = checked (sourceIndex + length2);
                stringList.Add(new string(Encoding.UTF8.GetChars(bytes)));
                IList <byte> byteList2 = byteList1;
                byte[]       numArray5 = buffer;
                int          index5    = num9;
                num4 = checked (index5 + 1);
                int num10 = (int)numArray5[index5];
                byteList2.Add((byte)num10);
            }while (num4 < length1);
            mqttMsgSubscribe1.topics    = new string[stringList.Count];
            mqttMsgSubscribe1.qosLevels = new byte[byteList1.Count];
            int index6 = 0;

            while (index6 < stringList.Count)
            {
                mqttMsgSubscribe1.topics[index6]    = stringList[index6];
                mqttMsgSubscribe1.qosLevels[index6] = byteList1[index6];
                checked { ++index6; }
            }
            return(mqttMsgSubscribe1);
        }
示例#31
0
 /// <summary>
 /// Send a message to the broker and wait answer
 /// </summary>
 /// <param name="msg">Message</param>
 /// <returns>MQTT message response</returns>
 private MqttMsgBase SendReceive(MqttMsgBase msg)
 {
     return this.SendReceive(msg, MqttSettings.MQTT_DEFAULT_TIMEOUT);
 }
示例#32
0
        /// <summary>
        /// Parse bytes for a PUBLISH message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBLISH message instance</returns>
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int    index = 0;

            byte[]         topicUtf8;
            int            topicUtf8Length;
            MqttMsgPublish msg = new MqttMsgPublish();

            // get remaining length and allocate buffer
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            int 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);
            // 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  = (ushort)((buffer[index++] << 8) & 0xFF00);
                msg.messageId |= (buffer[index++]);
            }

            // get payload with message data
            int messageSize   = remainingLength - index;
            int remaining     = messageSize;
            int 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);
        }
示例#33
0
 /// <summary>
 /// Send a message to the broker and wait answer
 /// </summary>
 /// <param name="msg">Message</param>
 /// <param name="timeout">Timeout for receiving answer</param>
 /// <returns>MQTT message response</returns>
 private MqttMsgBase SendReceive(MqttMsgBase msg, int timeout)
 {
     MqttUtility.Trace.WriteLine(TraceLevel.Frame, "SEND {0}", msg);
     return this.SendReceive(msg.GetBytes(), timeout);
 }
示例#34
0
        /// <summary>
        /// Process inflight messages queue
        /// </summary>
        private void ProcessInflightThread()
        {
            MqttMsgContext msgContext = null;
            MqttMsgBase msgInflight = null;
            MqttMsgBase msgReceived = null;
            bool acknowledge = false;
            int timeout = Timeout.Infinite;

            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)
                        {
                            // 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;

                                // 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)
                                        {
                                            // notify published message from broker (no need acknowledged)
                                            this.OnMqttMsgReceived(msgInflight);
                                        }
                                        break;

                                    case MqttMsgState.QueuedQos1:

                                        // QoS 1, PUBLISH or SUBSCRIBE/UNSUBSCRIBE message to send to broker, state change to wait PUBACK or SUBACK/UNSUBACK
                                        if (msgContext.Flow == MqttMsgFlow.ToPublish)
                                        {
                                            if (msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE)
                                                // PUBLISH message to send, wait for PUBACK
                                                msgContext.State = MqttMsgState.WaitForPuback;
                                            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;

                                            msgContext.Timestamp = Environment.TickCount;
                                            msgContext.Attempt++;
                                            // retry ? set dup flag
                                            if (msgContext.Attempt > 1)
                                                msgInflight.DupFlag = true;

                                            this.Send(msgInflight);

                                            // update timeout
                                            int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp));
                                            timeout = (msgTimeout < timeout) ? msgTimeout : 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 = ((MqttMsgPublish)msgInflight).MessageId;

                                            this.Send(puback);

                                            // notify published message from broker and acknowledged
                                            this.OnMqttMsgReceived(msgInflight);
                                        }
                                        break;

                                    case MqttMsgState.QueuedQos2:

                                        // QoS 2, PUBLISH message to send to broker, state change to wait PUBREC
                                        if (msgContext.Flow == MqttMsgFlow.ToPublish)
                                        {
                                            msgContext.State = MqttMsgState.WaitForPubrec;
                                            msgContext.Timestamp = Environment.TickCount;
                                            msgContext.Attempt++;
                                            // retry ? set dup flag
                                            if (msgContext.Attempt > 1)
                                                msgInflight.DupFlag = true;

                                            this.Send(msgInflight);

                                            // update timeout
                                            int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp));
                                            timeout = (msgTimeout < timeout) ? msgTimeout : 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 = ((MqttMsgPublish)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) && ((msgReceived.Type == MqttMsgBase.MQTT_MSG_PUBACK_TYPE) ||
                                                                          (msgReceived.Type == MqttMsgBase.MQTT_MSG_SUBACK_TYPE) ||
                                                                          (msgReceived.Type == MqttMsgBase.MQTT_MSG_UNSUBACK_TYPE)))
                                            {
                                                // PUBACK message or SUBACK message for the current message
                                                if (((msgInflight.Type == MqttMsgBase.MQTT_MSG_PUBLISH_TYPE) && (((MqttMsgPuback)msgReceived).MessageId == ((MqttMsgPublish)msgInflight).MessageId)) ||
                                                    ((msgInflight.Type == MqttMsgBase.MQTT_MSG_SUBSCRIBE_TYPE) && (((MqttMsgSuback)msgReceived).MessageId == ((MqttMsgSubscribe)msgInflight).MessageId)) ||
                                                    ((msgInflight.Type == MqttMsgBase.MQTT_MSG_UNSUBSCRIBE_TYPE) && (((MqttMsgUnsuback)msgReceived).MessageId == ((MqttMsgUnsubscribe)msgInflight).MessageId)))
                                                {
                                                    lock (this.internalQueue)
                                                    {
                                                        // received message processed
                                                        this.internalQueue.Dequeue();
                                                        acknowledge = true;
                                                    }

                                                    // notify received acknowledge from broker of a published message or subscribe/unsubscribe message
                                                    this.OnMqttMsgReceived(msgReceived);
                                                }
                                            }

                                            // current message not acknowledged, no PUBACK or SUBACK/UNSUBACK or not equal messageid 
                                            if (!acknowledge)
                                            {
                                                // 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 ((Environment.TickCount - msgContext.Timestamp) >= 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
                                                {
                                                    // 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 - (Environment.TickCount - msgContext.Timestamp));
                                                    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 (((MqttMsgPubrec)msgReceived).MessageId == ((MqttMsgPublish)msgInflight).MessageId)
                                                {
                                                    lock (this.internalQueue)
                                                    {
                                                        // received message processed
                                                        this.internalQueue.Dequeue();
                                                        acknowledge = true;
                                                    }

                                                    MqttMsgPubrel pubrel = new MqttMsgPubrel();
                                                    pubrel.MessageId = ((MqttMsgPublish)msgInflight).MessageId;

                                                    msgContext.State = MqttMsgState.WaitForPubcomp;
                                                    msgContext.Timestamp = Environment.TickCount;
                                                    msgContext.Attempt = 1;

                                                    this.Send(pubrel);

                                                    // update timeout
                                                    int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp));
                                                    timeout = (msgTimeout < timeout) ? msgTimeout : timeout;

                                                    // re-enqueue message
                                                    this.inflightQueue.Enqueue(msgContext);
                                                }
                                            }

                                            // current message not acknowledged
                                            if (!acknowledge)
                                            {
                                                // check timeout for receiving PUBREC since PUBLISH was sent
                                                if ((Environment.TickCount - msgContext.Timestamp) >= 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
                                                {
                                                    // re-enqueue message
                                                    this.inflightQueue.Enqueue(msgContext);

                                                    // update timeout
                                                    int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp));
                                                    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 (((MqttMsgPubrel)msgReceived).MessageId == ((MqttMsgPublish)msgInflight).MessageId)
                                                {
                                                    lock (this.internalQueue)
                                                    {
                                                        // received message processed
                                                        this.internalQueue.Dequeue();
                                                    }

                                                    MqttMsgPubcomp pubcomp = new MqttMsgPubcomp();
                                                    pubcomp.MessageId = ((MqttMsgPublish)msgInflight).MessageId;

                                                    this.Send(pubcomp);

                                                    // notify published message from broker and acknowledged
                                                    this.OnMqttMsgReceived(msgInflight);
                                                }
                                                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 (((MqttMsgPubcomp)msgReceived).MessageId == ((MqttMsgPublish)msgInflight).MessageId)
                                                {
                                                    lock (this.internalQueue)
                                                    {
                                                        // received message processed
                                                        this.internalQueue.Dequeue();
                                                        acknowledge = true;
                                                    }

                                                    // notify received acknowledge from broker of a published message
                                                    this.OnMqttMsgReceived(msgReceived);
                                                }
                                            }

                                            // current message not acknowledged
                                            if (!acknowledge)
                                            {
                                                // check timeout for receiving PUBCOMP since PUBREL was sent
                                                if ((Environment.TickCount - msgContext.Timestamp) >= 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
                                                {
                                                    // re-enqueue message
                                                    this.inflightQueue.Enqueue(msgContext);

                                                    // update timeout
                                                    int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp));
                                                    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 = ((MqttMsgPublish)msgInflight).MessageId;

                                            msgContext.State = MqttMsgState.WaitForPubcomp;
                                            msgContext.Timestamp = Environment.TickCount;
                                            msgContext.Attempt++;
                                            // retry ? set dup flag
                                            if (msgContext.Attempt > 1)
                                                pubrel.DupFlag = true;

                                            this.Send(pubrel);

                                            // update timeout
                                            int msgTimeout = (this.settings.DelayOnRetry - (Environment.TickCount - msgContext.Timestamp));
                                            timeout = (msgTimeout < timeout) ? msgTimeout : 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;
                        }
                    }
                }
            }
            catch (MqttCommunicationException e)
            {
                MqttUtility.Trace.WriteLine(TraceLevel.Error, "Exception occurred: {0}", e.ToString());

                this.Close();

                // raise disconnection client event
                this.OnMqttMsgDisconnected();
            }
        }
示例#35
0
        /// <summary>
        /// Parse bytes for a CONNECT message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>CONNECT message instance</returns>
        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);
        }