Exemple #1
0
        /// <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;
        }
        /// <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;
        }
        /// <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;
        }
Exemple #4
0
        /// <summary>
        /// Parse bytes for a DISCONNECT message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>DISCONNECT message instance</returns>
        public static MqttMsgDisconnect Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel)
        {
            MqttMsgDisconnect msg = new MqttMsgDisconnect();

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

            return msg;
        }
        /// <summary>
        /// Parse bytes for a PINGRESP message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PINGRESP message instance</returns>
        public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, IMqttNetworkChannel channel)
        {
            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(channel);

            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;
        }
        /// <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;
        }
Exemple #8
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
            int remainingLength = MqttMsgBase.decodeRemainingLength(channel);
            // NOTE : remainingLength must be 0

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

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

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

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

            if (((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5)) &&
                ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_DISCONNECT_FLAG_BITS))
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
            }

            // get remaining length and allocate buffer
            int remainingLength = DecodeVariableByte(channel);

            // NOTE : remainingLength must be 0
            if ((remainingLength != 0) && (protocolVersion == MqttProtocolVersion.Version_5))
            {
                // V5.0 specific
                buffer = new byte[remainingLength];

                // read bytes from socket...
                channel.Receive(buffer);
                msg.ResonCode = (MqttReasonCode)buffer[index++];
                int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index);
                propSize += index;
                MqttProperty prop;

                while (propSize > index)
                {
                    prop = (MqttProperty)buffer[index++];
                    switch (prop)
                    {
                    case MqttProperty.SessionExpiryInterval:
                        // 4 bytes
                        msg.SessionExpiryInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index);
                        break;

                    case MqttProperty.ReasonString:
                        // UTF8 encoded
                        msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.UserProperty:
                        // UTF8 key value encoding, so 2 strings in a raw
                        string key   = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        msg.UserProperties.Add(new UserProperty(key, value));
                        break;

                    case MqttProperty.ServerReference:
                        // UTF8 encoded
                        msg.ServerReference = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    default:
                        // non supported property
                        index = propSize;
                        break;
                    }
                }
            }

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

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

            // read bytes from socket...
            int received = 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 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;
        }
        /// <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);
        }
Exemple #15
0
        /// <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;
        }
        /// <summary>
        /// Parse bytes for a PUBLISH message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">MQTT Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBLISH message instance</returns>
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int    index = 0;

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

            // get remaining length and allocate buffer
            int remainingLength = DecodeVariableByte(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 = (MqttQoSLevel)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET);
            // check wrong QoS level (both bits can't be set 1)
            if (msg.QosLevel > MqttQoSLevel.ExactlyOnce)
            {
                throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
            }

            // read DUP flag from fixed header
            msg.DupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
            // read retain flag from fixed header
            msg.Retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01);

            // message id is valid only with QOS level 1 or QOS level 2
            if ((msg.QosLevel == MqttQoSLevel.AtLeastOnce) ||
                (msg.QosLevel == MqttQoSLevel.ExactlyOnce))
            {
                // message id
                msg.MessageId  = (ushort)((buffer[index++] << 8) & 0xFF00);
                msg.MessageId |= buffer[index++];
            }

            // We do have the properties here to decode
            if (protocolVersion == MqttProtocolVersion.Version_5)
            {
                // size of the properties
                int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index);
                propSize += index;
                MqttProperty prop;

                while (propSize > index)
                {
                    prop = (MqttProperty)buffer[index++];
                    switch (prop)
                    {
                    case MqttProperty.PayloadFormatIndicator:
                        msg.IsPayloadUTF8 = buffer[index++] != 0;
                        break;

                    case MqttProperty.MessageExpiryInterval:
                        msg.MessageExpiryInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index);
                        break;

                    case MqttProperty.TopicAlias:
                        msg.TopicAlias  = (ushort)(buffer[index++] << 8);
                        msg.TopicAlias |= buffer[index++];
                        break;

                    case MqttProperty.ResponseTopic:
                        msg.ResponseTopic = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.CorrelationData:
                        // byte[]
                        int length = ((buffer[index++] << 8) & 0xFF00);
                        length |= buffer[index++];
                        msg.CorrelationData = new byte[length];
                        Array.Copy(buffer, index, msg.CorrelationData, 0, length);
                        index += length;
                        break;

                    case MqttProperty.UserProperty:
                        // UTF8 key value encoding, so 2 strings in a raw
                        string key   = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        msg.UserProperties.Add(new UserProperty(key, value));
                        break;

                    case MqttProperty.SubscriptionIdentifier:
                        msg.SubscriptionIdentifier = EncodeDecodeHelper.DecodeVariableByte(buffer, ref index);
                        break;

                    case MqttProperty.ContentType:
                        msg.ContentType = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    default:
                        // non supported property
                        index = propSize;
                        break;
                    }
                }
            }

            // 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);
        }
