Example #1
0
 /// <summary>
 /// Constructor
 /// </summary>
 /// <param name="connect">CONNECT message received from client</param>
 public MqttMsgConnectEventArgs(MqttMsgConnect connect)
 {
     Message = connect;
 }
Example #2
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);
        }