private async Task SendPendingPublishPacketAsync(IMqttCommunicationAdapter adapter, CancellationToken cancellationToken) { var packet = _pendingPublishPackets.Take(cancellationToken); try { await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, packet).ConfigureAwait(false); } catch (Exception exception) { if (exception is MqttCommunicationTimedOutException) { MqttNetTrace.Warning(nameof(MqttClientPendingMessagesQueue), exception, "Sending publish packet failed due to timeout."); } else if (exception is MqttCommunicationException) { MqttNetTrace.Warning(nameof(MqttClientPendingMessagesQueue), exception, "Sending publish packet failed due to communication exception."); } if (exception is OperationCanceledException) { } else { MqttNetTrace.Error(nameof(MqttClientPendingMessagesQueue), exception, "Sending publish packet failed."); } if (packet.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce) { packet.Dup = true; _pendingPublishPackets.Add(packet, cancellationToken); } _session.Stop(); } }
public async Task LoadMessagesAsync() { if (_options.Storage == null) { return; } try { var retainedMessages = await _options.Storage.LoadRetainedMessagesAsync(); lock (_retainedMessages) { _retainedMessages.Clear(); foreach (var retainedMessage in retainedMessages) { _retainedMessages[retainedMessage.Topic] = retainedMessage.ToPublishPacket(); } } } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttClientRetainedMessagesManager), exception, "Unhandled exception while loading retained messages."); } }
public async Task RunAsync(MqttApplicationMessage willMessage, IMqttCommunicationAdapter adapter) { if (adapter == null) { throw new ArgumentNullException(nameof(adapter)); } _willMessage = willMessage; try { _adapter = adapter; _cancellationTokenSource = new CancellationTokenSource(); _pendingMessagesQueue.Start(adapter, _cancellationTokenSource.Token); await ReceivePacketsAsync(adapter, _cancellationTokenSource.Token); } catch (OperationCanceledException) { } catch (MqttCommunicationException exception) { MqttNetTrace.Warning(nameof(MqttClientSession), exception, "Client '{0}': Communication exception while processing client packets.", ClientId); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttClientSession), exception, "Client '{0}': Unhandled exception while processing client packets.", ClientId); } }
private void FireApplicationMessageReceivedEvent(MqttPublishPacket publishPacket) { try { var applicationMessage = publishPacket.ToApplicationMessage(); ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(applicationMessage)); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttClient), exception, "Unhandled exception while handling application message."); } }
private void AcceptDefaultEndpointConnectionsAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) { try { var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(args.Socket), new MqttPacketSerializer()); ClientAccepted?.Invoke(clientAdapter); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttServerAdapter), exception, "Error while accepting connection at default endpoint."); } }
private async Task SendPendingPublishPacketsAsync(IMqttCommunicationAdapter adapter, CancellationToken cancellationToken) { try { while (!cancellationToken.IsCancellationRequested) { await SendPendingPublishPacketAsync(adapter, cancellationToken); } } catch (OperationCanceledException) { } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttClientPendingMessagesQueue), exception, "Unhandled exception while sending pending publish packets."); } }
private async Task ReceivePackets(CancellationToken cancellationToken) { MqttNetTrace.Information(nameof(MqttClient), "Start receiving packets."); try { while (!cancellationToken.IsCancellationRequested) { _isReceivingPackets = true; var packet = await _adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) { return; } StartProcessReceivedPacket(packet, cancellationToken); } } catch (OperationCanceledException) { } catch (MqttCommunicationException exception) { if (cancellationToken.IsCancellationRequested) { return; } MqttNetTrace.Warning(nameof(MqttClient), exception, "MQTT communication exception while receiving packets."); await DisconnectInternalAsync().ConfigureAwait(false); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttClient), exception, "Unhandled exception while receiving packets."); await DisconnectInternalAsync().ConfigureAwait(false); } finally { MqttNetTrace.Information(nameof(MqttClient), "Stopped receiving packets."); } }
public void DispatchPublishPacket(MqttClientSession senderClientSession, MqttPublishPacket publishPacket) { try { var eventArgs = new MqttApplicationMessageReceivedEventArgs(senderClientSession?.ClientId, publishPacket.ToApplicationMessage()); ApplicationMessageReceived?.Invoke(this, eventArgs); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttClientSessionsManager), exception, "Error while processing application message"); } lock (_clientSessions) { foreach (var clientSession in _clientSessions.Values.ToList()) { clientSession.EnqueuePublishPacket(publishPacket); } } }
private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { var clientSocket = await _defaultEndpointSocket.AcceptAsync().ConfigureAwait(false); var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket, null), new MqttPacketSerializer()); ClientAccepted?.Invoke(clientAdapter); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttServerAdapter), exception, "Error while accepting connection at default endpoint."); //excessive CPU consumed if in endless loop of socket errors await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false); } } }
private async Task ProcessReceivedPacketAsync(MqttBasePacket packet) { try { MqttNetTrace.Information(nameof(MqttClient), "Received <<< {0}", packet); if (packet is MqttPingReqPacket) { await SendAsync(new MqttPingRespPacket()); return; } if (packet is MqttDisconnectPacket) { await DisconnectAsync(); return; } if (packet is MqttPublishPacket publishPacket) { await ProcessReceivedPublishPacket(publishPacket); return; } if (packet is MqttPubRelPacket pubRelPacket) { await ProcessReceivedPubRelPacket(pubRelPacket); return; } _packetDispatcher.Dispatch(packet); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttClient), exception, "Unhandled exception while processing received packet."); } }
public async Task HandleMessageAsync(string clientId, MqttPublishPacket publishPacket) { if (publishPacket == null) { throw new ArgumentNullException(nameof(publishPacket)); } List <MqttPublishPacket> allRetainedMessages; lock (_retainedMessages) { if (publishPacket.Payload?.Any() == false) { _retainedMessages.Remove(publishPacket.Topic); MqttNetTrace.Information(nameof(MqttClientRetainedMessagesManager), "Client '{0}' cleared retained message for topic '{1}'.", clientId, publishPacket.Topic); } else { _retainedMessages[publishPacket.Topic] = publishPacket; MqttNetTrace.Information(nameof(MqttClientRetainedMessagesManager), "Client '{0}' updated retained message for topic '{1}'.", clientId, publishPacket.Topic); } allRetainedMessages = new List <MqttPublishPacket>(_retainedMessages.Values); } try { // ReSharper disable once UseNullPropagation if (_options.Storage != null) { await _options.Storage.SaveRetainedMessagesAsync(allRetainedMessages.Select(p => p.ToApplicationMessage()).ToList()); } } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttClientRetainedMessagesManager), exception, "Unhandled exception while saving retained messages."); } }
private async Task AcceptTlsEndpointConnectionsAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { var clientSocket = await _tlsEndpointSocket.AcceptAsync().ConfigureAwait(false); var sslStream = new SslStream(new NetworkStream(clientSocket)); await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false).ConfigureAwait(false); var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket, sslStream), new MqttPacketSerializer()); ClientAccepted?.Invoke(clientAdapter); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttServerAdapter), exception, "Error while accepting connection at TLS endpoint."); //excessive CPU consumed if in endless loop of socket errors await Task.Delay(TimeSpan.FromSeconds(1), cancellationToken).ConfigureAwait(false); } } }
private async Task ReceivePacketsAsync(IMqttCommunicationAdapter adapter, CancellationToken cancellationToken) { try { while (!cancellationToken.IsCancellationRequested) { var packet = await adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(false); await ProcessReceivedPacketAsync(adapter, packet).ConfigureAwait(false); } } catch (OperationCanceledException) { } catch (MqttCommunicationException exception) { MqttNetTrace.Warning(nameof(MqttClientSession), exception, "Client '{0}': Communication exception while processing client packets.", ClientId); Stop(); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttClientSession), exception, "Client '{0}': Unhandled exception while processing client packets.", ClientId); Stop(); } }
public async Task RunClientSessionAsync(IMqttCommunicationAdapter clientAdapter) { var clientId = string.Empty; try { if (!(await clientAdapter.ReceivePacketAsync(_options.DefaultCommunicationTimeout, CancellationToken.None).ConfigureAwait(false) is MqttConnectPacket connectPacket)) { throw new MqttProtocolViolationException("The first packet from a client must be a 'CONNECT' packet [MQTT-3.1.0-1]."); } clientId = connectPacket.ClientId; // Switch to the required protocol version before sending any response. clientAdapter.PacketSerializer.ProtocolVersion = connectPacket.ProtocolVersion; var connectReturnCode = ValidateConnection(connectPacket); if (connectReturnCode != MqttConnectReturnCode.ConnectionAccepted) { await clientAdapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, CancellationToken.None, new MqttConnAckPacket { ConnectReturnCode = connectReturnCode }).ConfigureAwait(false); return; } var clientSession = GetOrCreateClientSession(connectPacket); await clientAdapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, CancellationToken.None, new MqttConnAckPacket { ConnectReturnCode = connectReturnCode, IsSessionPresent = clientSession.IsExistingSession }).ConfigureAwait(false); ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(new ConnectedMqttClient { ClientId = clientId, ProtocolVersion = clientAdapter.PacketSerializer.ProtocolVersion })); await clientSession.Session.RunAsync(connectPacket.WillMessage, clientAdapter).ConfigureAwait(false); } catch (Exception exception) { MqttNetTrace.Error(nameof(MqttServer), exception, exception.Message); } finally { try { await clientAdapter.DisconnectAsync(_options.DefaultCommunicationTimeout).ConfigureAwait(false); } catch (Exception) { //ignored } ClientDisconnected?.Invoke(this, new MqttClientDisconnectedEventArgs(new ConnectedMqttClient { ClientId = clientId, ProtocolVersion = clientAdapter.PacketSerializer.ProtocolVersion })); } }