Exemple #17
0
        /// <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, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel)
        {
            byte[]         buffer;
            int            index = 0;
            MqttMsgConnack msg   = new MqttMsgConnack();

            if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5))
            {
                // [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 = DecodeVariableByte(channel);

            buffer = new byte[remainingLength];

            // read bytes from socket...
            channel.Receive(buffer);
            if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5))
            {
                // [v3.1.1] ... set session present flag ...
                msg.SessionPresent = (buffer[index++] & SESSION_PRESENT_FLAG_MASK) != 0x00;
            }
            // ...and set return code from broker
            msg.ReturnCode = (MqttReasonCode)buffer[index++];

            // v5.0 properties
            if (protocolVersion == MqttProtocolVersion.Version_5)
            {
                // size of the properties
                int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index);
                propSize += index;
                MqttProperty prop;

                while (propSize > index)
                {
                    prop = (MqttProperty)buffer[index++];
                    switch (prop)
                    {
                    case MqttProperty.SessionExpiryInterval:
                        // 4 bytes
                        msg.SessionExpiryInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index);
                        break;

                    case MqttProperty.ReceiveMaximum:
                        // 2 bytes
                        msg.ReceiveMaximum  = (ushort)(buffer[index++] << 8);
                        msg.ReceiveMaximum |= buffer[index++];
                        break;

                    case MqttProperty.MaximumQoS:
                        msg.MaximumQoS = buffer[index++] != 0;
                        break;

                    case MqttProperty.RetainAvailable:
                        msg.RetainAvailable = buffer[index++] != 0;
                        break;

                    case MqttProperty.MaximumPacketSize:
                        // 4 bytes
                        msg.MaximumPacketSize = EncodeDecodeHelper.DecodeUint(buffer, ref index);
                        break;

                    case MqttProperty.AssignedClientIdentifier:
                        // UTF8 encoded
                        msg.AssignedClientIdentifier = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.TopicAliasMaximum:
                        // 2 bytes
                        msg.TopicAliasMaximum  = (ushort)(buffer[index++] << 8);
                        msg.TopicAliasMaximum |= buffer[index++];
                        break;

                    case MqttProperty.ReasonString:
                        // UTF8 encoded
                        msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.UserProperty:
                        // UTF8 key value encoding, so 2 strings in a raw
                        string key   = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        msg.UserProperties.Add(new UserProperty(key, value));
                        break;

                    case MqttProperty.WildcardSubscriptionAvailable:
                        msg.WildcardSubscriptionAvailable = buffer[index++] != 0;
                        break;

                    case MqttProperty.SubscriptionIdentifierAvailable:
                        msg.SubscriptionIdentifiersAvailable = buffer[index++] != 0;
                        break;

                    case MqttProperty.SharedSubscriptionAvailable:
                        msg.SharedSubscriptionAvailable = buffer[index++] != 0;
                        break;

                    case MqttProperty.ServerKeepAlive:
                        // 2 bytes
                        msg.ServerKeepAlive  = (ushort)(buffer[index++] << 8);
                        msg.ServerKeepAlive |= buffer[index++];
                        break;

                    case MqttProperty.ResponseInformation:
                        // UTF8 encoded
                        msg.ResponseInformation = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.ServerReference:
                        // UTF8 encoded
                        msg.ServerReference = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.AuthenticationMethod:
                        // UTF8 encoded
                        msg.AuthenticationMethod = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.AuthenticationData:
                        // byte[]
                        int length = ((buffer[index++] << 8) & 0xFF00);
                        length |= buffer[index++];
                        msg.AuthenticationData = new byte[length];
                        Array.Copy(buffer, index, msg.AuthenticationData, 0, length);
                        index += length;
                        break;

                    default:
                        // non supported property
                        index = propSize;
                        break;
                    }
                }
            }

            return(msg);
        }
