private async Task ReceivePackets(CancellationToken cancellationToken) { MqttTrace.Information(nameof(MqttClient), "Start receiving packets."); try { while (!cancellationToken.IsCancellationRequested) { var mqttPacket = await _adapter.ReceivePacketAsync(TimeSpan.Zero); MqttTrace.Information(nameof(MqttClient), $"Received <<< {mqttPacket}"); #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Task.Run(() => ProcessReceivedPacketAsync(mqttPacket), cancellationToken); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } } catch (MqttCommunicationException exception) { MqttTrace.Warning(nameof(MqttClient), exception, "MQTT communication error while receiving packets."); } catch (Exception exception) { MqttTrace.Error(nameof(MqttClient), exception, "Error while receiving packets."); } finally { MqttTrace.Information(nameof(MqttClient), "Stopped receiving packets."); await DisconnectInternalAsync(); } }
private async Task TrySendPendingPublishPacketAsync(MqttClientPublishPacketContext publishPacketContext) { try { if (_adapter == null) { return; } publishPacketContext.PublishPacket.Dup = publishPacketContext.SendTries > 0; await _adapter.SendPacketAsync(publishPacketContext.PublishPacket, _options.DefaultCommunicationTimeout); publishPacketContext.IsSent = true; } catch (MqttCommunicationException exception) { MqttTrace.Warning(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed."); } catch (Exception exception) { MqttTrace.Error(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed."); } finally { publishPacketContext.SendTries++; } }
private Task ProcessReceivedPacketAsync(MqttBasePacket mqttPacket) { try { if (mqttPacket is MqttPingReqPacket) { return(SendAsync(new MqttPingRespPacket())); } if (mqttPacket is MqttDisconnectPacket) { return(DisconnectAsync()); } var publishPacket = mqttPacket as MqttPublishPacket; if (publishPacket != null) { return(ProcessReceivedPublishPacket(publishPacket)); } var pubRelPacket = mqttPacket as MqttPubRelPacket; if (pubRelPacket != null) { return(ProcessReceivedPubRelPacket(pubRelPacket)); } _packetDispatcher.Dispatch(mqttPacket); } catch (Exception exception) { MqttTrace.Error(nameof(MqttClient), exception, "Error while processing received packet."); } return(Task.FromResult(0)); }
private async Task ReceivePackets(CancellationToken cancellationToken) { MqttTrace.Information(nameof(MqttClient), "Start receiving packets."); try { while (!cancellationToken.IsCancellationRequested) { var mqttPacket = await _adapter.ReceivePacketAsync(TimeSpan.Zero); MqttTrace.Information(nameof(MqttClient), $"Received <<< {mqttPacket}"); Task.Run(() => ProcessReceivedPacket(mqttPacket), cancellationToken).Forget(); } } catch (MqttCommunicationException exception) { MqttTrace.Warning(nameof(MqttClient), exception, "MQTT communication error while receiving packets."); } catch (Exception exception) { MqttTrace.Error(nameof(MqttClient), exception, "Error while receiving packets."); } finally { MqttTrace.Information(nameof(MqttClient), "Stopped receiving packets."); await DisconnectInternalAsync(); } }
private void AcceptDefaultEndpointConnectionsAsync(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args) { try { var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(args.Socket), new MqttV311PacketSerializer()); ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(args.Socket.Information.RemoteAddress.ToString(), clientAdapter)); } catch (Exception exception) { MqttTrace.Error(nameof(MqttServerAdapter), exception, "Error while acceping connection at default endpoint."); } }
private void FireApplicationMessageReceivedEvent(MqttPublishPacket publishPacket) { try { var applicationMessage = publishPacket.ToApplicationMessage(); ApplicationMessageReceived?.Invoke(this, new MqttApplicationMessageReceivedEventArgs(applicationMessage)); } catch (Exception exception) { MqttTrace.Error(nameof(MqttClient), exception, "Unhandled exception while handling application message."); } }
private async Task AcceptDefaultEndpointConnectionsAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null); var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket, null), new DefaultMqttV311PacketSerializer()); ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter)); } catch (Exception exception) when(!(exception is ObjectDisposedException)) { MqttTrace.Error(nameof(MqttServerAdapter), exception, "Error while acceping connection at default endpoint."); } } }
public async Task RunAsync(string identifier, MqttApplicationMessage willApplicationMessage, IMqttCommunicationAdapter adapter) { if (adapter == null) { throw new ArgumentNullException(nameof(adapter)); } _willApplicationMessage = willApplicationMessage; try { _identifier = identifier; Adapter = adapter; _cancellationTokenSource = new CancellationTokenSource(); _messageQueue.Start(adapter); while (!_cancellationTokenSource.IsCancellationRequested) { var packet = await adapter.ReceivePacketAsync(TimeSpan.Zero, _cancellationTokenSource.Token).ConfigureAwait(false); await HandleIncomingPacketAsync(packet).ConfigureAwait(false); } } catch (MqttCommunicationException) { } catch (Exception exception) { MqttTrace.Error(nameof(MqttClientSession), exception, "Client '{0}': Unhandled exception while processing client packets.", _identifier); } finally { if (willApplicationMessage != null) { _publishPacketReceivedCallback(this, _willApplicationMessage.ToPublishPacket()); } _messageQueue.Stop(); _cancellationTokenSource.Cancel(); Adapter = null; MqttTrace.Information(nameof(MqttClientSession), "Client '{0}': Disconnected.", _identifier); } }
public async Task RunClientSessionAsync(MqttClientConnectedEventArgs eventArgs) { try { if (!(await eventArgs.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]."); } // Switch to the required protocol version before sending any response. eventArgs.ClientAdapter.PacketSerializer.ProtocolVersion = connectPacket.ProtocolVersion; var connectReturnCode = ValidateConnection(connectPacket); if (connectReturnCode != MqttConnectReturnCode.ConnectionAccepted) { await eventArgs.ClientAdapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, CancellationToken.None, new MqttConnAckPacket { ConnectReturnCode = connectReturnCode }).ConfigureAwait(false); return; } var clientSession = GetOrCreateClientSession(connectPacket); await eventArgs.ClientAdapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, CancellationToken.None, new MqttConnAckPacket { ConnectReturnCode = connectReturnCode, IsSessionPresent = clientSession.IsExistingSession }).ConfigureAwait(false); await clientSession.Session.RunAsync(eventArgs.Identifier, connectPacket.WillMessage, eventArgs.ClientAdapter).ConfigureAwait(false); } catch (Exception exception) { MqttTrace.Error(nameof(MqttServer), exception, exception.Message); } finally { await eventArgs.ClientAdapter.DisconnectAsync(_options.DefaultCommunicationTimeout).ConfigureAwait(false); } }
private async Task AcceptTlsEndpointConnectionsAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { var clientSocket = await Task.Factory.FromAsync(_defaultEndpointSocket.BeginAccept, _defaultEndpointSocket.EndAccept, null); var sslStream = new SslStream(new NetworkStream(clientSocket)); await sslStream.AuthenticateAsServerAsync(_tlsCertificate, false, SslProtocols.Tls12, false); var clientAdapter = new MqttChannelCommunicationAdapter(new MqttTcpChannel(clientSocket, sslStream), new DefaultMqttV311PacketSerializer()); ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter)); } catch (Exception exception) { MqttTrace.Error(nameof(MqttServerAdapter), exception, "Error while acceping connection at TLS endpoint."); } } }
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()); ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter)); } catch (Exception exception) { MqttTrace.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); } } }
public void DispatchPublishPacket(MqttClientSession senderClientSession, MqttPublishPacket publishPacket) { try { var eventArgs = new MqttApplicationMessageReceivedEventArgs(senderClientSession?.ClientId, publishPacket.ToApplicationMessage()); ApplicationMessageReceived?.Invoke(this, eventArgs); } catch (Exception exception) { MqttTrace.Error(nameof(MqttClientSessionsManager), exception, "Error while processing application message"); } lock (_syncRoot) { foreach (var clientSession in _clientSessions.Values.ToList()) { clientSession.EnqueuePublishPacket(publishPacket); } } }
private async Task ReceivePackets(CancellationToken cancellationToken) { MqttTrace.Information(nameof(MqttClient), "Start receiving packets."); try { while (!cancellationToken.IsCancellationRequested) { var packet = await _adapter.ReceivePacketAsync(TimeSpan.Zero, cancellationToken).ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) { return; } StartProcessReceivedPacket(packet, cancellationToken); } } catch (TaskCanceledException) { } catch (MqttCommunicationException exception) { if (cancellationToken.IsCancellationRequested) { return; } MqttTrace.Warning(nameof(MqttClient), exception, "MQTT communication exception while receiving packets."); await DisconnectInternalAsync().ConfigureAwait(false); } catch (Exception exception) { MqttTrace.Error(nameof(MqttClient), exception, "Unhandled exception while receiving packets."); await DisconnectInternalAsync().ConfigureAwait(false); } finally { MqttTrace.Information(nameof(MqttClient), "Stopped receiving packets."); } }
private async Task ProcessReceivedPacketAsync(MqttBasePacket packet) { try { MqttTrace.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) { MqttTrace.Error(nameof(MqttClient), exception, "Unhandled exception while processing received packet."); } }
private async void ProcessReceivedPacket(MqttBasePacket mqttPacket) { try { if (mqttPacket is MqttPingReqPacket) { await SendAsync(new MqttPingRespPacket()); return; } if (mqttPacket is MqttDisconnectPacket) { await DisconnectAsync(); return; } var publishPacket = mqttPacket as MqttPublishPacket; if (publishPacket != null) { await ProcessReceivedPublishPacket(publishPacket); return; } var pubRelPacket = mqttPacket as MqttPubRelPacket; if (pubRelPacket != null) { await ProcessReceivedPubRelPacket(pubRelPacket); return; } _packetDispatcher.Dispatch(mqttPacket); } catch (Exception exception) { MqttTrace.Error(nameof(MqttClient), exception, "Error while processing received packet."); } }
public async Task RunClientSessionAsync(MqttClientConnectedEventArgs eventArgs) { try { var connectPacket = await eventArgs.ClientAdapter.ReceivePacketAsync(_options.DefaultCommunicationTimeout) as MqttConnectPacket; if (connectPacket == null) { throw new MqttProtocolViolationException("The first packet from a client must be a 'CONNECT' packet [MQTT-3.1.0-1]."); } var connectReturnCode = ValidateConnection(connectPacket); if (connectReturnCode != MqttConnectReturnCode.ConnectionAccepted) { await eventArgs.ClientAdapter.SendPacketAsync(new MqttConnAckPacket { ConnectReturnCode = connectReturnCode }, _options.DefaultCommunicationTimeout); return; } var clientSession = GetOrCreateClientSession(connectPacket); await eventArgs.ClientAdapter.SendPacketAsync(new MqttConnAckPacket { ConnectReturnCode = connectReturnCode, IsSessionPresent = clientSession.IsExistingSession }, _options.DefaultCommunicationTimeout); await clientSession.Session.RunAsync(eventArgs.Identifier, connectPacket.WillMessage, eventArgs.ClientAdapter); } catch (Exception exception) { MqttTrace.Error(nameof(MqttServer), exception, exception.Message); } finally { await eventArgs.ClientAdapter.DisconnectAsync(); } }
private async Task SendPendingPublishPacketsAsync(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { try { await _gate.WaitOneAsync(); if (cancellationToken.IsCancellationRequested) { return; } if (_adapter == null) { continue; } List <MqttClientPublishPacketContext> pendingPublishPackets; lock (_pendingPublishPackets) { pendingPublishPackets = _pendingPublishPackets.ToList(); } foreach (var publishPacket in pendingPublishPackets) { await TrySendPendingPublishPacketAsync(publishPacket); } } catch (Exception e) { MqttTrace.Error(nameof(MqttClientMessageQueue), e, "Error while sending pending publish packets."); } finally { Cleanup(); } } }
private async Task SendPendingPublishPacketsAsync(CancellationToken cancellationToken, IMqttCommunicationAdapter adapter) { var consumable = _pendingPublishPackets.GetConsumingEnumerable(); while (!cancellationToken.IsCancellationRequested) { if (_pendingPublishPackets.Count == 0) { await Task.Delay(TimeSpan.FromMilliseconds(5), cancellationToken).ConfigureAwait(false); continue; } var packets = consumable.Take(_pendingPublishPackets.Count).ToList(); try { await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, packets).ConfigureAwait(false); } catch (MqttCommunicationException exception) { MqttTrace.Warning(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed."); foreach (var publishPacket in packets) { publishPacket.Dup = true; _pendingPublishPackets.Add(publishPacket, cancellationToken); } } catch (Exception exception) { MqttTrace.Error(nameof(MqttClientMessageQueue), exception, "Sending publish packet failed."); foreach (var publishPacket in packets) { publishPacket.Dup = true; _pendingPublishPackets.Add(publishPacket, cancellationToken); } } } }
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()); ClientConnected?.Invoke(this, new MqttClientConnectedEventArgs(clientSocket.RemoteEndPoint.ToString(), clientAdapter)); } catch (Exception exception) { MqttTrace.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); } } }