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