Exemple #18
0
 public MQTTClientBase(IMqttNetworkChannel channel)
 {
     _channel  = channel;
     _clientId = Guid.NewGuid().ToString();
 }
 /// <summary>
 /// Decode remaining length reading bytes from socket
 /// </summary>
 /// <param name="channel">Channel from reading bytes</param>
 /// <returns>Decoded remaining length</returns>
 protected static int decodeRemainingLength(IMqttNetworkChannel channel)
 {
     int multiplier = 1;
     int value = 0;
     int digit = 0;
     byte[] nextByte = new byte[1];
     do
     {
         // next digit from stream
         channel.Receive(nextByte);
         digit = nextByte[0];
         value += ((digit & 127) * multiplier);
         multiplier *= 128;
     } while ((digit & 128) != 0);
     return value;
 }
        /// <summary>
        /// Parse bytes for a PUBREC message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">MQTT Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBREC message instance</returns>
        public static MqttMsgAuthentication Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel)
        {
            if (protocolVersion != MqttProtocolVersion.Version_5)
            {
                throw new NotSupportedException();
            }

            if ((fixedHeaderFirstByte & MSG_FLAG_BITS_MASK) != MQTT_MSG_AUTH_FLAG_BITS)
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidFlagBits);
            }

            MqttMsgAuthentication msg = new();

            byte[] buffer;
            int    index  = 0;
            int    length = 0;

            // get remaining length and allocate buffer
            int remainingLength = DecodeVariableByte(channel);

            buffer = new byte[remainingLength];

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

            msg.ReasonCode = (MqttReasonCode)buffer[index++];

            int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index);

            propSize += index;
            MqttProperty prop;

            while (propSize > index)
            {
                prop = (MqttProperty)buffer[index++];
                switch (prop)
                {
                case MqttProperty.AuthenticationMethod:
                    // UTF8 encoded
                    msg.AuthenticationMethod = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                    break;

                case MqttProperty.AuthenticationData:
                    // byte[]
                    length  = ((buffer[index++] << 8) & 0xFF00);
                    length |= buffer[index++];
                    msg.AuthenticationData = new byte[length];
                    Array.Copy(buffer, index, msg.AuthenticationData, 0, length);
                    index += length;
                    break;

                case MqttProperty.ReasonString:
                    // UTF8 encoded
                    msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                    break;

                case MqttProperty.UserProperty:
                    // UTF8 key value encoding, so 2 strings in a raw
                    string key   = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                    string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                    msg.UserProperties.Add(new UserProperty(key, value));
                    break;

                default:
                    // non supported property
                    index = propSize;
                    break;
                }
            }

            return(msg);
        }
