async Task HandleConnectionExceptionAsync(Exception exception) { if (exception is TimeoutException) { await NotifyErrorAsync(ServerProperties.Resources.ServerPacketListener_NoConnectReceived, exception) .ConfigureAwait(continueOnCapturedContext: false); } else if (exception is MqttConnectionException) { tracer.Error(exception, ServerProperties.Resources.ServerPacketListener_ConnectionError, clientId ?? "N/A"); var connectEx = exception as MqttConnectionException; var errorAck = new ConnectAck(connectEx.ReturnCode, existingSession: false); try { await channel.SendAsync(errorAck) .ConfigureAwait(continueOnCapturedContext: false); } catch (Exception ex) { await NotifyErrorAsync(ex).ConfigureAwait(continueOnCapturedContext: false); } } else { await NotifyErrorAsync(exception).ConfigureAwait(continueOnCapturedContext: false); } }
public async Task ExecuteAsync(string clientId, IPacket input, IMqttChannel <IPacket> channel) { if (input.Type != MqttPacketType.Unsubscribe) { return; } var unsubscribe = input as Unsubscribe; var session = sessionRepository.Read(clientId); if (session == null) { throw new MqttException(string.Format(Properties.Resources.SessionRepository_ClientSessionNotFound, clientId)); } foreach (var topic in unsubscribe.Topics) { var subscription = session.GetSubscriptions().FirstOrDefault(s => s.TopicFilter == topic); if (subscription != null) { session.RemoveSubscription(subscription); } } sessionRepository.Update(session); await channel.SendAsync(new UnsubscribeAck (unsubscribe.PacketId)) .ConfigureAwait(continueOnCapturedContext: false); }
protected async Task MonitorAckAsync <T> (Publish sentMessage, string clientId, IMqttChannel <IPacket> channel) where T : IFlowPacket { var intervalSubscription = Observable .Interval(TimeSpan.FromSeconds(configuration.WaitTimeoutSecs), NewThreadScheduler.Default) .Subscribe(async _ => { if (channel.IsConnected) { tracer.Warn(Properties.Resources.PublishFlow_RetryingQoSFlow, sentMessage.Type, clientId); var duplicated = new Publish(sentMessage.Topic, sentMessage.QualityOfService, sentMessage.Retain, duplicated: true, packetId: sentMessage.PacketId) { Payload = sentMessage.Payload }; await channel.SendAsync(duplicated); } }); await channel .ReceiverStream .ObserveOn(NewThreadScheduler.Default) .OfType <T> () .FirstOrDefaultAsync(x => x.PacketId == sentMessage.PacketId.Value); intervalSubscription.Dispose(); }
void StartKeepAliveMonitor() { var interval = configuration.KeepAliveSecs * 1000; keepAliveTimer = new Timer(); keepAliveTimer.AutoReset = true; keepAliveTimer.IntervalMillisecs = interval; keepAliveTimer.Elapsed += async(sender, e) => { try { tracer.Warn(Properties.Resources.ClientPacketListener_SendingKeepAlive, clientId, configuration.KeepAliveSecs); var ping = new PingRequest(); await channel.SendAsync(ping) .ConfigureAwait(continueOnCapturedContext: false); } catch (Exception ex) { NotifyError(ex); } }; keepAliveTimer.Start(); channel.SenderStream.Subscribe(p => { keepAliveTimer.IntervalMillisecs = interval; }); }
void StartKeepAliveMonitor() { int interval = _configuration.KeepAliveSecs * 1000; _keepAliveTimer = new Timer { AutoReset = true, IntervalMillisecs = interval }; _keepAliveTimer.Elapsed += async(sender, e) => { try { _tracer.Warn(ClientProperties.ClientPacketListener_SendingKeepAlive(_clientId, _configuration.KeepAliveSecs)); PingRequest ping = new PingRequest(); await _channel.SendAsync(ping); } catch (Exception ex) { NotifyError(ex); } }; _keepAliveTimer.Start(); _channel.SenderStream.Subscribe(p => { _keepAliveTimer.IntervalMillisecs = interval; }); }
public async Task SendPublishAsync(string clientId, Publish message, IMqttChannel <IPacket> channel, PendingMessageStatus status = PendingMessageStatus.PendingToSend) { if (channel == null || !channel.IsConnected) { SaveMessage(message, clientId, PendingMessageStatus.PendingToSend); return; } var qos = configuration.GetSupportedQos(message.QualityOfService); if (qos != MqttQualityOfService.AtMostOnce && status == PendingMessageStatus.PendingToSend) { SaveMessage(message, clientId, PendingMessageStatus.PendingToAcknowledge); } await channel.SendAsync(message) .ConfigureAwait(continueOnCapturedContext: false); if (qos == MqttQualityOfService.AtLeastOnce) { await MonitorAckAsync <PublishAck> (message, clientId, channel) .ConfigureAwait(continueOnCapturedContext: false); } else if (qos == MqttQualityOfService.ExactlyOnce) { await MonitorAckAsync <PublishReceived> (message, clientId, channel).ConfigureAwait(continueOnCapturedContext: false); await channel .ReceiverStream .ObserveOn(NewThreadScheduler.Default) .OfType <PublishComplete> () .FirstOrDefaultAsync(x => x.PacketId == message.PacketId.Value); } }
async Task HandleConnectionExceptionAsync(Exception exception) { if (exception is TimeoutException) { await NotifyErrorAsync(ServerProperties.ServerPacketListener_NoConnectReceived, exception); } else if (exception is MqttConnectionException) { _tracer.Error(exception, ServerProperties.ServerPacketListener_ConnectionError(_clientId ?? "N/A")); MqttConnectionException connectEx = exception as MqttConnectionException; ConnectAck errorAck = new ConnectAck(connectEx.ReturnCode, existingSession: false); try { await _channel.SendAsync(errorAck); } catch (Exception ex) { await NotifyErrorAsync(ex); } } else { await NotifyErrorAsync(exception); } }
public async Task ExecuteAsync(string clientId, IPacket input, IMqttChannel <IPacket> channel) { if (input.Type != MqttPacketType.Unsubscribe) { return; } Unsubscribe unsubscribe = input as Unsubscribe; ClientSession session = _sessionRepository.Read(clientId); if (session == null) { throw new MqttException(ServerProperties.SessionRepository_ClientSessionNotFound(clientId)); } foreach (string topic in unsubscribe.Topics) { ClientSubscription subscription = session.GetSubscriptions().FirstOrDefault(s => s.TopicFilter == topic); if (subscription != null) { session.RemoveSubscription(subscription); } } _sessionRepository.Update(session); await channel.SendAsync(new UnsubscribeAck( unsubscribe.PacketId )); }
async Task SendPacketAsync(IPacket packet) { sender.OnNext(packet); await clientSender.Run(async() => await packetChannel.SendAsync (packet).ConfigureAwait(continueOnCapturedContext: false)) .ConfigureAwait(continueOnCapturedContext: false); }
public async Task SendAckAsync(string clientId, IFlowPacket ack, IMqttChannel <IPacket> channel, PendingMessageStatus status = PendingMessageStatus.PendingToSend) { if ((ack.Type == MqttPacketType.PublishReceived || ack.Type == MqttPacketType.PublishRelease) && status == PendingMessageStatus.PendingToSend) { SavePendingAcknowledgement(ack, clientId); } if (!channel.IsConnected) { return; } await channel.SendAsync(ack) .ConfigureAwait(continueOnCapturedContext: false); if (ack.Type == MqttPacketType.PublishReceived) { await MonitorAckAsync <PublishRelease> (ack, clientId, channel) .ConfigureAwait(continueOnCapturedContext: false); } else if (ack.Type == MqttPacketType.PublishRelease) { await MonitorAckAsync <PublishComplete> (ack, clientId, channel) .ConfigureAwait(continueOnCapturedContext: false); } }
public async Task ExecuteAsync(string clientId, IPacket input, IMqttChannel <IPacket> channel) { if (input.Type != MqttPacketType.Connect) { return; } var connect = input as Connect; if (!authenticationProvider.Authenticate(clientId, connect.UserName, connect.Password)) { throw new MqttConnectionException(MqttConnectionStatus.BadUserNameOrPassword); } var session = sessionRepository.Read(clientId); var sessionPresent = connect.CleanSession ? false : session != null; if (connect.CleanSession && session != null) { sessionRepository.Delete(session.Id); session = null; tracer.Info(Server.Properties.Resources.Server_CleanedOldSession, clientId); } var sendPendingMessages = false; if (session == null) { session = new ClientSession(clientId, connect.CleanSession); sessionRepository.Create(session); tracer.Info(Server.Properties.Resources.Server_CreatedSession, clientId); } else { sendPendingMessages = true; } if (connect.Will != null) { var connectionWill = new ConnectionWill(clientId, connect.Will); willRepository.Create(connectionWill); } await channel.SendAsync(new ConnectAck (MqttConnectionStatus.Accepted, sessionPresent)) .ConfigureAwait(continueOnCapturedContext: false); if (sendPendingMessages) { await SendPendingMessagesAsync(session, channel) .ConfigureAwait(continueOnCapturedContext: false); await SendPendingAcknowledgementsAsync(session, channel) .ConfigureAwait(continueOnCapturedContext: false); } }
public async Task ExecuteAsync(string clientId, IPacket input, IMqttChannel <IPacket> channel) { if (input.Type != MqttPacketType.PingRequest) { return; } await channel.SendAsync(new PingResponse()); }
public async Task ExecuteAsync(string clientId, IPacket input, IMqttChannel <IPacket> channel) { if (input.Type != MqttPacketType.Connect) { return; } Connect connect = input as Connect; if (!_authenticationProvider.Authenticate(clientId, connect.UserName, connect.Password)) { throw new MqttConnectionException(MqttConnectionStatus.BadUserNameOrPassword); } ClientSession session = _sessionRepository.Read(clientId); bool sessionPresent = connect.CleanSession ? false : session != null; _tracer.Info($"Client connecting with protocol level {connect.ProtocolLelvel}."); if (connect.CleanSession && session != null) { _sessionRepository.Delete(session.Id); session = null; _tracer.Info(ServerProperties.Server_CleanedOldSession(clientId)); } bool sendPendingMessages = false; if (session == null) { session = new ClientSession(clientId, connect.CleanSession); _sessionRepository.Create(session); _tracer.Info(ServerProperties.Server_CreatedSession(clientId)); } else { sendPendingMessages = true; } if (connect.Will != null) { ConnectionWill connectionWill = new ConnectionWill(clientId, connect.Will); _willRepository.Create(connectionWill); } await channel.SendAsync(new ConnectAck( MqttConnectionStatus.Accepted, sessionPresent )); if (sendPendingMessages) { await SendPendingMessagesAsync(session, channel); await SendPendingAcknowledgementsAsync(session, channel); } }
public async Task ExecuteAsync(string clientId, IPacket input, IMqttChannel <IPacket> channel) { if (input.Type != MqttPacketType.PingRequest) { return; } await channel.SendAsync(new PingResponse()) .ConfigureAwait(continueOnCapturedContext: false); }
public async Task SendAsync(IPacket packet) { if (_disposed) { throw new ObjectDisposedException(GetType().FullName); } byte[] bytes = await _manager.GetBytesAsync(packet); _sender.OnNext(packet); await _innerChannel.SendAsync(bytes); }
public async Task SendAsync(IPacket packet) { if (disposed) { throw new ObjectDisposedException(GetType().FullName); } var bytes = await manager.GetBytesAsync(packet) .ConfigureAwait(continueOnCapturedContext: false); sender.OnNext(packet); await innerChannel.SendAsync(bytes) .ConfigureAwait(continueOnCapturedContext: false); }
protected async Task MonitorAckAsync <T>(IFlowPacket sentMessage, string clientId, IMqttChannel <IPacket> channel) where T : IFlowPacket { using (IDisposable intervalSubscription = Observable .Interval(TimeSpan.FromSeconds(configuration.WaitTimeoutSecs), NewThreadScheduler.Default) .Subscribe(async _ => { if (channel.IsConnected) { _tracer.Warn(ClientProperties.PublishFlow_RetryingQoSFlow(sentMessage.Type, clientId)); await channel.SendAsync(sentMessage); } })) { await channel .ReceiverStream .ObserveOn(NewThreadScheduler.Default) .OfType <T>() .FirstOrDefaultAsync(x => x.PacketId == sentMessage.PacketId); } }
public async Task ExecuteAsync(string clientId, IPacket input, IMqttChannel <IPacket> channel) { if (input.Type != MqttPacketType.Subscribe) { return; } var subscribe = input as Subscribe; var session = sessionRepository.Read(clientId); if (session == null) { throw new MqttException(string.Format(Properties.Resources.SessionRepository_ClientSessionNotFound, clientId)); } var returnCodes = new List <SubscribeReturnCode> (); foreach (var subscription in subscribe.Subscriptions) { try { if (!topicEvaluator.IsValidTopicFilter(subscription.TopicFilter)) { tracer.Error(Server.Properties.Resources.ServerSubscribeFlow_InvalidTopicSubscription, subscription.TopicFilter, clientId); returnCodes.Add(SubscribeReturnCode.Failure); continue; } var clientSubscription = session .GetSubscriptions() .FirstOrDefault(s => s.TopicFilter == subscription.TopicFilter); if (clientSubscription != null) { clientSubscription.MaximumQualityOfService = subscription.MaximumQualityOfService; } else { Console.WriteLine("Client just connected: " + clientId + " " + subscription.TopicFilter); clientSubscription = new ClientSubscription { ClientId = clientId, TopicFilter = subscription.TopicFilter, MaximumQualityOfService = subscription.MaximumQualityOfService }; session.AddSubscription(clientSubscription); } await SendRetainedMessagesAsync(clientSubscription, channel) .ConfigureAwait(continueOnCapturedContext: false); var supportedQos = configuration.GetSupportedQos(subscription.MaximumQualityOfService); var returnCode = supportedQos.ToReturnCode(); returnCodes.Add(returnCode); } catch (RepositoryException repoEx) { tracer.Error(repoEx, Server.Properties.Resources.ServerSubscribeFlow_ErrorOnSubscription, clientId, subscription.TopicFilter); returnCodes.Add(SubscribeReturnCode.Failure); } } sessionRepository.Update(session); await channel.SendAsync(new SubscribeAck (subscribe.PacketId, returnCodes.ToArray())) .ConfigureAwait(continueOnCapturedContext: false); }
public async Task ExecuteAsync(string clientId, IPacket input, IMqttChannel <IPacket> channel) { if (input.Type != MqttPacketType.Subscribe) { return; } Subscribe subscribe = input as Subscribe; ClientSession session = _sessionRepository.Read(clientId); if (session == null) { throw new MqttException(ServerProperties.SessionRepository_ClientSessionNotFound(clientId)); } List <SubscribeReturnCode> returnCodes = new List <SubscribeReturnCode>(); foreach (Subscription subscription in subscribe.Subscriptions) { try { if (!_topicEvaluator.IsValidTopicFilter(subscription.TopicFilter)) { _tracer.Error(ServerProperties.ServerSubscribeFlow_InvalidTopicSubscription(subscription.TopicFilter, clientId)); returnCodes.Add(SubscribeReturnCode.Failure); continue; } ClientSubscription clientSubscription = session .GetSubscriptions() .FirstOrDefault(s => s.TopicFilter == subscription.TopicFilter); if (clientSubscription != null) { clientSubscription.MaximumQualityOfService = subscription.MaximumQualityOfService; } else { clientSubscription = new ClientSubscription { ClientId = clientId, TopicFilter = subscription.TopicFilter, MaximumQualityOfService = subscription.MaximumQualityOfService }; session.AddSubscription(clientSubscription); } await SendRetainedMessagesAsync(clientSubscription, channel); MqttQualityOfService supportedQos = _configuration.GetSupportedQos(subscription.MaximumQualityOfService); SubscribeReturnCode returnCode = supportedQos.ToReturnCode(); returnCodes.Add(returnCode); } catch (RepositoryException repoEx) { _tracer.Error(repoEx, ServerProperties.ServerSubscribeFlow_ErrorOnSubscription(clientId, subscription.TopicFilter)); returnCodes.Add(SubscribeReturnCode.Failure); } } _sessionRepository.Update(session); await channel.SendAsync(new SubscribeAck( subscribe.PacketId, returnCodes.ToArray())); }