private static void ValidateConnectPacket(MqttConnectPacket packet) { if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession) { throw new MqttProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7]."); } }
public MqttPublishPacket Create(MqttConnectPacket connectPacket) { if (connectPacket == null) { throw new ArgumentNullException(nameof(connectPacket)); } if (!connectPacket.WillFlag) { throw new MqttProtocolViolationException("The CONNECT packet contains no will message (WillFlag)."); } var packet = new MqttPublishPacket { Topic = connectPacket.WillTopic, Payload = connectPacket.WillMessage, QualityOfServiceLevel = connectPacket.WillQoS, Retain = connectPacket.WillRetain, ContentType = connectPacket.WillContentType, CorrelationData = connectPacket.WillCorrelationData, MessageExpiryInterval = connectPacket.WillMessageExpiryInterval, PayloadFormatIndicator = connectPacket.WillPayloadFormatIndicator, ResponseTopic = connectPacket.WillResponseTopic, UserProperties = connectPacket.WillUserProperties }; return(packet); }
public MqttClientConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter, MqttClientSession session, MqttConnectionValidatorContext connectionValidatorContext, IMqttServerOptions serverOptions, MqttClientSessionsManager sessionsManager, IMqttRetainedMessagesManager retainedMessagesManager, IMqttNetLogger logger) { Session = session ?? throw new ArgumentNullException(nameof(session)); _serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions)); _sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager)); _retainedMessagesManager = retainedMessagesManager ?? throw new ArgumentNullException(nameof(retainedMessagesManager)); _channelAdapter = channelAdapter ?? throw new ArgumentNullException(nameof(channelAdapter)); _connectionValidatorContext = connectionValidatorContext ?? throw new ArgumentNullException(nameof(connectionValidatorContext)); _dataConverter = _channelAdapter.PacketFormatterAdapter.DataConverter; _endpoint = _channelAdapter.Endpoint; ConnectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket)); if (logger == null) { throw new ArgumentNullException(nameof(logger)); } _logger = logger.CreateScopedLogger(nameof(MqttClientConnection)); _connectedTimestamp = DateTime.UtcNow; LastPacketReceivedTimestamp = _connectedTimestamp; _lastNonKeepAlivePacketReceivedTimestamp = LastPacketReceivedTimestamp; }
private async Task <MqttConnAckPacket> AuthenticateAsync(MqttApplicationMessage willApplicationMessage, CancellationToken cancellationToken) { string userName = null; string password = null; Options.Credentials?.Create(out userName, out password); var connectPacket = new MqttConnectPacket { ClientId = Options.ClientId, Username = userName, Password = password, CleanSession = Options.CleanSession, KeepAlivePeriod = (ushort)Options.KeepAlivePeriod.TotalSeconds, WillMessage = willApplicationMessage }; var response = await SendAndReceiveAsync <MqttConnAckPacket>(connectPacket, cancellationToken).ConfigureAwait(false); if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted) { throw new MqttConnectingFailedException(response.ConnectReturnCode); } return(response); }
public MqttClient( MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter, MqttSession session, MqttServerOptions serverOptions, MqttServerEventContainer eventContainer, MqttClientSessionsManager sessionsManager, IMqttNetLogger logger) { _serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions)); _eventContainer = eventContainer; _sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager)); ChannelAdapter = channelAdapter ?? throw new ArgumentNullException(nameof(channelAdapter)); Endpoint = channelAdapter.Endpoint; Session = session ?? throw new ArgumentNullException(nameof(session)); _connectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket)); if (logger == null) { throw new ArgumentNullException(nameof(logger)); } _logger = logger.WithSource(nameof(MqttClient)); }
public MqttClientConnection( MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter, MqttClientSession session, IMqttServerOptions serverOptions, MqttClientSessionsManager sessionsManager, MqttRetainedMessagesManager retainedMessagesManager, IMqttNetChildLogger logger) { Session = session ?? throw new ArgumentNullException(nameof(session)); _serverOptions = serverOptions ?? throw new ArgumentNullException(nameof(serverOptions)); _sessionsManager = sessionsManager ?? throw new ArgumentNullException(nameof(sessionsManager)); _retainedMessagesManager = retainedMessagesManager ?? throw new ArgumentNullException(nameof(retainedMessagesManager)); _channelAdapter = channelAdapter ?? throw new ArgumentNullException(nameof(channelAdapter)); _dataConverter = _channelAdapter.PacketFormatterAdapter.DataConverter; _endpoint = _channelAdapter.Endpoint; _connectPacket = connectPacket ?? throw new ArgumentNullException(nameof(connectPacket)); if (logger == null) { throw new ArgumentNullException(nameof(logger)); } _logger = logger.CreateChildLogger(nameof(MqttClientConnection)); _keepAliveMonitor = new MqttClientKeepAliveMonitor(_connectPacket.ClientId, StopAsync, _logger); _connectedTimestamp = DateTime.UtcNow; _lastPacketReceivedTimestamp = _connectedTimestamp; _lastNonKeepAlivePacketReceivedTimestamp = _lastPacketReceivedTimestamp; }
async Task <MqttConnectionValidatorContext> ValidateConnectionAsync(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter) { var context = new MqttConnectionValidatorContext(connectPacket, channelAdapter, new ConcurrentDictionary <object, object>()); var connectionValidator = _options.ConnectionValidator; if (connectionValidator == null) { context.ReasonCode = MqttConnectReasonCode.Success; return(context); } await connectionValidator.ValidateConnectionAsync(context).ConfigureAwait(false); // Check the client ID and set a random one if supported. if (string.IsNullOrEmpty(connectPacket.ClientId) && channelAdapter.PacketFormatterAdapter.ProtocolVersion == MqttProtocolVersion.V500) { connectPacket.ClientId = context.AssignedClientIdentifier; } if (string.IsNullOrEmpty(connectPacket.ClientId)) { context.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid; } return(context); }
public void DetectVersionFromMqttConnectPacket() { var packet = new MqttConnectPacket { ClientId = "XYZ", Password = Encoding.UTF8.GetBytes("PASS"), Username = "******", KeepAlivePeriod = 123, CleanSession = true }; Assert.AreEqual( MqttProtocolVersion.V310, DeserializeAndDetectVersion(new MqttPacketFormatterAdapter(new MqttPacketWriter()), Serialize(packet, MqttProtocolVersion.V310))); Assert.AreEqual( MqttProtocolVersion.V311, DeserializeAndDetectVersion(new MqttPacketFormatterAdapter(new MqttPacketWriter()), Serialize(packet, MqttProtocolVersion.V311))); Assert.AreEqual( MqttProtocolVersion.V500, DeserializeAndDetectVersion(new MqttPacketFormatterAdapter(new MqttPacketWriter()), Serialize(packet, MqttProtocolVersion.V500))); var adapter = new MqttPacketFormatterAdapter(new MqttPacketWriter()); var ex = Assert.ThrowsException <MqttProtocolViolationException>(() => DeserializeAndDetectVersion(adapter, WriterFactory().AddMqttHeader(MqttControlPacketType.Connect, new byte[0]))); Assert.AreEqual("CONNECT packet must have at least 7 bytes.", ex.Message); ex = Assert.ThrowsException <MqttProtocolViolationException>(() => DeserializeAndDetectVersion(adapter, WriterFactory().AddMqttHeader(MqttControlPacketType.Connect, new byte[7]))); Assert.AreEqual("Protocol '' not supported.", ex.Message); ex = Assert.ThrowsException <MqttProtocolViolationException>(() => DeserializeAndDetectVersion(adapter, WriterFactory().AddMqttHeader(MqttControlPacketType.Connect, new byte[] { 255, 255, 0, 0, 0, 0, 0 }))); Assert.AreEqual("Expected at least 65537 bytes but there are only 7 bytes", ex.Message); }
private byte Serialize(MqttConnectPacket packet, MqttPacketWriter writer) { ValidateConnectPacket(packet); // Write variable header writer.Write(0x00, 0x04); // 3.1.2.1 Protocol Name if (ProtocolVersion == MqttProtocolVersion.V311) { writer.Write(ProtocolVersionV311Name); writer.Write(0x04); // 3.1.2.2 Protocol Level (4) } else { writer.Write(ProtocolVersionV310Name); writer.Write(0x64, 0x70, 0x03); // Protocol Level (0x03) } var connectFlags = new ByteWriter(); // 3.1.2.3 Connect Flags connectFlags.Write(false); // Reserved connectFlags.Write(packet.CleanSession); connectFlags.Write(packet.WillMessage != null); if (packet.WillMessage != null) { connectFlags.Write((int)packet.WillMessage.QualityOfServiceLevel, 2); connectFlags.Write(packet.WillMessage.Retain); } else { connectFlags.Write(0, 2); connectFlags.Write(false); } connectFlags.Write(packet.Password != null); connectFlags.Write(packet.Username != null); writer.Write(connectFlags); writer.Write(packet.KeepAlivePeriod); writer.WriteWithLengthPrefix(packet.ClientId); if (packet.WillMessage != null) { writer.WriteWithLengthPrefix(packet.WillMessage.Topic); writer.WriteWithLengthPrefix(packet.WillMessage.Payload); } if (packet.Username != null) { writer.WriteWithLengthPrefix(packet.Username); } if (packet.Password != null) { writer.WriteWithLengthPrefix(packet.Password); } return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Connect)); }
async Task <MqttClientConnection> CreateClientConnection( MqttConnectPacket connectPacket, MqttConnAckPacket connAckPacket, IMqttChannelAdapter channelAdapter, IDictionary <object, object> sessionItems) { MqttClientConnection connection; using (await _createConnectionSyncRoot.WaitAsync(CancellationToken.None).ConfigureAwait(false)) { MqttClientSession session; lock (_clientSessions) { if (!_clientSessions.TryGetValue(connectPacket.ClientId, out session)) { _logger.Verbose("Created a new session for client '{0}'.", connectPacket.ClientId); session = CreateSession(connectPacket.ClientId, sessionItems); } else { if (connectPacket.CleanSession) { _logger.Verbose("Deleting existing session of client '{0}'.", connectPacket.ClientId); session = CreateSession(connectPacket.ClientId, sessionItems); } else { _logger.Verbose("Reusing existing session of client '{0}'.", connectPacket.ClientId); connAckPacket.IsSessionPresent = true; } } _clientSessions[connectPacket.ClientId] = session; } MqttClientConnection existingConnection; lock (_clientConnections) { _clientConnections.TryGetValue(connectPacket.ClientId, out existingConnection); connection = CreateConnection(connectPacket, channelAdapter, session); _clientConnections[connectPacket.ClientId] = connection; } if (existingConnection != null) { await _eventDispatcher.SafeNotifyClientDisconnectedAsync(existingConnection.ClientId, MqttClientDisconnectType.Takeover, existingConnection.Endpoint); existingConnection.IsTakenOver = true; await existingConnection.StopAsync(MqttClientDisconnectReason.SessionTakenOver) .ConfigureAwait(false); } } return(connection); }
private MqttConnectReturnCode ValidateConnection(MqttConnectPacket connectPacket) { if (_options.ConnectionValidator != null) { return(_options.ConnectionValidator(connectPacket)); } return(MqttConnectReturnCode.ConnectionAccepted); }
private static async Task <MqttBasePacket> DeserializeConnectAsync(MqttPacketReader reader) { await reader.ReadRemainingDataAsync(2); // Skip 2 bytes var protocolName = await reader.ReadRemainingDataAsync(4); if (Encoding.UTF8.GetString(protocolName, 0, protocolName.Length) != "MQTT") { throw new MqttProtocolViolationException("Protocol name is not 'MQTT'."); } var protocolLevel = await reader.ReadRemainingDataByteAsync(); var connectFlags = await reader.ReadRemainingDataByteAsync(); var connectFlagsReader = new ByteReader(connectFlags); connectFlagsReader.Read(); // Reserved. var packet = new MqttConnectPacket { CleanSession = connectFlagsReader.Read() }; var willFlag = connectFlagsReader.Read(); var willQoS = connectFlagsReader.Read(2); var willRetain = connectFlagsReader.Read(); var passwordFlag = connectFlagsReader.Read(); var usernameFlag = connectFlagsReader.Read(); packet.KeepAlivePeriod = await reader.ReadRemainingDataUShortAsync(); packet.ClientId = await reader.ReadRemainingDataStringWithLengthPrefixAsync(); if (willFlag) { packet.WillMessage = new MqttApplicationMessage( await reader.ReadRemainingDataStringWithLengthPrefixAsync(), await reader.ReadRemainingDataWithLengthPrefixAsync(), (MqttQualityOfServiceLevel)willQoS, willRetain); } if (usernameFlag) { packet.Username = await reader.ReadRemainingDataStringWithLengthPrefixAsync(); } if (passwordFlag) { packet.Password = await reader.ReadRemainingDataStringWithLengthPrefixAsync(); } ValidateConnectPacket(packet); return(packet); }
MqttClientConnection CreateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter, MqttClientSession session) { return(new MqttClientConnection( connectPacket, channelAdapter, session, _options, this, _rootLogger)); }
private Task SerializeAsync(MqttConnectPacket packet, IMqttCommunicationChannel destination) { ValidateConnectPacket(packet); using (var output = new MqttPacketWriter()) { // Write variable header output.Write(0x00, 0x04); // 3.1.2.1 Protocol Name output.Write(MqttPrefix); output.Write(0x04); // 3.1.2.2 Protocol Level var connectFlags = new ByteWriter(); // 3.1.2.3 Connect Flags connectFlags.Write(false); // Reserved connectFlags.Write(packet.CleanSession); connectFlags.Write(packet.WillMessage != null); if (packet.WillMessage != null) { connectFlags.Write((int)packet.WillMessage.QualityOfServiceLevel, 2); connectFlags.Write(packet.WillMessage.Retain); } else { connectFlags.Write(0, 2); connectFlags.Write(false); } connectFlags.Write(packet.Password != null); connectFlags.Write(packet.Username != null); output.Write(connectFlags); output.Write(packet.KeepAlivePeriod); output.WriteWithLengthPrefix(packet.ClientId); if (packet.WillMessage != null) { output.WriteWithLengthPrefix(packet.WillMessage.Topic); output.WriteWithLengthPrefix(packet.WillMessage.Payload); } if (packet.Username != null) { output.WriteWithLengthPrefix(packet.Username); } if (packet.Password != null) { output.WriteWithLengthPrefix(packet.Password); } output.InjectFixedHeader(MqttControlPacketType.Connect); return(output.WriteToAsync(destination)); } }
protected void ValidateConnectPacket(MqttConnectPacket packet) { if (packet == null) { throw new ArgumentNullException(nameof(packet)); } if (string.IsNullOrEmpty(packet.ClientId) && !packet.CleanSession) { throw new MqttProtocolViolationException("CleanSession must be set if ClientId is empty [MQTT-3.1.3-7]."); } }
MqttClientConnection CreateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter, MqttClientSession session, MqttConnectionValidatorContext connectionValidatorContext) { return(new MqttClientConnection( connectPacket, channelAdapter, session, connectionValidatorContext, _options, this, _retainedMessagesManager, _rootLogger)); }
public void DeserializeV311_MqttConnectPacket() { var p = new MqttConnectPacket { ClientId = "XYZ", Password = Encoding.UTF8.GetBytes("PASS"), Username = "******", KeepAlivePeriod = 123, CleanSession = true }; DeserializeAndCompare(p, "EBsABE1RVFQEwgB7AANYWVoABFVTRVIABFBBU1M="); }
public void SerializeV310_MqttConnectPacket() { var p = new MqttConnectPacket { ClientId = "XYZ", Password = Encoding.UTF8.GetBytes("PASS"), Username = "******", KeepAlivePeriod = 123, CleanSession = true }; SerializeAndCompare(p, "EB0ABk1RSXNkcAPCAHsAA1hZWgAEVVNFUgAEUEFTUw==", MqttProtocolVersion.V310); }
public async Task ConnectAsync(MqttApplicationMessage willApplicationMessage = null) { MqttTrace.Verbose(nameof(MqttClient), "Trying to connect."); if (IsConnected) { throw new MqttProtocolViolationException("It is not allowed to connect with a server after the connection is established."); } var connectPacket = new MqttConnectPacket { ClientId = _options.ClientId, Username = _options.UserName, Password = _options.Password, CleanSession = _options.CleanSession, KeepAlivePeriod = (ushort)_options.KeepAlivePeriod.TotalSeconds, WillMessage = willApplicationMessage }; await _adapter.ConnectAsync(_options, _options.DefaultCommunicationTimeout); MqttTrace.Verbose(nameof(MqttClient), "Connection with server established."); _cancellationTokenSource = new CancellationTokenSource(); _latestPacketIdentifier = 0; _processedPublishPackets.Clear(); _packetDispatcher.Reset(); IsConnected = true; #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Task.Run(() => ReceivePackets(_cancellationTokenSource.Token), _cancellationTokenSource.Token); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed var response = await SendAndReceiveAsync <MqttConnAckPacket>(connectPacket); if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted) { await DisconnectAsync(); throw new MqttConnectingFailedException(response.ConnectReturnCode); } if (_options.KeepAlivePeriod != TimeSpan.Zero) { #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Task.Run(() => SendKeepAliveMessagesAsync(_cancellationTokenSource.Token), _cancellationTokenSource.Token); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } Connected?.Invoke(this, EventArgs.Empty); }
public async Task ConnectAsync(MqttApplicationMessage willApplicationMessage = null) { ThrowIfConnected("It is not allowed to connect with a server after the connection is established."); try { _cancellationTokenSource = new CancellationTokenSource(); _latestPacketIdentifier = 0; _packetDispatcher.Reset(); MqttTrace.Verbose(nameof(MqttClient), "Trying to connect with server."); await _adapter.ConnectAsync(_options.DefaultCommunicationTimeout, _options).ConfigureAwait(false); MqttTrace.Verbose(nameof(MqttClient), "Connection with server established."); StartReceivePackets(_cancellationTokenSource.Token); var connectPacket = new MqttConnectPacket { ClientId = _options.ClientId, Username = _options.UserName, Password = _options.Password, CleanSession = _options.CleanSession, KeepAlivePeriod = (ushort)_options.KeepAlivePeriod.TotalSeconds, WillMessage = willApplicationMessage }; var response = await SendAndReceiveAsync <MqttConnAckPacket>(connectPacket).ConfigureAwait(false); if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted) { throw new MqttConnectingFailedException(response.ConnectReturnCode); } MqttTrace.Verbose(nameof(MqttClient), "MQTT connection with server established."); if (_options.KeepAlivePeriod != TimeSpan.Zero) { StartSendKeepAliveMessages(_cancellationTokenSource.Token); } Connected?.Invoke(this, EventArgs.Empty); } catch (Exception) { await DisconnectInternalAsync().ConfigureAwait(false); throw; } }
private MqttConnectReturnCode ValidateConnection(MqttConnectPacket connectPacket) { if (_options.ConnectionValidator == null) { return(MqttConnectReturnCode.ConnectionAccepted); } var context = new MqttConnectionValidatorContext( connectPacket.ClientId, connectPacket.Username, connectPacket.Password, connectPacket.WillMessage); _options.ConnectionValidator(context); return(context.ReturnCode); }
async Task <MqttClientConnection> CreateClientConnectionAsync(MqttConnectPacket connectPacket, MqttConnectionValidatorContext connectionValidatorContext, IMqttChannelAdapter channelAdapter) { MqttClientConnection existingConnection; MqttClientConnection connection; using (await _createConnectionSyncRoot.WaitAsync(CancellationToken.None).ConfigureAwait(false)) { MqttClientSession session; lock (_sessions) { if (!_sessions.TryGetValue(connectPacket.ClientId, out session)) { _logger.Verbose("Created a new session for client '{0}'.", connectPacket.ClientId); session = CreateSession(connectPacket.ClientId, connectionValidatorContext); } else { if (connectPacket.CleanSession) { _logger.Verbose("Deleting existing session of client '{0}'.", connectPacket.ClientId); session = CreateSession(connectPacket.ClientId, connectionValidatorContext); } else { _logger.Verbose("Reusing existing session of client '{0}'.", connectPacket.ClientId); } } _sessions[connectPacket.ClientId] = session; } lock (_connections) { _connections.TryGetValue(connectPacket.ClientId, out existingConnection); connection = CreateConnection(connectPacket, channelAdapter, session, connectionValidatorContext); _connections[connectPacket.ClientId] = connection; } if (existingConnection != null) { await existingConnection.StopAsync(MqttClientDisconnectReason.SessionTakenOver).ConfigureAwait(false); } } return(connection); }
async Task <MqttClientConnection> CreateClientConnectionAsync(MqttConnectPacket connectPacket, MqttConnectionValidatorContext connectionValidatorContext, IMqttChannelAdapter channelAdapter) { MqttClientConnection connection; MqttClientConnection existingConnection = null; using (await _createConnectionGate.WaitAsync(_cancellationToken).ConfigureAwait(false)) { var session = _sessions.AddOrUpdate( connectPacket.ClientId, key => { _logger.Verbose("Created a new session for client '{0}'.", key); return(new MqttClientSession(key, connectionValidatorContext.SessionItems, _eventDispatcher, _options, _retainedMessagesManager, _rootLogger)); }, (key, existingSession) => { if (connectPacket.CleanSession) { _logger.Verbose("Deleting existing session of client '{0}'.", connectPacket.ClientId); return(new MqttClientSession(key, connectionValidatorContext.SessionItems, _eventDispatcher, _options, _retainedMessagesManager, _rootLogger)); } _logger.Verbose("Reusing existing session of client '{0}'.", connectPacket.ClientId); return(existingSession); }); connection = new MqttClientConnection(connectPacket, channelAdapter, session, connectionValidatorContext, _options, this, _retainedMessagesManager, _rootLogger); _connections.AddOrUpdate( connectPacket.ClientId, key => connection, (key, tempExistingConnection) => { existingConnection = tempExistingConnection; return(connection); }); } // Disconnect the client outside of the lock so that new clients can still connect while a single // one is being disconnected. if (existingConnection != null) { await existingConnection.StopAsync(true).ConfigureAwait(false); } return(connection); }
private async Task <MqttClientConnection> CreateConnectionAsync(MqttConnectPacket connectPacket, MqttConnectionValidatorContext connectionValidatorContext, IMqttChannelAdapter channelAdapter) { await _createConnectionGate.WaitAsync(_cancellationToken).ConfigureAwait(false); try { var isSessionPresent = _sessions.TryGetValue(connectPacket.ClientId, out var session); var isConnectionPresent = _connections.TryGetValue(connectPacket.ClientId, out var existingConnection); if (isConnectionPresent) { await existingConnection.StopAsync().ConfigureAwait(false); } if (isSessionPresent) { if (connectPacket.CleanSession) { session = null; _logger.Verbose("Deleting existing session of client '{0}'.", connectPacket.ClientId); } else { _logger.Verbose("Reusing existing session of client '{0}'.", connectPacket.ClientId); } } if (session == null) { session = new MqttClientSession(connectPacket.ClientId, connectionValidatorContext.SessionItems, _eventDispatcher, _options, _logger); _logger.Verbose("Created a new session for client '{0}'.", connectPacket.ClientId); } var connection = new MqttClientConnection(connectPacket, channelAdapter, session, _options, this, _retainedMessagesManager, _logger); _connections[connection.ClientId] = connection; _sessions[session.ClientId] = session; return(connection); } finally { _createConnectionGate.Release(); } }
public MqttConnectPacket Create(MqttClientOptions clientOptions) { if (clientOptions == null) { throw new ArgumentNullException(nameof(clientOptions)); } var connectPacket = new MqttConnectPacket { ClientId = clientOptions.ClientId, Username = clientOptions.Credentials?.GetUserName(clientOptions), Password = clientOptions.Credentials?.GetPassword(clientOptions), CleanSession = clientOptions.CleanSession, KeepAlivePeriod = (ushort)clientOptions.KeepAlivePeriod.TotalSeconds, AuthenticationMethod = clientOptions.AuthenticationMethod, AuthenticationData = clientOptions.AuthenticationData, WillDelayInterval = clientOptions.WillDelayInterval, MaximumPacketSize = clientOptions.MaximumPacketSize, ReceiveMaximum = clientOptions.ReceiveMaximum, RequestProblemInformation = clientOptions.RequestProblemInformation, RequestResponseInformation = clientOptions.RequestResponseInformation, SessionExpiryInterval = clientOptions.SessionExpiryInterval, TopicAliasMaximum = clientOptions.TopicAliasMaximum, UserProperties = clientOptions.UserProperties, TryPrivate = clientOptions.TryPrivate }; if (!string.IsNullOrEmpty(clientOptions.WillTopic)) { connectPacket.WillFlag = true; connectPacket.WillTopic = clientOptions.WillTopic; connectPacket.WillQoS = clientOptions.WillQualityOfServiceLevel; connectPacket.WillMessage = clientOptions.WillPayload; connectPacket.WillRetain = clientOptions.WillRetain; connectPacket.WillDelayInterval = clientOptions.WillDelayInterval; connectPacket.WillContentType = clientOptions.WillContentType; connectPacket.WillCorrelationData = clientOptions.WillCorrelationData; connectPacket.WillResponseTopic = clientOptions.WillResponseTopic; connectPacket.WillMessageExpiryInterval = clientOptions.WillMessageExpiryInterval; connectPacket.WillPayloadFormatIndicator = clientOptions.WillPayloadFormatIndicator; connectPacket.WillUserProperties = clientOptions.WillUserProperties; } return(connectPacket); }
public void DeserializeV311_MqttConnectPacketWithWillMessage() { var p = new MqttConnectPacket { ClientId = "XYZ", Password = "******", Username = "******", KeepAlivePeriod = 123, CleanSession = true, WillMessage = new MqttApplicationMessage( "My/last/will", Encoding.UTF8.GetBytes("Good byte."), MqttQualityOfServiceLevel.AtLeastOnce, true) }; DeserializeAndCompare(p, "EDUABE1RVFQE7gB7AANYWVoADE15L2xhc3Qvd2lsbAAKR29vZCBieXRlLgAEVVNFUgAEUEFTUw=="); }
MqttClientConnection CreateClientConnection(MqttConnectPacket connectPacket, MqttConnectionValidatorContext connectionValidatorContext, IMqttChannelAdapter channelAdapter) { lock (_createConnectionSyncRoot) { MqttClientSession session; lock (_sessions) { if (!_sessions.TryGetValue(connectPacket.ClientId, out session)) { _logger.Verbose("Created a new session for client '{0}'.", connectPacket.ClientId); session = CreateSession(connectPacket.ClientId, connectionValidatorContext); } else { if (connectPacket.CleanSession) { _logger.Verbose("Deleting existing session of client '{0}'.", connectPacket.ClientId); session = CreateSession(connectPacket.ClientId, connectionValidatorContext); } else { _logger.Verbose("Reusing existing session of client '{0}'.", connectPacket.ClientId); } } _sessions[connectPacket.ClientId] = session; } MqttClientConnection existingConnection; MqttClientConnection connection; lock (_connections) { _connections.TryGetValue(connectPacket.ClientId, out existingConnection); connection = CreateConnection(connectPacket, channelAdapter, session, connectionValidatorContext); _connections[connectPacket.ClientId] = connection; } existingConnection?.StopAsync(MqttClientDisconnectReason.SessionTakenOver).GetAwaiter().GetResult(); return(connection); } }
private async Task AuthenticateAsync(MqttApplicationMessage willApplicationMessage) { var connectPacket = new MqttConnectPacket { ClientId = _options.ClientId, Username = _options.UserName, Password = _options.Password, CleanSession = _options.CleanSession, KeepAlivePeriod = (ushort)_options.KeepAlivePeriod.TotalSeconds, WillMessage = willApplicationMessage }; var response = await SendAndReceiveAsync <MqttConnAckPacket>(connectPacket).ConfigureAwait(false); if (response.ConnectReturnCode != MqttConnectReturnCode.ConnectionAccepted) { throw new MqttConnectingFailedException(response.ConnectReturnCode); } }
public async Task RunAsync(MqttConnectPacket connectPacket, IMqttChannelAdapter adapter) { if (connectPacket == null) { throw new ArgumentNullException(nameof(connectPacket)); } if (adapter == null) { throw new ArgumentNullException(nameof(adapter)); } try { var cancellationTokenSource = new CancellationTokenSource(); _willMessage = connectPacket.WillMessage; _adapter = adapter; _cancellationTokenSource = cancellationTokenSource; _pendingMessagesQueue.Start(adapter, cancellationTokenSource.Token); _lastPacketReceivedTracker.Restart(); _lastNonKeepAlivePacketReceivedTracker.Restart(); if (connectPacket.KeepAlivePeriod > 0) { StartCheckingKeepAliveTimeout(TimeSpan.FromSeconds(connectPacket.KeepAlivePeriod), cancellationTokenSource.Token); } await ReceivePacketsAsync(adapter, cancellationTokenSource.Token).ConfigureAwait(false); } catch (OperationCanceledException) { } catch (MqttCommunicationException exception) { _logger.Warning <MqttClientSession>(exception, "Client '{0}': Communication exception while processing client packets.", ClientId); } catch (Exception exception) { _logger.Error <MqttClientSession>(exception, "Client '{0}': Unhandled exception while processing client packets.", ClientId); } }
async Task <ValidatingConnectionEventArgs> ValidateConnection(MqttConnectPacket connectPacket, IMqttChannelAdapter channelAdapter) { var context = new ValidatingConnectionEventArgs(connectPacket, channelAdapter) { SessionItems = new ConcurrentDictionary <object, object>() }; await _eventContainer.ValidatingConnectionEvent.InvokeAsync(context).ConfigureAwait(false); // Check the client ID and set a random one if supported. if (string.IsNullOrEmpty(connectPacket.ClientId) && channelAdapter.PacketFormatterAdapter.ProtocolVersion == MqttProtocolVersion.V500) { connectPacket.ClientId = context.AssignedClientIdentifier; } if (string.IsNullOrEmpty(connectPacket.ClientId)) { context.ReasonCode = MqttConnectReasonCode.ClientIdentifierNotValid; } return(context); }