Exemple #21
0
        /// <summary>
        /// Connect to broker
        /// </summary>
        /// <param name="clientId">Client identifier</param>
        /// <param name="username">Username</param>
        /// <param name="password">Password</param>
        /// <param name="willRetain">Will retain flag</param>
        /// <param name="willQosLevel">Will QOS level</param>
        /// <param name="willFlag">Will flag</param>
        /// <param name="willTopic">Will topic</param>
        /// <param name="willMessage">Will message</param>
        /// <param name="cleanSession">Clean sessione flag</param>
        /// <param name="keepAlivePeriod">Keep alive period</param>
        /// <returns>Return code of CONNACK message from broker</returns>
        public byte Connect(string clientId,
            string username,
            string password,
            bool willRetain,
            byte willQosLevel,
            bool willFlag,
            string willTopic,
            string willMessage,
            bool cleanSession,
            ushort keepAlivePeriod)
        {
            // create CONNECT message
            MqttMsgConnect connect = new MqttMsgConnect(clientId,
                username,
                password,
                willRetain,
                willQosLevel,
                willFlag,
                willTopic,
                willMessage,
                cleanSession,
                keepAlivePeriod);

            try
            {
                // create network channel and connect to broker
#if WINDOWS_PHONE
                this.channel = new WPMqttNetworkChannel(this.brokerHostName, this.brokerIpAddress, this.brokerPort, this.secure, this.caCert);
#else
                this.channel = new MqttNetworkChannel(this.brokerHostName, this.brokerIpAddress, this.brokerPort, this.secure, this.caCert);
#endif
                this.channel.Connect();
            }
            catch (Exception ex)
            {
                throw new MqttConnectionException("Exception connecting to the broker", ex);
            }

            this.lastCommTime = 0;
            this.isRunning = true;
            // start thread for receiving messages from broker
            this.receiveThread = new Thread(this.ReceiveThread);
            this.receiveThread.Start();

            MqttMsgConnack connack = (MqttMsgConnack)this.SendReceive(connect);
            // if connection accepted, start keep alive timer and 
            if (connack.ReturnCode == MqttMsgConnack.CONN_ACCEPTED)
            {
                // set all client properties
                this.ClientId = clientId;
                this.CleanSession = cleanSession;
                this.WillFlag = willFlag;
                this.WillTopic = willTopic;
                this.WillMessage = willMessage;
                this.WillQosLevel = willQosLevel;

                this.keepAlivePeriod = keepAlivePeriod * 1000; // convert in ms

                // start thread for sending keep alive message to the broker
                this.keepAliveThread = new Thread(this.KeepAliveThread);
                this.keepAliveThread.Start();

                // start thread for raising received message event from broker
                this.receiveEventThread = new Thread(this.ReceiveEventThread);
                this.receiveEventThread.Start();

                // start thread for handling inflight messages queue to broker asynchronously (publish and acknowledge)
                this.processInflightThread = new Thread(this.ProcessInflightThread);
                this.processInflightThread.Start();

                this.IsConnected = true;
            }
            return connack.ReturnCode;
        }
        /// <summary>
        /// Parse bytes for a PINGRESP message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">MQTT Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PINGRESP message instance</returns>
        public static MqttMsgPingResp Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel)
        {
            MqttMsgPingResp msg = new MqttMsgPingResp();

            if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5))
            {
                // [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
            DecodeVariableByte(channel);

            return(msg);
        }
        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);
        }
Exemple #24
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);
        }
Exemple #25
0
        /// <summary>
        /// Parse bytes for a CONNECT message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">MQTT Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>CONNECT message instance</returns>
        public static MqttMsgConnect Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel)
        {
            byte[]         buffer;
            int            index = 0;
            bool           isUsernameFlag;
            bool           isPasswordFlag;
            int            length;
            MqttMsgConnect msg = new MqttMsgConnect();

            // get remaining length and allocate buffer
            int remainingLength = DecodeVariableByte(channel);

            buffer = new byte[remainingLength];

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

            // protocol name
            msg.ProtocolName = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);

            // [v3.1.1] wrong protocol name valid for 5.0 as well
            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 = (MqttProtocolVersion)buffer[index];
            index += PROTOCOL_VERSION_SIZE;

            // connect flags
            // [v3.1.1] check lsb (reserved) must be 0
            if (((msg.ProtocolVersion == MqttProtocolVersion.Version_3_1_1) || (msg.ProtocolVersion == MqttProtocolVersion.Version_5)) &&
                ((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++];

            // In case of v5, we have properties encoded with length and type.
            // This is different than in the v3.x protocols
            if (msg.ProtocolVersion == MqttProtocolVersion.Version_5)
            {
                // size of the properties
                int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index);
                propSize += index;
                MqttProperty prop;

                while (propSize > index)
                {
                    prop = (MqttProperty)buffer[index++];
                    switch (prop)
                    {
                    case MqttProperty.AuthenticationMethod:
                        // UTF8 encoded
                        msg.AuthenticationMethod = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.AuthenticationData:
                        // byte[]
                        length  = ((buffer[index++] << 8) & 0xFF00);
                        length |= buffer[index++];
                        msg.AuthenticationData = new byte[length];
                        Array.Copy(buffer, index, msg.AuthenticationData, 0, length);
                        index += length;
                        break;

                    case MqttProperty.RequestProblemInformation:
                        // 1 byte
                        msg.RequestProblemInformation = buffer[index++] != 0;
                        break;

                    case MqttProperty.RequestResponseInformation:
                        // 1 byte
                        msg.RequestResponseInformation = buffer[index++] != 0;
                        break;

                    case MqttProperty.ReceiveMaximum:
                        // 2 bytes
                        msg.ReceiveMaximum  = (ushort)(buffer[index++] << 8);
                        msg.ReceiveMaximum |= buffer[index++];
                        break;

                    case MqttProperty.TopicAliasMaximum:
                        // 2 bytes
                        msg.TopicAliasMaximum  = (ushort)(buffer[index++] << 8);
                        msg.TopicAliasMaximum |= buffer[index++];
                        break;

                    case MqttProperty.UserProperty:
                        // UTF8 key value encoding, so 2 strings in a raw
                        string key   = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        msg.UserProperties.Add(new UserProperty(key, value));
                        break;

                    case MqttProperty.MaximumPacketSize:
                        // 4 bytes
                        msg.MaximumPacketSize = EncodeDecodeHelper.DecodeUint(buffer, ref index);
                        break;

                    case MqttProperty.SessionExpiryInterval:
                        // 4 bytes
                        msg.SessionExpiryInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index);
                        break;

                    case MqttProperty.WillDelayInterval:
                        // 4 bytes
                        msg.WillDelayInterval = EncodeDecodeHelper.DecodeUint(buffer, ref index);
                        break;

                    default:
                        // non supported property
                        index = propSize;
                        break;
                    }
                }
            }

            // client identifier [v3.1.1] it may be zero bytes long (empty string)
            msg.ClientId = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
            // [v3.1.1] if client identifier is zero bytes long, clean session must be true
            if ((msg.ProtocolVersion == MqttProtocolVersion.Version_3_1_1) && (msg.ClientId.Length == 0) && (!msg.CleanSession))
            {
                throw new MqttClientException(MqttClientErrorCode.InvalidClientId);
            }

            // will topic and will message
            if (msg.WillFlag)
            {
                msg.WillTopic   = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                msg.WillMessage = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
            }

            // username
            if (isUsernameFlag)
            {
                msg.Username = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
            }

            // password
            if (isPasswordFlag)
            {
                msg.Password = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
            }

            return(msg);
        }
