public async Task MqttSubscriptionsManager_SubscribeAndUnsubscribeSingle() { var s = new MqttClientSession("", new ConcurrentDictionary <object, object>(), new MqttServerEventDispatcher(new TestLogger()), new MqttServerOptions(), new TestLogger()); var sm = new MqttClientSubscriptionsManager(s, new MqttServerEventDispatcher(new TestLogger()), new MqttServerOptions()); var sp = new MqttSubscribePacket(); sp.TopicFilters.Add(new TopicFilterBuilder().WithTopic("A/B/C").Build()); await sm.SubscribeAsync(sp, new MqttConnectPacket()); Assert.IsTrue(sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce).IsSubscribed); var up = new MqttUnsubscribePacket(); up.TopicFilters.Add("A/B/C"); await sm.UnsubscribeAsync(up); Assert.IsFalse(sm.CheckSubscriptions("A/B/C", MqttQualityOfServiceLevel.AtMostOnce).IsSubscribed); }
public MqttUnsubAckPacket Unsubscribe(MqttUnsubscribePacket unsubscribePacket) { if (unsubscribePacket == null) { throw new ArgumentNullException(nameof(unsubscribePacket)); } lock (_subscriptions) { foreach (var topicFilter in unsubscribePacket.TopicFilters) { _subscriptions.Remove(topicFilter); _eventDispatcher.OnClientUnsubscribedTopic(_clientId, topicFilter); } } return(new MqttUnsubAckPacket { PacketIdentifier = unsubscribePacket.PacketIdentifier }); }
public void Serialize_Full_MqttUnsubscribePacket_V500() { var unsubscribePacket = new MqttUnsubscribePacket { PacketIdentifier = 123, TopicFilters = new List <string> { "TopicFilter1" }, UserProperties = new List <MqttUserProperty> { new MqttUserProperty("Foo", "Bar") } }; var deserialized = MqttPacketSerializationHelper.EncodeAndDecodePacket(unsubscribePacket, MqttProtocolVersion.V500); Assert.AreEqual(unsubscribePacket.PacketIdentifier, deserialized.PacketIdentifier); Assert.AreEqual(unsubscribePacket.TopicFilters.Count, deserialized.TopicFilters.Count); Assert.AreEqual(unsubscribePacket.TopicFilters[0], deserialized.TopicFilters[0]); CollectionAssert.AreEqual(unsubscribePacket.UserProperties, deserialized.UserProperties); }
public async Task <List <MqttUnsubscribeReasonCode> > UnsubscribeAsync(MqttUnsubscribePacket unsubscribePacket) { if (unsubscribePacket == null) { throw new ArgumentNullException(nameof(unsubscribePacket)); } var reasonCodes = new List <MqttUnsubscribeReasonCode>(); foreach (var topicFilter in unsubscribePacket.TopicFilters) { var interceptorContext = await InterceptUnsubscribeAsync(topicFilter).ConfigureAwait(false); if (!interceptorContext.AcceptUnsubscription) { reasonCodes.Add(MqttUnsubscribeReasonCode.ImplementationSpecificError); continue; } _subscriptionsLock.EnterWriteLock(); try { reasonCodes.Add(_subscriptions.Remove(topicFilter) ? MqttUnsubscribeReasonCode.Success : MqttUnsubscribeReasonCode.NoSubscriptionExisted); } finally { _subscriptionsLock.ExitWriteLock(); } } foreach (var topicFilter in unsubscribePacket.TopicFilters) { await _eventDispatcher.SafeNotifyClientUnsubscribedTopicAsync(_clientSession.ClientId, topicFilter).ConfigureAwait(false); } return(reasonCodes); }
public MqttClientUnsubscribeResult CreateClientUnsubscribeResult(MqttUnsubscribePacket unsubscribePacket, MqttUnsubAckPacket unsubAckPacket) { if (unsubscribePacket == null) { throw new ArgumentNullException(nameof(unsubscribePacket)); } if (unsubAckPacket == null) { throw new ArgumentNullException(nameof(unsubAckPacket)); } if (unsubAckPacket.ReasonCodes.Count != unsubscribePacket.TopicFilters.Count) { throw new MqttProtocolViolationException("The return codes are not matching the topic filters [MQTT-3.9.3-1]."); } var result = new MqttClientUnsubscribeResult(); result.Items.AddRange(unsubscribePacket.TopicFilters.Select((t, i) => new MqttClientUnsubscribeResultItem(t, (MqttClientUnsubscribeResultCode)unsubAckPacket.ReasonCodes[i]))); return(result); }
byte EncodeUnsubscribePacket(MqttUnsubscribePacket packet) { if (packet.TopicFilters?.Any() != true) { throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2]."); } ThrowIfPacketIdentifierIsInvalid(packet.PacketIdentifier, packet); _bufferWriter.WriteTwoByteInteger(packet.PacketIdentifier); _propertiesWriter.WriteUserProperties(packet.UserProperties); _propertiesWriter.WriteTo(_bufferWriter); _propertiesWriter.Reset(); foreach (var topicFilter in packet.TopicFilters) { _bufferWriter.WriteString(topicFilter); } return(MqttBufferWriter.BuildFixedHeader(MqttControlPacketType.Unsubscibe, 0x02)); }
public async Task <MqttUnsubAckPacket> UnsubscribeAsync(MqttUnsubscribePacket unsubscribePacket) { if (unsubscribePacket == null) { throw new ArgumentNullException(nameof(unsubscribePacket)); } await _semaphore.WaitAsync().ConfigureAwait(false); try { foreach (var topicFilter in unsubscribePacket.TopicFilters) { _subscriptions.Remove(topicFilter); } } finally { _semaphore.Release(); } return(unsubscribePacket.CreateResponse <MqttUnsubAckPacket>()); }
static byte EncodeUnsubscribePacket(MqttUnsubscribePacket packet, IMqttPacketWriter packetWriter) { if (!packet.TopicFilters.Any()) { throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2]."); } if (!packet.PacketIdentifier.HasValue) { throw new MqttProtocolViolationException("Unsubscribe packet has no packet identifier."); } packetWriter.Write(packet.PacketIdentifier.Value); if (packet.TopicFilters?.Any() == true) { foreach (var topicFilter in packet.TopicFilters) { packetWriter.WriteWithLengthPrefix(topicFilter); } } return(MqttPacketWriter.BuildFixedHeader(MqttControlPacketType.Unsubscibe, 0x02)); }
static byte EncodeUnsubscribePacket(MqttUnsubscribePacket packet, MqttBufferWriter bufferWriter) { if (!packet.TopicFilters.Any()) { throw new MqttProtocolViolationException("At least one topic filter must be set [MQTT-3.10.3-2]."); } if (packet.PacketIdentifier == 0) { throw new MqttProtocolViolationException("Unsubscribe packet has no packet identifier."); } bufferWriter.WriteTwoByteInteger(packet.PacketIdentifier); if (packet.TopicFilters?.Any() == true) { foreach (var topicFilter in packet.TopicFilters) { bufferWriter.WriteString(topicFilter); } } return(MqttBufferWriter.BuildFixedHeader(MqttControlPacketType.Unsubscibe, 0x02)); }
private void HandleIncomingUnsubscribePacket(IMqttChannelAdapter adapter, MqttUnsubscribePacket unsubscribePacket, CancellationToken cancellationToken) { var unsubscribeResult = _subscriptionsManager.Unsubscribe(unsubscribePacket); adapter.SendPacketAsync(unsubscribeResult, cancellationToken).GetAwaiter().GetResult(); }
private async Task HandleIncomingUnsubscribePacketAsync(IMqttChannelAdapter adapter, MqttUnsubscribePacket unsubscribePacket, CancellationToken cancellationToken) { var unsubscribeResult = await _subscriptionsManager.UnsubscribeAsync(unsubscribePacket); await adapter.SendPacketsAsync(_options.DefaultCommunicationTimeout, cancellationToken, unsubscribeResult); }
static MqttClientUnsubscribeResultItem CreateUnsubscribeResultItem(int index, MqttUnsubscribePacket unsubscribePacket, MqttUnsubAckPacket unsubAckPacket) { var resultCode = MqttClientUnsubscribeResultCode.Success; if (unsubAckPacket.ReasonCodes != null) { // MQTTv3.1.1 has no reason code and no return code!. resultCode = (MqttClientUnsubscribeResultCode)unsubAckPacket.ReasonCodes[index]; } return(new MqttClientUnsubscribeResultItem { TopicFilter = unsubscribePacket.TopicFilters[index], ResultCode = resultCode }); }
public async Task <MqttUnsubscribeResult> Unsubscribe(MqttUnsubscribePacket unsubscribePacket, CancellationToken cancellationToken) { if (unsubscribePacket == null) { throw new ArgumentNullException(nameof(unsubscribePacket)); } var result = new MqttUnsubscribeResult(); var removedSubscriptions = new List <string>(); await _subscriptionsLock.WaitAsync(cancellationToken).ConfigureAwait(false); try { foreach (var topicFilter in unsubscribePacket.TopicFilters) { _subscriptions.TryGetValue(topicFilter, out var existingSubscription); var interceptorContext = await InterceptUnsubscribe(topicFilter, existingSubscription, cancellationToken).ConfigureAwait(false); var acceptUnsubscription = interceptorContext.Response.ReasonCode == MqttUnsubscribeReasonCode.Success; result.ReasonCodes.Add(interceptorContext.Response.ReasonCode); if (interceptorContext.CloseConnection) { // When any of the interceptor calls leads to a connection close the connection // must be closed. So do not revert to false! result.CloseConnection = true; } if (!acceptUnsubscription) { continue; } if (interceptorContext.ProcessUnsubscription) { _subscriptions.Remove(topicFilter); // must remove subscription object from topic hash dictionary also if (existingSubscription.TopicHasWildcard) { if (_wildcardSubscriptionsByTopicHash.TryGetValue(existingSubscription.TopicHash, out var subs)) { subs.Subscriptions.Remove(existingSubscription); if (subs.Subscriptions.Count == 0) { _wildcardSubscriptionsByTopicHash.Remove(existingSubscription.TopicHash); } } } else { if (_noWildcardSubscriptionsByTopicHash.TryGetValue(existingSubscription.TopicHash, out var subs)) { subs.Remove(existingSubscription); if (subs.Count == 0) { _noWildcardSubscriptionsByTopicHash.Remove(existingSubscription.TopicHash); } } } removedSubscriptions.Add(topicFilter); } } } finally { _subscriptionsLock.Release(); if (_subscriptionChangedNotification != null) { _subscriptionChangedNotification.OnSubscriptionsRemoved(_session, removedSubscriptions); } } if (_eventContainer.ClientUnsubscribedTopicEvent.HasHandlers) { foreach (var topicFilter in unsubscribePacket.TopicFilters) { var eventArgs = new ClientUnsubscribedTopicEventArgs { ClientId = _session.Id, TopicFilter = topicFilter }; await _eventContainer.ClientUnsubscribedTopicEvent.InvokeAsync(eventArgs).ConfigureAwait(false); } } return(result); }