public async Task <SessionState> ConnectAsync(MqttClientCredentials credentials, MqttLastWill will = null, bool cleanSession = false) { if (disposed) { throw new ObjectDisposedException(GetType().FullName); } try { if (IsConnected) { throw new MqttClientException(string.Format(Properties.Resources.Client_AlreadyConnected, Id)); } if (string.IsNullOrEmpty(credentials.ClientId) && !cleanSession) { throw new MqttClientException(Properties.Resources.Client_AnonymousClientWithoutCleanSession); } Id = string.IsNullOrEmpty(credentials.ClientId) ? MqttClient.GetAnonymousClientId() : credentials.ClientId; OpenClientSession(cleanSession); await InitializeChannelAsync().ConfigureAwait(continueOnCapturedContext: false); var connect = new Connect(Id, cleanSession) { UserName = credentials.UserName, Password = credentials.Password, Will = will, KeepAlive = configuration.KeepAliveSecs }; await SendPacketAsync(connect) .ConfigureAwait(continueOnCapturedContext: false); var connectTimeout = TimeSpan.FromSeconds(configuration.WaitTimeoutSecs); var ack = await packetListener .PacketStream .ObserveOn(NewThreadScheduler.Default) .OfType <ConnectAck> () .FirstOrDefaultAsync() .Timeout(connectTimeout); if (ack == null) { var message = string.Format(Properties.Resources.Client_ConnectionDisconnected, Id); throw new MqttClientException(message); } if (ack.Status != MqttConnectionStatus.Accepted) { throw new MqttConnectionException(ack.Status); } IsConnected = true; return(ack.SessionPresent ? SessionState.SessionPresent : SessionState.CleanSession); } catch (TimeoutException timeEx) { Close(timeEx); throw new MqttClientException(string.Format(Properties.Resources.Client_ConnectionTimeout, Id), timeEx); } catch (MqttConnectionException connectionEx) { Close(connectionEx); var message = string.Format(Properties.Resources.Client_ConnectNotAccepted, Id, connectionEx.ReturnCode); throw new MqttClientException(message, connectionEx); } catch (MqttClientException clientEx) { Close(clientEx); throw; } catch (Exception ex) { Close(ex); throw new MqttClientException(string.Format(Properties.Resources.Client_ConnectionError, Id), ex); } }
protected override Connect Read(byte[] bytes) { ValidateHeaderFlag(bytes, t => t == MqttPacketType.Connect, 0x00); var remainingLengthBytesLength = 0; MqttProtocol.Encoding.DecodeRemainingLength(bytes, out remainingLengthBytesLength); var protocolName = bytes.GetString(MqttProtocol.PacketTypeLength + remainingLengthBytesLength); if (protocolName != MqttProtocol.Name) { var error = string.Format(Properties.Resources.ConnectFormatter_InvalidProtocolName, protocolName); throw new MqttException(error); } var protocolLevelIndex = MqttProtocol.PacketTypeLength + remainingLengthBytesLength + MqttProtocol.NameLength; var protocolLevel = bytes.Byte(protocolLevelIndex); if (protocolLevel < MqttProtocol.SupportedLevel) { var error = string.Format(Properties.Resources.ConnectFormatter_UnsupportedLevel, protocolLevel); throw new MqttConnectionException(MqttConnectionStatus.UnacceptableProtocolVersion, error); } var protocolLevelLength = 1; var connectFlagsIndex = protocolLevelIndex + protocolLevelLength; var connectFlags = bytes.Byte(connectFlagsIndex); if (connectFlags.IsSet(0)) { throw new MqttException(Properties.Resources.ConnectFormatter_InvalidReservedFlag); } if (connectFlags.Bits(4, 2) == 0x03) { throw new MqttException(Properties.Resources.Formatter_InvalidQualityOfService); } var willFlag = connectFlags.IsSet(2); var willRetain = connectFlags.IsSet(5); if (!willFlag && willRetain) { throw new MqttException(Properties.Resources.ConnectFormatter_InvalidWillRetainFlag); } var userNameFlag = connectFlags.IsSet(7); var passwordFlag = connectFlags.IsSet(6); if (!userNameFlag && passwordFlag) { throw new MqttException(Properties.Resources.ConnectFormatter_InvalidPasswordFlag); } var willQos = (MqttQualityOfService)connectFlags.Bits(4, 2); var cleanSession = connectFlags.IsSet(1); var keepAliveLength = 2; var keepAliveBytes = bytes.Bytes(connectFlagsIndex + 1, keepAliveLength); var keepAlive = keepAliveBytes.ToUInt16(); var payloadStartIndex = connectFlagsIndex + keepAliveLength + 1; var nextIndex = 0; var clientId = bytes.GetString(payloadStartIndex, out nextIndex); if (clientId.Length > MqttProtocol.ClientIdMaxLength) { throw new MqttConnectionException(MqttConnectionStatus.IdentifierRejected, Properties.Resources.ConnectFormatter_ClientIdMaxLengthExceeded); } if (!IsValidClientId(clientId)) { var error = string.Format(Properties.Resources.ConnectFormatter_InvalidClientIdFormat, clientId); throw new MqttConnectionException(MqttConnectionStatus.IdentifierRejected, error); } if (string.IsNullOrEmpty(clientId) && !cleanSession) { throw new MqttConnectionException(MqttConnectionStatus.IdentifierRejected, Properties.Resources.ConnectFormatter_ClientIdEmptyRequiresCleanSession); } if (string.IsNullOrEmpty(clientId)) { clientId = MqttClient.GetAnonymousClientId(); } var connect = new Connect(clientId, cleanSession); connect.KeepAlive = keepAlive; if (willFlag) { var willTopic = bytes.GetString(nextIndex, out int willMessageIndex); var willMessageLengthBytes = bytes.Bytes(willMessageIndex, count: 2); var willMessageLenght = willMessageLengthBytes.ToUInt16(); var willMessage = bytes.Bytes(willMessageIndex + 2, willMessageLenght); connect.Will = new MqttLastWill(willTopic, willQos, willRetain, willMessage); nextIndex = willMessageIndex + 2 + willMessageLenght; } if (userNameFlag) { var userName = bytes.GetString(nextIndex, out nextIndex); connect.UserName = userName; } if (passwordFlag) { var password = bytes.GetString(nextIndex); connect.Password = password; } return(connect); }