Exemple #26
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;
        }
        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);
        }
Exemple #28
0
        /// <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)
            {
                msg._qosLevel = ((byte)((fixedHeaderFirstByte & QOS_LEVEL_MASK) >> QOS_LEVEL_OFFSET)).ToQOS();

                msg._dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
                // retain flag not used
                msg._retainFlag = 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)

            IList <String> tmpTopics    = new List <String>();
            IList <byte>   tmpQosLevels = new List <byte>();

            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 QOS[tmpQosLevels.Count];
            for (int i = 0; i < tmpTopics.Count; i++)
            {
                msg._topics[i]    = (string)tmpTopics[i];
                msg._qosLevels[i] = ((byte)tmpQosLevels[i]).ToQOS();
            }

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

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

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

            // NOTE : remainingLength must be 0

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

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

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

            buffer = new byte[remainingLength];

            // read bytes from socket...
            int received = 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 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);
        }
Exemple #31
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);
        }
Exemple #32
0
 public MQTTDeviceClient(IMqttNetworkChannel channel) : base(channel)
 {
 }
Exemple #33
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);
        }
Exemple #34
0
        /// <summary>
        /// Parse bytes for a UNSUBSCRIBE message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>UNSUBSCRIBE message instance</returns>
        public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int    index = 0;

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

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

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

            buffer = new byte[remainingLength];

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

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

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

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

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

            // if .Net Micro Framework
#if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3 || NANOFRAMEWORK_V1_0)
            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);
        }
Exemple #35
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);
        }
        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);
        }
Exemple #37
0
        /// <summary>
        /// Parse bytes for a PUBLISH 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>PUBLISH message instance</returns>
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, 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);
            // check wrong QoS level (both bits can't be set 1)
            if (msg.qosLevel > QOS_LEVEL_EXACTLY_ONCE)
                throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
            // read DUP flag from fixed header
            msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
            // read retain flag from fixed header
            msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01);

            // message id is valid only with QOS level 1 or QOS level 2
            if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) ||
                (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE))
            {
                // message id
                msg.messageId = (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;
        }
Exemple #38
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);
        }
Exemple #39
0
        /// <summary>
        /// Parse bytes for a PUBACK message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBACK message instance</returns>
        public static MqttPublishAcknowledgeMessage Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int    index = 0;
            MqttPublishAcknowledgeMessage msg = new MqttPublishAcknowledgeMessage();

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

            // get remaining length and allocate buffer
            int remainingLength = MqttMessage.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);
        }
