public void Dispatch(MqttBasePacket packet) { if (packet == null) { throw new ArgumentNullException(nameof(packet)); } ushort identifier = 0; if (packet is IMqttPacketWithIdentifier packetWithIdentifier && packetWithIdentifier.PacketIdentifier.HasValue) { identifier = packetWithIdentifier.PacketIdentifier.Value; } var type = packet.GetType(); var key = new Tuple <ushort, Type>(identifier, type); if (_awaiters.TryRemove(key, out var awaiter)) { Task.Run(() => awaiter.TrySetResult(packet)); // Task.Run fixes a dead lock. Without this the client only receives one message. return; } throw new InvalidOperationException($"Packet of type '{type.Name}' not handled or dispatched."); }
public void Dispatch(MqttBasePacket packet) { if (packet == null) { throw new ArgumentNullException(nameof(packet)); } var type = packet.GetType(); if (packet is IMqttPacketWithIdentifier withIdentifier) { if (_packetByResponseTypeAndIdentifier.TryGetValue(type, out var byid)) { if (byid.TryRemove(withIdentifier.PacketIdentifier, out var tcs)) { tcs.TrySetResult(packet); return; } } } else if (_packetByResponseType.TryRemove(type, out var tcs)) { tcs.TrySetResult(packet); return; } throw new InvalidOperationException($"Packet of type '{type.Name}' not handled or dispatched."); }
public void Dispatch(MqttBasePacket packet) { if (packet == null) { throw new ArgumentNullException(nameof(packet)); } if (packet is MqttDisconnectPacket disconnectPacket) { foreach (var packetAwaiter in _awaiters) { packetAwaiter.Value.Fail(new MqttUnexpectedDisconnectReceivedException(disconnectPacket)); } return; } ushort identifier = 0; if (packet is IMqttPacketWithIdentifier packetWithIdentifier && packetWithIdentifier.PacketIdentifier > 0) { identifier = packetWithIdentifier.PacketIdentifier; } var type = packet.GetType(); var key = new Tuple <ushort, Type>(identifier, type); if (_awaiters.TryRemove(key, out var awaiter)) { awaiter.Complete(packet); return; } throw new MqttProtocolViolationException($"Received packet '{packet}' at an unexpected time."); }
public void Dispatch(MqttBasePacket packet) { if (packet == null) { throw new ArgumentNullException(nameof(packet)); } var type = packet.GetType(); if (_awaiters.TryGetValue(type, out var byId)) { ushort?identifier = 0; if (packet is IMqttPacketWithIdentifier packetWithIdentifier) { identifier = packetWithIdentifier.PacketIdentifier; } if (byId.TryRemove(identifier.Value, out var tcs)) { tcs.TrySetResult(packet); return; } } throw new InvalidOperationException($"Packet of type '{type.Name}' not handled or dispatched."); }
public bool TryDispatch(MqttBasePacket packet) { if (packet == null) { throw new ArgumentNullException(nameof(packet)); } ushort identifier = 0; if (packet is IMqttPacketWithIdentifier packetWithIdentifier) { identifier = packetWithIdentifier.PacketIdentifier; } var packetType = packet.GetType(); var awaitables = new List <IMqttPacketAwaitable>(); lock (_awaitables) { for (var i = _awaitables.Count - 1; i >= 0; i--) { var entry = _awaitables[i]; // Note: The PingRespPacket will also arrive here and has NO identifier but there // is code which waits for it. So the code must be able to deal with filters which // are referring to the type only (identifier is 0)! if (entry.Filter.Type != packetType || entry.Filter.Identifier != identifier) { continue; } awaitables.Add(entry); _awaitables.RemoveAt(i); } } foreach (var matchingEntry in awaitables) { matchingEntry.Complete(packet); } return(awaitables.Count > 0); }
async Task <TResponsePacket> SendAndReceiveAsync <TResponsePacket>(MqttBasePacket requestPacket, CancellationToken cancellationToken) where TResponsePacket : MqttBasePacket { cancellationToken.ThrowIfCancellationRequested(); ushort identifier = 0; if (requestPacket is IMqttPacketWithIdentifier packetWithIdentifier && packetWithIdentifier.PacketIdentifier > 0) { identifier = packetWithIdentifier.PacketIdentifier; } using (var packetAwaiter = _packetDispatcher.AddAwaiter <TResponsePacket>(identifier)) { try { _sendTracker.Restart(); await _adapter.SendPacketAsync(requestPacket, Options.CommunicationTimeout, cancellationToken).ConfigureAwait(false); } catch (Exception e) { _logger.Warning(e, "Error when sending request packet ({0}).", requestPacket.GetType().Name); packetAwaiter.Cancel(); } try { return(await packetAwaiter.WaitOneAsync(Options.CommunicationTimeout).ConfigureAwait(false)); } catch (Exception exception) { if (exception is MqttCommunicationTimedOutException) { _logger.Warning(null, "Timeout while waiting for response packet ({0}).", typeof(TResponsePacket).Name); } throw; } } }
public void AssertIsConnectPacket(MqttBasePacket packet) { Assert.AreEqual(packet.GetType(), typeof(MqttConnectPacket)); }
static void ThrowIfPacketIdentifierIsInvalid(ushort packetIdentifier, MqttBasePacket packet) { // SUBSCRIBE, UNSUBSCRIBE, and PUBLISH(in cases where QoS > 0) Control Packets MUST contain a non-zero 16 - bit Packet Identifier[MQTT - 2.3.1 - 1]. if (packetIdentifier == 0) { throw new MqttProtocolViolationException($"Packet identifier is not set for {packet.GetType().Name}."); } }