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); } }
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 HandleIncomingPacketAsync(MqttBasePacket packet) { var subscribePacket = packet as MqttSubscribePacket; if (subscribePacket != null) { return(_adapter.SendPacketAsync(_subscriptionsManager.Subscribe(subscribePacket), _options.DefaultCommunicationTimeout)); } var unsubscribePacket = packet as MqttUnsubscribePacket; if (unsubscribePacket != null) { return(_adapter.SendPacketAsync(_subscriptionsManager.Unsubscribe(unsubscribePacket), _options.DefaultCommunicationTimeout)); } var publishPacket = packet as MqttPublishPacket; if (publishPacket != null) { return(HandleIncomingPublishPacketAsync(publishPacket)); } var pubRelPacket = packet as MqttPubRelPacket; if (pubRelPacket != null) { return(HandleIncomingPubRelPacketAsync(pubRelPacket)); } var pubAckPacket = packet as MqttPubAckPacket; if (pubAckPacket != null) { return(HandleIncomingPubAckPacketAsync(pubAckPacket)); } if (packet is MqttPingReqPacket) { return(_adapter.SendPacketAsync(new MqttPingRespPacket(), _options.DefaultCommunicationTimeout)); } if (packet is MqttDisconnectPacket || packet is MqttConnectPacket) { _cancellationTokenSource.Cancel(); return(Task.FromResult((object)null)); } MqttTrace.Warning(nameof(MqttClientSession), $"Client '{_identifier}': Received not supported packet ({packet}). Closing connection."); _cancellationTokenSource.Cancel(); return(Task.FromResult((object)null)); }
private Task HandleIncomingPacketAsync(MqttBasePacket packet) { if (packet is MqttSubscribePacket subscribePacket) { return(Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, _subscriptionsManager.Subscribe(subscribePacket))); } if (packet is MqttUnsubscribePacket unsubscribePacket) { return(Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, _subscriptionsManager.Unsubscribe(unsubscribePacket))); } if (packet is MqttPublishPacket publishPacket) { return(HandleIncomingPublishPacketAsync(publishPacket)); } if (packet is MqttPubRelPacket pubRelPacket) { return(HandleIncomingPubRelPacketAsync(pubRelPacket)); } if (packet is MqttPubRecPacket pubRecPacket) { return(Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, pubRecPacket.CreateResponse <MqttPubRelPacket>())); } if (packet is MqttPubAckPacket || packet is MqttPubCompPacket) { // Discard message. return(Task.FromResult((object)null)); } if (packet is MqttPingReqPacket) { return(Adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPingRespPacket())); } if (packet is MqttDisconnectPacket || packet is MqttConnectPacket) { _cancellationTokenSource.Cancel(); return(Task.FromResult((object)null)); } MqttTrace.Warning(nameof(MqttClientSession), "Client '{0}': Received not supported packet ({1}). Closing connection.", _identifier, packet); _cancellationTokenSource.Cancel(); return(Task.FromResult((object)null)); }
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 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); } } } }
public async Task <MqttBasePacket> WaitForPacketAsync(Func <MqttBasePacket, bool> selector, TimeSpan timeout) { if (selector == null) { throw new ArgumentNullException(nameof(selector)); } var packetAwaiter = AddPacketAwaiter(selector); DispatchPendingPackets(); var hasTimeout = await Task.WhenAny(Task.Delay(timeout), packetAwaiter.Task) != packetAwaiter.Task; RemovePacketAwaiter(packetAwaiter); if (hasTimeout) { MqttTrace.Warning(nameof(MqttPacketDispatcher), "Timeout while waiting for packet."); throw new MqttCommunicationTimedOutException(); } return(packetAwaiter.Task.Result); }
public async Task <MqttBasePacket> WaitForPacketAsync(MqttBasePacket request, Type responseType, TimeSpan timeout) { if (request == null) { throw new ArgumentNullException(nameof(request)); } var packetAwaiter = AddPacketAwaiter(request, responseType); try { return(await packetAwaiter.Task.TimeoutAfter(timeout)); } catch (MqttCommunicationTimedOutException) { MqttTrace.Warning(nameof(MqttPacketDispatcher), "Timeout while waiting for packet of type '{0}'.", responseType.Name); throw; } finally { RemovePacketAwaiter(request, responseType); } }