Exemple #40
0
 public MQTTAppClient(IMqttNetworkChannel channel) : base(channel)
 {
 }
        /// <summary>
        /// Parse bytes for a UNSUBSCRIBE message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>UNSUBSCRIBE message instance</returns>
        public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, byte protocolVersion, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int index = 0;
            byte[] topicUtf8;
            int topicUtf8Length;
            MqttMsgUnsubscribe msg = new MqttMsgUnsubscribe();

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

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

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

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

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

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

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

            // if .Net Micro Framework
            #if (MF_FRAMEWORK_VERSION_V4_2 || MF_FRAMEWORK_VERSION_V4_3)
            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;
        }
Exemple #42
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);
        }
        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);
        }
        /// <summary>
        /// Parse bytes for a SUBACK message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">MQTT Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>SUBACK message instance</returns>
        public static MqttMsgSuback Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel)
        {
            byte[]        buffer;
            int           index = 0;
            MqttMsgSuback msg   = new MqttMsgSuback();

            if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5))
            {
                // [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 = DecodeVariableByte(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++]);

            if ((protocolVersion == MqttProtocolVersion.Version_5) && (index < buffer.Length))
            {
                // size of the properties
                int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index);
                propSize += index;
                MqttProperty prop;

                while (propSize > index)
                {
                    prop = (MqttProperty)buffer[index++];
                    switch (prop)
                    {
                    case MqttProperty.ReasonString:
                        // UTF8 encoded
                        msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.UserProperty:
                        // UTF8 key value encoding, so 2 strings in a raw
                        string key   = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        msg.UserProperties.Add(new UserProperty(key, value));
                        break;

                    default:
                        // non supported property
                        index = propSize;
                        break;
                    }
                }
            }

            // payload contains QoS levels granted
            msg.GrantedQoSLevels = new MqttQoSLevel[remainingLength - index];
            if (protocolVersion == MqttProtocolVersion.Version_5)
            {
                msg.ReasonCodes = new MqttReasonCode[remainingLength - index];
            }

            int qosIdx = 0;

            do
            {
                if (protocolVersion == MqttProtocolVersion.Version_5)
                {
                    msg.ReasonCodes[qosIdx] = (MqttReasonCode)buffer[index];
                }

                msg.GrantedQoSLevels[qosIdx++] = (MqttQoSLevel)buffer[index++];
            } while (index < remainingLength);

            return(msg);
        }
Exemple #45
0
        /// <summary>
        /// Parse bytes for a PUBLISH 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>PUBLISH message instance</returns>
        public static MqttMsgPublish Parse(byte fixedHeaderFirstByte, byte protocolVersion, 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);
            // check wrong QoS level (both bits can't be set 1)
            if (msg.qosLevel > QOS_LEVEL_EXACTLY_ONCE)
            {
                throw new MqttClientException(MqttClientErrorCode.QosNotAllowed);
            }
            // read DUP flag from fixed header
            msg.dupFlag = (((fixedHeaderFirstByte & DUP_FLAG_MASK) >> DUP_FLAG_OFFSET) == 0x01);
            // read retain flag from fixed header
            msg.retain = (((fixedHeaderFirstByte & RETAIN_FLAG_MASK) >> RETAIN_FLAG_OFFSET) == 0x01);

            // message id is valid only with QOS level 1 or QOS level 2
            if ((msg.qosLevel == QOS_LEVEL_AT_LEAST_ONCE) ||
                (msg.qosLevel == QOS_LEVEL_EXACTLY_ONCE))
            {
                // message id
                msg.messageId  = (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);
        }
        /// <summary>
        /// Parse bytes for a UNSUBSCRIBE message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">MQTT Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>UNSUBSCRIBE message instance</returns>
        public static MqttMsgUnsubscribe Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel)
        {
            byte[] buffer;
            int    indexUnsub = 0;

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

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

            // get remaining length and allocate buffer
            int remainingLength = DecodeVariableByte(channel);

            buffer = new byte[remainingLength];

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

            if (protocolVersion == MqttProtocolVersion.Version_3_1)
            {
                // only 3.1.0
                // read QoS level from fixed header
                msg.QosLevel = (MqttQoSLevel)((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[indexUnsub++] << 8) & 0xFF00);
            msg.MessageId |= buffer[indexUnsub++];

            if (protocolVersion == MqttProtocolVersion.Version_5)
            {
                // size of the properties
                int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref indexUnsub);
                propSize += indexUnsub;
                MqttProperty prop;

                while (propSize > indexUnsub)
                {
                    prop = (MqttProperty)buffer[indexUnsub++];
                    switch (prop)
                    {
                    case MqttProperty.UserProperty:
                        // UTF8 key value encoding, so 2 strings in a raw
                        string key   = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref indexUnsub);
                        string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref indexUnsub);
                        msg.UserProperties.Add(new UserProperty(key, value));
                        break;

                    default:
                        // non supported property
                        indexUnsub = propSize;
                        break;
                    }
                }
            }

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

            IList tmpTopics = new ArrayList();

            do
            {
                // topic name
                topicUtf8Length  = ((buffer[indexUnsub++] << 8) & 0xFF00);
                topicUtf8Length |= buffer[indexUnsub++];
                topicUtf8        = new byte[topicUtf8Length];
                Array.Copy(buffer, indexUnsub, topicUtf8, 0, topicUtf8Length);
                indexUnsub += topicUtf8Length;
                tmpTopics.Add(Encoding.UTF8.GetString(topicUtf8, 0, topicUtf8.Length));
            } while (indexUnsub < 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);
        }
        /// <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);
        }
