private void OnClientConnected(object sender, MqttClientConnectedEventArgs eventArgs) { MqttTrace.Information(nameof(MqttServer), $"Client '{eventArgs.Identifier}': Connected."); ClientConnected?.Invoke(this, eventArgs); Task.Run(() => _clientSessionsManager.RunClientSessionAsync(eventArgs), _cancellationTokenSource.Token); }
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 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 SendKeepAliveMessagesAsync(CancellationToken cancellationToken) { MqttTrace.Information(nameof(MqttClient), "Start sending keep alive packets."); try { while (!cancellationToken.IsCancellationRequested) { await Task.Delay(_options.KeepAlivePeriod, cancellationToken); await SendAndReceiveAsync <MqttPingRespPacket>(new MqttPingReqPacket()); } } catch (MqttCommunicationException exception) { MqttTrace.Warning(nameof(MqttClient), exception, "MQTT communication error while receiving packets."); } catch (Exception exception) { MqttTrace.Warning(nameof(MqttClient), exception, "Error while sending/receiving keep alive packets."); } finally { MqttTrace.Information(nameof(MqttClient), "Stopped sending keep alive packets."); await DisconnectInternalAsync(); } }
private async Task DisconnectInternalAsync() { var cts = _cancellationTokenSource; if (cts == null || cts.IsCancellationRequested) { return; } cts.Cancel(false); cts.Dispose(); _cancellationTokenSource = null; try { await _adapter.DisconnectAsync(_options.DefaultCommunicationTimeout).ConfigureAwait(false); MqttTrace.Information(nameof(MqttClient), "Disconnected from adapter."); } catch (Exception exception) { MqttTrace.Warning(nameof(MqttClient), exception, "Error while disconnecting from adapter."); } finally { Disconnected?.Invoke(this, EventArgs.Empty); } }
public async Task <MqttBasePacket> ReceivePacketAsync(TimeSpan timeout) { MqttBasePacket packet; if (timeout > TimeSpan.Zero) { var workerTask = _serializer.DeserializeAsync(_channel); var timeoutTask = Task.Delay(timeout); var hasTimeout = Task.WhenAny(timeoutTask, workerTask) == timeoutTask; if (hasTimeout) { throw new MqttCommunicationTimedOutException(); } packet = workerTask.Result; } else { packet = await _serializer.DeserializeAsync(_channel); } if (packet == null) { throw new MqttProtocolViolationException("Received malformed packet."); } MqttTrace.Information(nameof(MqttChannelCommunicationAdapter), $"RX <<< {packet}"); return(packet); }
public void Stop() { _cancellationTokenSource?.Cancel(); _cancellationTokenSource = null; _adapter.ClientConnected -= OnClientConnected; _adapter.Stop(); _clientSessionsManager.Clear(); MqttTrace.Information(nameof(MqttServer), "Stopped."); }
public void Start() { if (_cancellationTokenSource != null) { throw new InvalidOperationException("The MQTT server is already started."); } _cancellationTokenSource = new CancellationTokenSource(); _adapter.ClientConnected += OnClientConnected; _adapter.Start(_options); MqttTrace.Information(nameof(MqttServer), "Started."); }
public void Stop() { _cancellationTokenSource?.Cancel(false); _cancellationTokenSource?.Dispose(); _cancellationTokenSource = null; foreach (var adapter in _adapters) { adapter.ClientConnected -= OnClientConnected; adapter.Stop(); } _clientSessionsManager.Clear(); MqttTrace.Information(nameof(MqttServer), "Stopped."); }
public async Task <MqttBasePacket> ReceivePacketAsync(TimeSpan timeout, CancellationToken cancellationToken) { try { ReceivedMqttPacket receivedMqttPacket; if (timeout > TimeSpan.Zero) { receivedMqttPacket = await ReceiveAsync(_channel.RawReceiveStream, cancellationToken).TimeoutAfter(timeout).ConfigureAwait(false); } else { receivedMqttPacket = await ReceiveAsync(_channel.ReceiveStream, cancellationToken).ConfigureAwait(false); } if (cancellationToken.IsCancellationRequested) { throw new TaskCanceledException(); } var packet = PacketSerializer.Deserialize(receivedMqttPacket); if (packet == null) { throw new MqttProtocolViolationException("Received malformed packet."); } MqttTrace.Information(nameof(MqttChannelCommunicationAdapter), "RX <<< {0}", packet); return(packet); } catch (TaskCanceledException) { throw; } catch (MqttCommunicationTimedOutException) { throw; } catch (MqttCommunicationException) { throw; } catch (Exception exception) { throw new MqttCommunicationException(exception); } }
public async Task SendPacketsAsync(TimeSpan timeout, CancellationToken cancellationToken, IEnumerable <MqttBasePacket> packets) { try { lock (_channel) { foreach (var packet in packets) { MqttTrace.Information(nameof(MqttChannelCommunicationAdapter), "TX >>> {0} [Timeout={1}]", packet, timeout); var writeBuffer = PacketSerializer.Serialize(packet); _sendTask = _sendTask.ContinueWith(p => _channel.SendStream.WriteAsync(writeBuffer, 0, writeBuffer.Length, cancellationToken).ConfigureAwait(false), cancellationToken); } } await _sendTask; // configure await false generates stackoverflow if (timeout > TimeSpan.Zero) { await _channel.SendStream.FlushAsync(cancellationToken).TimeoutAfter(timeout).ConfigureAwait(false); } else { await _channel.SendStream.FlushAsync(cancellationToken).ConfigureAwait(false); } } catch (TaskCanceledException) { throw; } catch (MqttCommunicationTimedOutException) { throw; } catch (MqttCommunicationException) { throw; } catch (Exception exception) { throw new MqttCommunicationException(exception); } }
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); } }
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 SendKeepAliveMessagesAsync(CancellationToken cancellationToken) { MqttTrace.Information(nameof(MqttClient), "Start sending keep alive packets."); try { while (!cancellationToken.IsCancellationRequested) { await Task.Delay(_options.KeepAlivePeriod, cancellationToken).ConfigureAwait(false); if (cancellationToken.IsCancellationRequested) { return; } await SendAndReceiveAsync <MqttPingRespPacket>(new MqttPingReqPacket()).ConfigureAwait(false); } } catch (TaskCanceledException) { } catch (MqttCommunicationException exception) { if (cancellationToken.IsCancellationRequested) { return; } MqttTrace.Warning(nameof(MqttClient), exception, "MQTT communication exception while sending/receiving keep alive packets."); await DisconnectInternalAsync().ConfigureAwait(false); } catch (Exception exception) { MqttTrace.Warning(nameof(MqttClient), exception, "Unhandled exception while sending/receiving keep alive packets."); await DisconnectInternalAsync().ConfigureAwait(false); } finally { MqttTrace.Information(nameof(MqttClient), "Stopped sending keep alive 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."); } }
public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout) { MqttTrace.Information(nameof(MqttChannelCommunicationAdapter), $"TX >>> {packet} [Timeout={timeout}]"); bool hasTimeout; try { var task = _serializer.SerializeAsync(packet, _channel); hasTimeout = await Task.WhenAny(Task.Delay(timeout), task) != task; } catch (Exception exception) { throw new MqttCommunicationException(exception); } if (hasTimeout) { throw new MqttCommunicationTimedOutException(); } }