public async Task SendPacketAsync(MqttBasePacket packet, TimeSpan timeout, CancellationToken cancellationToken) { await _writerSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false); try { var packetData = PacketFormatterAdapter.Encode(packet); if (timeout == TimeSpan.Zero) { await _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, cancellationToken).ConfigureAwait(false); } else { await MqttTaskTimeout.WaitAsync( t => _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, t), timeout, cancellationToken).ConfigureAwait(false); } Interlocked.Add(ref _bytesReceived, packetData.Count); _logger.Verbose("TX ({0} bytes) >>> {1}", packetData.Count, packet); } catch (Exception exception) { if (IsWrappedException(exception)) { throw; } WrapException(exception); } finally { PacketFormatterAdapter.FreeBuffer(); _writerSemaphore?.Release(); } }
private static byte EncodePacket(MqttBasePacket packet, IMqttPacketWriter packetWriter) { switch (packet) { case MqttConnectPacket connectPacket: return(EncodeConnectPacket(connectPacket, packetWriter)); case MqttConnAckPacket connAckPacket: return(EncodeConnAckPacket(connAckPacket, packetWriter)); case MqttDisconnectPacket disconnectPacket: return(EncodeDisconnectPacket(disconnectPacket, packetWriter)); case MqttPingReqPacket _: return(EncodePingReqPacket()); case MqttPingRespPacket _: return(EncodePingRespPacket()); case MqttPublishPacket publishPacket: return(EncodePublishPacket(publishPacket, packetWriter)); case MqttPubAckPacket pubAckPacket: return(EncodePubAckPacket(pubAckPacket, packetWriter)); case MqttPubRecPacket pubRecPacket: return(EncodePubRecPacket(pubRecPacket, packetWriter)); case MqttPubRelPacket pubRelPacket: return(EncodePubRelPacket(pubRelPacket, packetWriter)); case MqttPubCompPacket pubCompPacket: return(EncodePubCompPacket(pubCompPacket, packetWriter)); case MqttSubscribePacket subscribePacket: return(EncodeSubscribePacket(subscribePacket, packetWriter)); case MqttSubAckPacket subAckPacket: return(EncodeSubAckPacket(subAckPacket, packetWriter)); case MqttUnsubscribePacket unsubscribePacket: return(EncodeUnsubscribePacket(unsubscribePacket, packetWriter)); case MqttUnsubAckPacket unsubAckPacket: return(EncodeUnsubAckPacket(unsubAckPacket, packetWriter)); case MqttAuthPacket authPacket: return(EncodeAuthPacket(authPacket, packetWriter)); default: throw new MqttProtocolViolationException("Packet type invalid."); } }
private static void DeserializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) { var serializer = new MqttPacketSerializer { ProtocolVersion = protocolVersion }; var buffer1 = serializer.Serialize(packet); using (var headerStream = new MemoryStream(Join(buffer1))) { var channel = new TestMqttChannel(headerStream); var fixedHeader = new byte[2]; var singleByteBuffer = new byte[1]; var header = MqttPacketReader.ReadFixedHeaderAsync(channel, fixedHeader, singleByteBuffer, CancellationToken.None).GetAwaiter().GetResult(); using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, header.RemainingLength)) { var deserializedPacket = serializer.Deserialize(new ReceivedMqttPacket(header.Flags, new MqttPacketBodyReader(bodyStream.ToArray(), 0, (int)bodyStream.Length))); var buffer2 = serializer.Serialize(deserializedPacket); Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(Join(buffer2))); } } }
public async Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); ThrowIfDisposed(); using (await _syncRoot.WaitAsync(cancellationToken).ConfigureAwait(false)) { // Check for cancellation here again because "WaitAsync" might take some time. cancellationToken.ThrowIfCancellationRequested(); try { var packetData = PacketFormatterAdapter.Encode(packet); _packetInspectorHandler.BeginSendPacket(packetData); await _channel.WriteAsync(packetData.Array, packetData.Offset, packetData.Count, cancellationToken).ConfigureAwait(false); Interlocked.Add(ref _bytesReceived, packetData.Count); _logger.Verbose("TX ({0} bytes) >>> {1}", packetData.Count, packet); } catch (Exception exception) { if (IsWrappedException(exception)) { throw; } WrapAndThrowException(exception); } finally { PacketFormatterAdapter.FreeBuffer(); } } }
private void DeserializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) { var writer = WriterFactory(); var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, writer); var buffer1 = serializer.Encode(packet); using (var headerStream = new MemoryStream(Join(buffer1))) { var channel = new TestMqttChannel(headerStream); var fixedHeader = new byte[2]; var header = new MqttPacketReader(channel).ReadFixedHeaderAsync(fixedHeader, CancellationToken.None).GetAwaiter().GetResult().FixedHeader; using (var bodyStream = new MemoryStream(Join(buffer1), (int)headerStream.Position, header.RemainingLength)) { var reader = ReaderFactory(bodyStream.ToArray()); var deserializedPacket = serializer.Decode(new ReceivedMqttPacket(header.Flags, reader, 0)); var buffer2 = serializer.Encode(deserializedPacket); Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(Join(buffer2))); } } }
private Task SendAsync(MqttBasePacket packet) { return(_adapter.SendPacketAsync(packet, _options.DefaultCommunicationTimeout)); }
private void StartProcessReceivedPacket(MqttBasePacket packet, CancellationToken cancellationToken) { #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Task.Run(async() => await ProcessReceivedPacketAsync(packet), cancellationToken).ConfigureAwait(false); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed }
async Task TryProcessReceivedPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken) { try { _receiveTracker.Restart(); if (packet is MqttPublishPacket publishPacket) { EnqueueReceivedPublishPacket(publishPacket); } else if (packet is MqttPubRelPacket pubRelPacket) { await SendAsync(new MqttPubCompPacket { PacketIdentifier = pubRelPacket.PacketIdentifier, ReasonCode = MqttPubCompReasonCode.Success }, cancellationToken).ConfigureAwait(false); } else if (packet is MqttPingReqPacket) { await SendAsync(new MqttPingRespPacket(), cancellationToken).ConfigureAwait(false); } else if (packet is MqttDisconnectPacket) { // Also dispatch disconnect to waiting threads to generate a proper exception. _packetDispatcher.Dispatch(packet); await DisconnectAsync(null, cancellationToken).ConfigureAwait(false); } else if (packet is MqttAuthPacket authPacket) { var extendedAuthenticationExchangeHandler = Options.ExtendedAuthenticationExchangeHandler; if (extendedAuthenticationExchangeHandler != null) { await extendedAuthenticationExchangeHandler.HandleRequestAsync(new MqttExtendedAuthenticationExchangeContext(authPacket, this)).ConfigureAwait(false); } } else { _packetDispatcher.Dispatch(packet); } } catch (Exception exception) { if (_cleanDisconnectInitiated) { return; } if (exception is OperationCanceledException) { } else if (exception is MqttCommunicationException) { _logger.Warning(exception, "Communication error while receiving packets."); } else { _logger.Error(exception, "Error while receiving packets."); } _packetDispatcher.Dispatch(exception); if (!DisconnectIsPending()) { await DisconnectInternalAsync(_packetReceiverTask, exception, null).ConfigureAwait(false); } } }
private async Task TrySendNextQueuedPacketAsync(IMqttChannelAdapter adapter, CancellationToken cancellationToken) { MqttBasePacket packet = null; try { lock (_queue) { if (_queue.Count > 0) { packet = _queue.Dequeue(); } } if (packet == null) { await _queueAutoResetEvent.WaitOneAsync(cancellationToken).ConfigureAwait(false); return; } if (cancellationToken.IsCancellationRequested) { return; } adapter.SendPacketAsync(packet, cancellationToken).GetAwaiter().GetResult(); _logger.Verbose("Enqueued packet sent (ClientId: {0}).", _clientSession.ClientId); } catch (Exception exception) { if (exception is MqttCommunicationTimedOutException) { _logger.Warning(exception, "Sending publish packet failed: Timeout (ClientId: {0}).", _clientSession.ClientId); } else if (exception is MqttCommunicationException) { _logger.Warning(exception, "Sending publish packet failed: Communication exception (ClientId: {0}).", _clientSession.ClientId); } else if (exception is OperationCanceledException) { } else { _logger.Error(exception, "Sending publish packet failed (ClientId: {0}).", _clientSession.ClientId); } if (packet is MqttPublishPacket publishPacket) { if (publishPacket.QualityOfServiceLevel > MqttQualityOfServiceLevel.AtMostOnce) { publishPacket.Dup = true; Enqueue(publishPacket); } } if (!cancellationToken.IsCancellationRequested) { _clientSession.Stop(MqttClientDisconnectType.NotClean); } } }
public Task SerializeAsync(MqttBasePacket packet, IMqttCommunicationChannel destination) { if (packet == null) { throw new ArgumentNullException(nameof(packet)); } if (destination == null) { throw new ArgumentNullException(nameof(destination)); } var connectPacket = packet as MqttConnectPacket; if (connectPacket != null) { return(SerializeAsync(connectPacket, destination)); } var connAckPacket = packet as MqttConnAckPacket; if (connAckPacket != null) { return(SerializeAsync(connAckPacket, destination)); } var disconnectPacket = packet as MqttDisconnectPacket; if (disconnectPacket != null) { return(SerializeAsync(disconnectPacket, destination)); } var pingReqPacket = packet as MqttPingReqPacket; if (pingReqPacket != null) { return(SerializeAsync(pingReqPacket, destination)); } var pingRespPacket = packet as MqttPingRespPacket; if (pingRespPacket != null) { return(SerializeAsync(pingRespPacket, destination)); } var publishPacket = packet as MqttPublishPacket; if (publishPacket != null) { return(SerializeAsync(publishPacket, destination)); } var pubAckPacket = packet as MqttPubAckPacket; if (pubAckPacket != null) { return(SerializeAsync(pubAckPacket, destination)); } var pubRecPacket = packet as MqttPubRecPacket; if (pubRecPacket != null) { return(SerializeAsync(pubRecPacket, destination)); } var pubRelPacket = packet as MqttPubRelPacket; if (pubRelPacket != null) { return(SerializeAsync(pubRelPacket, destination)); } var pubCompPacket = packet as MqttPubCompPacket; if (pubCompPacket != null) { return(SerializeAsync(pubCompPacket, destination)); } var subscribePacket = packet as MqttSubscribePacket; if (subscribePacket != null) { return(SerializeAsync(subscribePacket, destination)); } var subAckPacket = packet as MqttSubAckPacket; if (subAckPacket != null) { return(SerializeAsync(subAckPacket, destination)); } var unsubscribePacket = packet as MqttUnsubscribePacket; if (unsubscribePacket != null) { return(SerializeAsync(unsubscribePacket, destination)); } var unsubAckPacket = packet as MqttUnsubAckPacket; if (unsubAckPacket != null) { return(SerializeAsync(unsubAckPacket, destination)); } throw new MqttProtocolViolationException("Packet type invalid."); }
private void StartProcessReceivedPacket(MqttBasePacket packet) { Task.Run(() => ProcessReceivedPacketAsync(packet), _cancellationTokenSource.Token); }
private byte[] Serialize(MqttBasePacket packet, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) { var serializer = MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, WriterFactory()); return(Join(serializer.Encode(packet))); }
private void SerializeAndCompare(MqttBasePacket packet, string expectedBase64Value, MqttProtocolVersion protocolVersion = MqttProtocolVersion.V311) { Assert.AreEqual(expectedBase64Value, Convert.ToBase64String(Serialize(packet, protocolVersion))); }
byte[] Serialize(MqttBasePacket packet, MqttProtocolVersion protocolVersion) { return(MqttPacketFormatterAdapter.GetMqttPacketFormatter(protocolVersion, WriterFactory()).Encode(packet).ToArray()); }
private Task SendAsync(MqttBasePacket packet) { return(_adapter.SendPacketsAsync(_options.CommunicationTimeout, _cancellationTokenSource.Token, packet)); }
public void AssertIsConnectPacket(MqttBasePacket packet) { Assert.AreEqual(packet.GetType(), typeof(MqttConnectPacket)); }
Task SendPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken) { return(_channelAdapter.SendPacketAsync(packet, cancellationToken).ContinueWith(task => { Statistics.HandleSentPacket(packet); }, cancellationToken)); }
private byte SerializePacket(MqttBasePacket packet, MqttPacketWriter writer) { if (packet is MqttConnectPacket connectPacket) { return(Serialize(connectPacket, writer)); } if (packet is MqttConnAckPacket connAckPacket) { return(Serialize(connAckPacket, writer)); } if (packet is MqttDisconnectPacket disconnectPacket) { return(Serialize(disconnectPacket, writer)); } if (packet is MqttPingReqPacket pingReqPacket) { return(Serialize(pingReqPacket, writer)); } if (packet is MqttPingRespPacket pingRespPacket) { return(Serialize(pingRespPacket, writer)); } if (packet is MqttPublishPacket publishPacket) { return(Serialize(publishPacket, writer)); } if (packet is MqttPubAckPacket pubAckPacket) { return(Serialize(pubAckPacket, writer)); } if (packet is MqttPubRecPacket pubRecPacket) { return(Serialize(pubRecPacket, writer)); } if (packet is MqttPubRelPacket pubRelPacket) { return(Serialize(pubRelPacket, writer)); } if (packet is MqttPubCompPacket pubCompPacket) { return(Serialize(pubCompPacket, writer)); } if (packet is MqttSubscribePacket subscribePacket) { return(Serialize(subscribePacket, writer)); } if (packet is MqttSubAckPacket subAckPacket) { return(Serialize(subAckPacket, writer)); } if (packet is MqttUnsubscribePacket unsubscribePacket) { return(Serialize(unsubscribePacket, writer)); } if (packet is MqttUnsubAckPacket unsubAckPacket) { return(Serialize(unsubAckPacket, writer)); } throw new MqttProtocolViolationException("Packet type invalid."); }
async Task TryProcessReceivedPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken) { try { _receiveTracker.Restart(); if (packet is MqttPublishPacket publishPacket) { EnqueueReceivedPublishPacket(publishPacket); } else if (packet is MqttPubRecPacket pubRecPacket) { await ProcessReceivedPubRecPacket(pubRecPacket, cancellationToken).ConfigureAwait(false); } else if (packet is MqttPubRelPacket pubRelPacket) { await ProcessReceivedPubRelPacket(pubRelPacket, cancellationToken).ConfigureAwait(false); } else if (packet is MqttPingReqPacket) { await SendAsync(MqttPingRespPacket.Instance, cancellationToken).ConfigureAwait(false); } else if (packet is MqttDisconnectPacket disconnectPacket) { await ProcessReceivedDisconnectPacket(disconnectPacket).ConfigureAwait(false); } else if (packet is MqttAuthPacket authPacket) { await ProcessReceivedAuthPacket(authPacket).ConfigureAwait(false); } else { _packetDispatcher.Dispatch(packet); } } catch (Exception exception) { if (_cleanDisconnectInitiated) { return; } if (exception is OperationCanceledException) { } else if (exception is MqttCommunicationException) { _logger.Warning(exception, "Communication error while receiving packets."); } else { _logger.Error(exception, "Error while receiving packets."); } _packetDispatcher.Dispatch(exception); if (!DisconnectIsPending()) { await DisconnectInternalAsync(_packetReceiverTask, exception, null).ConfigureAwait(false); } } }
async Task TryProcessReceivedPacketAsync(MqttBasePacket packet, CancellationToken cancellationToken) { try { if (packet is MqttPublishPacket publishPacket) { EnqueueReceivedPublishPacket(publishPacket); } else if (packet is MqttPubRecPacket pubRecPacket) { await ProcessReceivedPubRecPacket(pubRecPacket, cancellationToken).ConfigureAwait(false); } else if (packet is MqttPubRelPacket pubRelPacket) { await ProcessReceivedPubRelPacket(pubRelPacket, cancellationToken).ConfigureAwait(false); } else if (packet is MqttDisconnectPacket disconnectPacket) { await ProcessReceivedDisconnectPacket(disconnectPacket).ConfigureAwait(false); } else if (packet is MqttAuthPacket authPacket) { await ProcessReceivedAuthPacket(authPacket).ConfigureAwait(false); } else if (packet is MqttPingRespPacket) { _packetDispatcher.TryDispatch(packet); } else if (packet is MqttPingReqPacket) { throw new MqttProtocolViolationException("The PINGREQ Packet is sent from a Client to the Server only."); } else { if (!_packetDispatcher.TryDispatch(packet)) { throw new MqttProtocolViolationException($"Received packet '{packet}' at an unexpected time."); } } } catch (Exception exception) { if (_cleanDisconnectInitiated) { return; } if (exception is OperationCanceledException) { } else if (exception is MqttCommunicationException) { _logger.Warning(exception, "Communication error while receiving packets."); } else { _logger.Error(exception, "Error while receiving packets."); } _packetDispatcher.FailAll(exception); await DisconnectInternalAsync(_packetReceiverTask, exception, null).ConfigureAwait(false); } }
private void ProcessReceivedPacket(IMqttChannelAdapter adapter, MqttBasePacket packet, CancellationToken cancellationToken) { if (packet is MqttPublishPacket publishPacket) { HandleIncomingPublishPacket(adapter, publishPacket, cancellationToken); return; } if (packet is MqttPingReqPacket) { adapter.SendPacketAsync(new MqttPingRespPacket(), cancellationToken).GetAwaiter().GetResult(); return; } if (packet is MqttPubRelPacket pubRelPacket) { var responsePacket = new MqttPubCompPacket { PacketIdentifier = pubRelPacket.PacketIdentifier }; adapter.SendPacketAsync(responsePacket, cancellationToken).GetAwaiter().GetResult(); return; } if (packet is MqttPubRecPacket pubRecPacket) { var responsePacket = new MqttPubRelPacket { PacketIdentifier = pubRecPacket.PacketIdentifier }; adapter.SendPacketAsync(responsePacket, cancellationToken).GetAwaiter().GetResult(); return; } if (packet is MqttPubAckPacket || packet is MqttPubCompPacket) { return; } if (packet is MqttSubscribePacket subscribePacket) { HandleIncomingSubscribePacket(adapter, subscribePacket, cancellationToken); return; } if (packet is MqttUnsubscribePacket unsubscribePacket) { HandleIncomingUnsubscribePacket(adapter, unsubscribePacket, cancellationToken); return; } if (packet is MqttDisconnectPacket) { Stop(MqttClientDisconnectType.Clean, true); return; } if (packet is MqttConnectPacket) { Stop(MqttClientDisconnectType.NotClean, true); return; } _logger.Warning(null, "Client '{0}': Received not supported packet ({1}). Closing connection.", ClientId, packet); Stop(MqttClientDisconnectType.NotClean, true); }
private async Task ProcessReceivedPacketAsync(IMqttCommunicationAdapter adapter, MqttBasePacket packet) { if (packet is MqttSubscribePacket subscribePacket) { await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, _subscriptionsManager.Subscribe(subscribePacket)); EnqueueRetainedMessages(subscribePacket); } else if (packet is MqttUnsubscribePacket unsubscribePacket) { await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, _subscriptionsManager.Unsubscribe(unsubscribePacket)); } else if (packet is MqttPublishPacket publishPacket) { await HandleIncomingPublishPacketAsync(adapter, publishPacket); } else if (packet is MqttPubRelPacket pubRelPacket) { await HandleIncomingPubRelPacketAsync(adapter, pubRelPacket); } else if (packet is MqttPubRecPacket pubRecPacket) { await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, pubRecPacket.CreateResponse <MqttPubRelPacket>()); } else if (packet is MqttPubAckPacket || packet is MqttPubCompPacket) { // Discard message. } else if (packet is MqttPingReqPacket) { await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, _cancellationTokenSource.Token, new MqttPingRespPacket()); } else if (packet is MqttDisconnectPacket || packet is MqttConnectPacket) { Stop(); } else { MqttNetTrace.Warning(nameof(MqttClientSession), "Client '{0}': Received not supported packet ({1}). Closing connection.", ClientId, packet); Stop(); } }