Exemple #48
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;
        }
Exemple #49
0
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="socket">Raw socket for communication</param>
        public MqttClient(Socket socket)
        {
            this.channel = new MqttNetworkChannel(socket);

            // reference to MQTT settings
            this.settings = MqttSettings.Instance;

            // client not connected yet (CONNACK not send from client), some default values
            this.IsConnected = false;
            this.ClientId = null;
            this.CleanSession = true;

            this.keepAliveEvent = new AutoResetEvent(false);

            // queue for handling inflight messages (publishing and acknowledge)
            this.inflightWaitHandle = new AutoResetEvent(false);
            this.inflightQueue = new Queue();

            // queue for received message
            this.receiveEventWaitHandle = new AutoResetEvent(false);
            this.receiveQueue = new Queue();
            this.internalQueue = new Queue();
        }
        /// <summary>
        /// Parse bytes for a PUBREL message
        /// </summary>
        /// <param name="fixedHeaderFirstByte">First fixed header byte</param>
        /// <param name="protocolVersion">MQTT Protocol Version</param>
        /// <param name="channel">Channel connected to the broker</param>
        /// <returns>PUBREL message instance</returns>
        public static MqttMsgPubrel Parse(byte fixedHeaderFirstByte, MqttProtocolVersion protocolVersion, IMqttNetworkChannel channel)
        {
            byte[]        buffer;
            int           index = 0;
            MqttMsgPubrel msg   = new MqttMsgPubrel();

            if ((protocolVersion == MqttProtocolVersion.Version_3_1_1) || (protocolVersion == MqttProtocolVersion.Version_5))
            {
                // [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 = DecodeVariableByte(channel);

            buffer = new byte[remainingLength];

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

            if (protocolVersion == MqttProtocolVersion.Version_3_1)
            {
                // only 3.1.0

                // read QoS level from fixed header (would be QoS Level 1)
                msg.QosLevel = (MqttQoSLevel)((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++];


            if (protocolVersion == MqttProtocolVersion.Version_5)
            {
                msg.ReasonCode = (MqttReasonCode)buffer[index++];
                // size of the properties
                int propSize = EncodeDecodeHelper.GetPropertySize(buffer, ref index);
                propSize += index;
                MqttProperty prop;

                while (propSize > index)
                {
                    prop = (MqttProperty)buffer[index++];
                    switch (prop)
                    {
                    case MqttProperty.ReasonString:
                        // UTF8 encoded
                        msg.Reason = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        break;

                    case MqttProperty.UserProperty:
                        // UTF8 key value encoding, so 2 strings in a raw
                        string key   = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        string value = EncodeDecodeHelper.GetUTF8FromBuffer(buffer, ref index);
                        msg.UserProperties.Add(new UserProperty(key, value));
                        break;

                    default:
                        // non supported property
                        index = propSize;
                        break;
                    }
                }
            }

            return(msg);
        }