public static SubAckPacket AddSubscriptions(ISessionState session, SubscribePacket packet, QualityOfService maxSupportedQos) { List <Subscription> subscriptions = session.Subscriptions; var returnCodes = new List <QualityOfService>(subscriptions.Count); foreach (SubscriptionRequest request in packet.Requests) { Subscription existingSubscription = null; for (int i = subscriptions.Count - 1; i >= 0; i--) { Subscription subscription = subscriptions[i]; if (subscription.TopicFilter.Equals(request.TopicFilter, StringComparison.Ordinal)) { subscriptions.RemoveAt(i); existingSubscription = subscription; break; } } QualityOfService finalQos = request.QualityOfService < maxSupportedQos ? request.QualityOfService : maxSupportedQos; subscriptions.Add(existingSubscription == null ? new Subscription(request.TopicFilter, request.QualityOfService) : existingSubscription.CreateUpdated(finalQos)); returnCodes.Add(finalQos); } var ack = new SubAckPacket { PacketId = packet.PacketId, ReturnCodes = returnCodes }; return(ack); }
static void DecodeSubscribePayload(DataReader reader, SubscribePacket packet, ref uint remainingLength) { var subscribeTopics = new List <SubscriptionRequest>(); while (remainingLength > 0) { string topicFilter = DecodeString(reader, ref remainingLength); ValidateTopicFilter(topicFilter); DecreaseRemainingLength(ref remainingLength, 1); var qos = reader.ReadByte(); if (qos >= (int)QualityOfService.Reserved) { throw new DecoderException($"[MQTT-3.8.3-4]. Invalid QoS value: {qos}."); } subscribeTopics.Add(new SubscriptionRequest(topicFilter, (QualityOfService)qos)); } if (subscribeTopics.Count == 0) { throw new DecoderException("[MQTT-3.8.3-3]"); } packet.Requests = subscribeTopics; }
static void DecodeSubscribePayload(IByteBuffer buffer, SubscribePacket packet, ref int remainingLength) { const int ReservedQos = (int)QualityOfService.Reserved; var subscribeTopics = new List <SubscriptionRequest>(); while (remainingLength > 0) { string topicFilter = DecodeString(buffer, ref remainingLength); ValidateTopicFilter(topicFilter); DecreaseRemainingLength(ref remainingLength, 1); int qos = buffer.ReadByte(); if (qos >= ReservedQos) { ThrowHelper.ThrowDecoderException_MQTT_383_4(qos); } subscribeTopics.Add(new SubscriptionRequest(topicFilter, (QualityOfService)qos)); } if (0u >= (uint)subscribeTopics.Count) { ThrowHelper.ThrowDecoderException_MQTT_383_3(); } packet.Requests = subscribeTopics; }
public async Task <string> InternalSubscribeAsync(string subject, string queueGroup, Func <NATSMsgSubscriptionConfig, SubscriptionMessageHandler> messageHandlerSetup, int?maxMsg = null, string subscribeId = null) { await ConnectAsync(); var SubscribeId = subscribeId ?? $"sid{Interlocked.Increment(ref _subscribeId)}"; _logger.LogDebug($"设置订阅消息队列订阅编号 Subject = {subject} QueueGroup = {queueGroup} SubscribeId = {SubscribeId}"); var SubscriptionConfig = new NATSMsgSubscriptionConfig(subject, SubscribeId, queueGroup, maxMsg); //处理订阅响应的管道 var messageHandler = messageHandlerSetup(SubscriptionConfig); _logger.LogDebug($"开始添加消息队列处理器 Subject = {subject} QueueGroup = {queueGroup} SubscribeId = {SubscribeId}"); //添加订阅响应管道 _embed_channel.Pipeline.AddLast(messageHandler); _logger.LogDebug($"结束添加消息队列处理器 Subject = {subject} QueueGroup = {queueGroup} SubscribeId = {SubscribeId}"); _logger.LogDebug($"开始发送订阅请求 订阅主题 {subject } 订阅编号 {SubscribeId}"); var SubscribePacketMsg = new SubscribePacket(SubscribeId, subject, queueGroup); await _embed_channel.WriteAndFlushAsync(SubscribePacketMsg); _logger.LogDebug($"结束发送订阅请求 订阅主题 {subject } 订阅编号 {SubscribeId}"); //添加消息处理到消息处理集合 _subscriptionMessageHandler.Add(messageHandler); return(SubscribeId); }
async Task SubscribeAsync(IChannelHandlerContext context, SubscribePacket packetPassed) { string topicFilter; QualityOfService qos; if (packetPassed == null || packetPassed.Requests == null) { topicFilter = topicFilter = CommandTopicFilterFormat.FormatInvariant(this.deviceId); qos = mqttTransportSettings.ReceivingQoS; } else if (packetPassed.Requests.Count == 1) { topicFilter = packetPassed.Requests[0].TopicFilter; qos = packetPassed.Requests[0].QualityOfService; } else { throw new ArgumentException("unexpected request count. expected 1, got " + packetPassed.Requests.Count.ToString()); } int packetId = Util.GetNextPacketId(); var subscribePacket = new SubscribePacket(packetId, new SubscriptionRequest(topicFilter, qos)); this.subscribeCompletions[packetId] = new TaskCompletionSource(); await Util.WriteMessageAsync(context, subscribePacket, ShutdownOnWriteErrorHandler); await this.subscribeCompletions[packetId].Task; }
public async Task <string> InternalSubscribeAsync(string subject, string queueGroup, SubscriptionMessageHandler messageHandler, string subscribeId = null) { await ConnectAsync(); var SubscribeId = subscribeId ?? $"sid{Interlocked.Increment(ref _subscribeId)}"; _logger.LogDebug($"开始添加消息队列处理器 Subject = {subject} QueueGroup = {queueGroup} SubscribeId = {SubscribeId}"); //添加订阅响应管道 _embed_channel.Pipeline.AddLast(messageHandler); _logger.LogDebug($"结束添加消息队列处理器 Subject = {subject} QueueGroup = {queueGroup} SubscribeId = {SubscribeId}"); _logger.LogDebug($"开始发送订阅请求 订阅主题 {subject } 订阅编号 {SubscribeId}"); var SubscribePacketMsg = new SubscribePacket(SubscribeId, subject, queueGroup); await _embed_channel.WriteAndFlushAsync(SubscribePacketMsg); _logger.LogDebug($"结束发送订阅请求 订阅主题 {subject } 订阅编号 {SubscribeId}"); return(SubscribeId); }
public Task <IMqttResult> Subscribe(MqttClientSession clientSession, SubscribePacket subscribePacket) { if (!CLIENT_DIC.TryGetValue(clientSession.ClientId, out List <MqttSubscription> subList)) { subList = new List <MqttSubscription>(); CLIENT_DIC.TryAdd(clientSession.ClientId, subList); } foreach (SubscriptionRequest subReq in subscribePacket.Requests) { if (!subList.Exists(x => x.Topic.Equals(subReq.TopicFilter, StringComparison.OrdinalIgnoreCase))) { subList.Add(new MqttSubscription { ClientSession = clientSession, Topic = subReq.TopicFilter, Qos = subReq.QualityOfService }); } if (!TOPIC_DIC.TryGetValue(subReq.TopicFilter, out List <string> clientIds)) { clientIds = new List <string>(); TOPIC_DIC.TryAdd(subReq.TopicFilter, clientIds); } clientIds.Add(clientSession.ClientId); } return(Task.FromResult <IMqttResult>(SubscribeResult.SUCCESS)); }
static void EncodeSubscribeMessage(DataWriter writer, SubscribePacket packet) { const int VariableHeaderSize = PACKET_ID_LENGTH; int payloadBufferSize = 0; var encodedTopicFilters = new List <byte[]>(); foreach (var topic in packet.Requests) { byte[] topicFilterBytes = EncodeStringInUtf8(topic.TopicFilter); payloadBufferSize += STRING_SIZE_LENGTH + topicFilterBytes.Length + 1; // length, value, QoS encodedTopicFilters.Add(topicFilterBytes); } int variablePartSize = VariableHeaderSize + payloadBufferSize; writer.WriteByte(CalculateFirstByteOfFixedHeader(packet)); WriteVariableLengthInt(writer, variablePartSize); // Variable Header writer.WriteInt16((short)packet.PacketId); // todo: review: validate? // Payload for (int i = 0; i < encodedTopicFilters.Count; i++) { var topicFilterBytes = encodedTopicFilters[i]; writer.WriteInt16((short)topicFilterBytes.Length); writer.WriteBytes(topicFilterBytes); writer.WriteByte((byte)packet.Requests[i].QualityOfService); } }
private void Subscribe(SubscribePacket packet) { if (packet.PacketId == 0) { packet.PacketId = GetNextPacketId(); } Send(packet); }
async Task SubscribeForDM() { var messageSync = new SubscriptionRequest("/ig_message_sync", QualityOfService.AtLeastOnce); var sendMessageResp = new SubscriptionRequest("/ig_send_message_response", QualityOfService.AtLeastOnce); var subIrisResp = new SubscriptionRequest("/ig_sub_iris_response", QualityOfService.AtLeastOnce); var subscribePacket = new SubscribePacket((ushort)CryptographicBuffer.GenerateRandomNumber(), messageSync, sendMessageResp, subIrisResp); await FbnsPacketEncoder.EncodePacket(subscribePacket, _outboundWriter); }
/// <summary> /// 订阅主题 /// </summary> /// <param name="topic">主题</param> /// <param name="qos">服务质量等级</param> /// <param name="cancellationToken"></param> public Task SubscribeAsync(string topic, MqttQos qos, CancellationToken cancellationToken) { var packet = new SubscribePacket(); packet.VariableHeader.PacketIdentifier = _packetIdProvider.NewPacketId(); packet.Add(topic, qos); return(SendPacketAsync(packet)); }
bool TryDecodePacket(IChannelHandlerContext context, IByteBuffer buffer, out Packet packet) { if (!buffer.IsReadable(2)) { packet = null; return(false); } byte signature = buffer.ReadByte(); if (!TryDecodeRemainingLength(buffer, out int remainingLength) || !buffer.IsReadable(remainingLength)) { packet = null; return(false); } var fixedHeader = new FixedHeader(signature, remainingLength); switch (fixedHeader.PacketType) { case PacketType.CONNECT: packet = new ConnectPacket(); break; case PacketType.CONNACK: packet = new ConnAckPacket(); break; case PacketType.DISCONNECT: packet = new DisconnectPacket(); break; case PacketType.PINGREQ: packet = new PingReqPacket(); break; case PacketType.PINGRESP: packet = new PingRespPacket(); break; case PacketType.PUBACK: packet = new PubAckPacket(); break; case PacketType.PUBCOMP: packet = new PubCompPacket(); break; case PacketType.PUBLISH: packet = new PublishPacket(); break; case PacketType.PUBREC: packet = new PubRecPacket(); break; case PacketType.PUBREL: packet = new PubRelPacket(); break; case PacketType.SUBSCRIBE: packet = new SubscribePacket(); break; case PacketType.SUBACK: packet = new SubAckPacket(); break; case PacketType.UNSUBSCRIBE: packet = new UnsubscribePacket(); break; case PacketType.UNSUBACK: packet = new UnsubscribePacket(); break; default: throw new DecoderException("Unsupported Message Type"); } packet.FixedHeader = fixedHeader; packet.Decode(buffer); return(true); }
/// <summary> /// 订阅主题 /// </summary> /// <param name="topic">主题</param> /// <param name="qos">服务质量等级</param> /// <param name="cancellationToken"></param> public async Task SubscribeAsync(string topic, MqttQos qos, CancellationToken cancellationToken) { var packet = new SubscribePacket { PacketId = _packetIdProvider.NewPacketId(), }; packet.Add(topic, qos); await SendAndFlushPacketAsync(packet); }
/// <summary> /// 订阅主题 /// </summary> /// <param name="topic">主题</param> /// <param name="qos">服务质量等级</param> public Task SubscribeAsync(string topic, MqttQos qos = MqttQos.AtMostOnce) { var packet = new SubscribePacket { PacketIdentifier = _packetIdentifierProvider.GetNewPacketIdentifier(), }; packet.Subscribe(topic, qos); return(_clientChannel.WriteAndFlushAsync(packet)); }
public async Task Subscribe(IChannelHandlerContext context, SubscribePacket packet) { if (packet != null) { var topics = packet.Requests.Select(p => p.TopicFilter).ToArray(); await _channelService.Suscribe(await _channelService.GetDeviceId(context.Channel), topics); await SubAck(context, SubAckPacket.InResponseTo(packet, QualityOfService.ExactlyOnce )); } }
public void TestSubscribeMessage(int packetId, string[] topicFilters, QualityOfService[] requestedQosValues) { var packet = new SubscribePacket(packetId, topicFilters.Zip(requestedQosValues, (topic, qos) => new SubscriptionRequest(topic, qos)).ToArray()); SubscribePacket recoded = this.RecodePacket(packet, true, true); this.contextMock.Verify(x => x.FireChannelRead(It.IsAny <SubscribePacket>()), Times.Once); Assert.Equal(packet.Requests, recoded.Requests, EqualityComparer <SubscriptionRequest> .Default); Assert.Equal(packet.PacketId, recoded.PacketId); }
/// <summary> /// 订阅主题 /// </summary> /// <param name="topic">主题</param> /// <param name="qos">服务质量等级</param> public Task <SubAckPacket> SubscribeAsync(string topic, MqttQos qos = MqttQos.AtMostOnce) { var packet = new SubscribePacket { PacketId = _packetIdentifierProvider.GetPacketId(), }; packet.Add(topic, qos); return(SendAndReceiveAsync <SubAckPacket>(packet, _cancellationTokenSource.Token)); }
public async Task ShouldNotAssumeEventOrdering_SubscribeContinuesAfterUnsubAckReceived() { var request = new SubscribePacket(0, new SubscriptionRequest("myTopic", QualityOfService.AtMostOnce)); Func <PacketWithId, SubAckPacket> ackFactory = (packet) => new SubAckPacket() { PacketId = packet.PacketId }; await SendRequestAndAcknowledgementsInSpecificOrder(request, ackFactory, true).ConfigureAwait(false); }
public PendingSubscribe(TaskCompletionSource <object> promise, string topic, SubscribePacket packet) { Promise = promise; Topic = topic; Packet = packet; Callbacks = new List <Action <Packet> >(); retransmissionAction = new RetransmissionAction <SubscribePacket>() { OriginalPacket = packet }; }
public void TestSubscribeMessage(ushort packetId, string[] topicFilters, MqttQos[] requestedQosValues) { var packet = new SubscribePacket(); packet.VariableHeader.PacketIdentifier = packetId; packet.AddRange(topicFilters.Zip(requestedQosValues, (topic, qos) => new SubscribeRequest(topic, qos)).ToArray()); SubscribePacket recoded = RecodePacket(packet, true, true); contextMock.Verify(x => x.FireChannelRead(It.IsAny <SubscribePacket>()), Times.Once); //Assert.Equal(packet.Requests, recoded.Requests, EqualityComparer<SubscribeRequest>.Default); //Assert.Equal(packet.PacketId, recoded.PacketId); }
public async Task ShouldNotAssumeEventOrdering_SubscribeContinuesBeforeSubAckReceived() { var request = new SubscribePacket(0, new SubscriptionRequest("myTopic", QualityOfService.AtMostOnce)); Func <PacketWithId, SubAckPacket> ackFactory = (packet) => { return(new SubAckPacket() { PacketId = packet.PacketId }); }; await SendRequestAndAcksInSpecificOrderAsync(request, ackFactory, false).ConfigureAwait(false); }
public void Process(SubscribePacket packet, NetPeer peer) { Channel channel; if (ChannelManager.Global.Channels.ContainsKey(packet.Channel)) { channel = ChannelManager.Global.Channels[packet.Channel]; } else { channel = new Channel(packet.Channel); } channel.Subscibers.Add(peer); Logger.Log($"{peer.EndPoint} subscibed to {packet.Channel}."); }
static void DecodeSubscribePayload(IByteBuffer buffer, SubscribePacket packet, ref int remainingLength) { while (remainingLength > 0) { string topicFilter = DecodeString(buffer, ref remainingLength); ValidateTopicFilter(topicFilter); DecreaseRemainingLength(ref remainingLength, 1); int qos = buffer.ReadByte(); //if (qos >= (int)MqttQos.Reserved) //{ // throw new DecoderException($"[MQTT-3.8.3-4]. Invalid QoS value: {qos}."); //} packet.Add(new SubscriptionRequest(topicFilter, (MqttQos)qos)); } }
static void EncodeSubscribeMessage(IByteBufferAllocator bufferAllocator, SubscribePacket packet, List <object> output) { const int VariableHeaderSize = PacketIdLength; int payloadBufferSize = 0; ThreadLocalObjectList encodedTopicFilters = ThreadLocalObjectList.NewInstance(); IByteBuffer buf = null; try { foreach (SubscriptionRequest topic in packet.Requests) { byte[] topicFilterBytes = EncodeStringInUtf8(topic.TopicFilter); payloadBufferSize += StringSizeLength + topicFilterBytes.Length + 1; // length, value, QoS encodedTopicFilters.Add(topicFilterBytes); } int variablePartSize = VariableHeaderSize + payloadBufferSize; int fixedHeaderBufferSize = 1 + MaxVariableLength; buf = bufferAllocator.Buffer(fixedHeaderBufferSize + variablePartSize); buf.WriteByte(CalculateFirstByteOfFixedHeader(packet)); WriteVariableLengthInt(buf, variablePartSize); // Variable Header buf.WriteShort(packet.PacketId); // todo: review: validate? // Payload for (int i = 0; i < encodedTopicFilters.Count; i++) { var topicFilterBytes = (byte[])encodedTopicFilters[i]; buf.WriteShort(topicFilterBytes.Length); buf.WriteBytes(topicFilterBytes, 0, topicFilterBytes.Length); buf.WriteByte((int)packet.Requests[i].QualityOfService); } output.Add(buf); buf = null; } finally { buf?.SafeRelease(); encodedTopicFilters.Return(); } }
Packet DecodePacketInternal(IByteBuffer buffer, byte packetSignature, ref int remainingLength) { Packet packet; var fixedHeader = new FixedHeader(packetSignature, remainingLength); switch (fixedHeader.PacketType) { case PacketType.CONNECT: packet = new ConnectPacket(); break; case PacketType.CONNACK: packet = new ConnAckPacket(); break; case PacketType.DISCONNECT: packet = new DisconnectPacket(); break; case PacketType.PINGREQ: packet = new PingReqPacket(); break; case PacketType.PINGRESP: packet = new PingRespPacket(); break; case PacketType.PUBACK: packet = new PubAckPacket(); break; case PacketType.PUBCOMP: packet = new PubCompPacket(); break; case PacketType.PUBLISH: packet = new PublishPacket(); break; case PacketType.PUBREC: packet = new PubRecPacket(); break; case PacketType.PUBREL: packet = new PubRelPacket(); break; case PacketType.SUBSCRIBE: packet = new SubscribePacket(); break; case PacketType.SUBACK: packet = new SubAckPacket(); break; case PacketType.UNSUBSCRIBE: packet = new UnsubscribePacket(); break; case PacketType.UNSUBACK: packet = new UnsubscribePacket(); break; default: throw new DecoderException("Unsupported Message Type"); } packet.FixedHeader = fixedHeader; packet.Decode(buffer); remainingLength = packet.RemaingLength; return(packet); }
async Task SubscribeAsync(IChannelHandlerContext context) { if (this.IsInState(StateFlags.Receiving) || this.IsInState(StateFlags.Subscribing)) { return; } this.stateFlags |= StateFlags.Subscribing; this.subscribeCompletion = new TaskCompletionSource(); string topicFilter = CommandTopicFilterFormat.FormatInvariant(this.deviceId); var subscribePacket = new SubscribePacket(Util.GetNextPacketId(), new SubscriptionRequest(topicFilter, this.mqttTransportSettings.ReceivingQoS)); await Util.WriteMessageAsync(context, subscribePacket, ShutdownOnWriteErrorHandler); await this.subscribeCompletion.Task; }
/// <summary> /// Subscribes the specified context. /// </summary> /// <param name="context">The context.</param> /// <param name="packet">The packet.</param> public async Task Subscribe(IChannelHandlerContext context, SubscribePacket packet) { if (packet != null) { var deviceId = await _channelService.GetDeviceId(context.Channel); var topics = packet.Requests.Select(p => p.TopicFilter).ToArray(); var message = TransportMessage.CreateInvokeMessage(new RemoteInvokeMessage { ServiceId = "Subscribe", Parameters = new Dictionary <string, object> { { "packet", packet } } }); WirteDiagnosticBefore(message, context.Channel.RemoteAddress.ToString(), deviceId, packet.PacketType); await _channelService.Suscribe(deviceId, topics); await SubAck(context, SubAckPacket.InResponseTo(packet, QualityOfService.ExactlyOnce)); WirteDiagnosticAfter(message); } }
async Task SubscribeAsync(IChannelHandlerContext context, SubscribePacket packetPassed) { if (Logging.IsEnabled) { Logging.Enter(this, context.Name, packetPassed, nameof(SubscribeAsync)); } string topicFilter; QualityOfService qos; if (packetPassed == null || packetPassed.Requests == null) { topicFilter = this.GetCommandTopicFilter(); qos = mqttTransportSettings.ReceivingQoS; } else if (packetPassed.Requests.Count == 1) { topicFilter = packetPassed.Requests[0].TopicFilter; qos = packetPassed.Requests[0].QualityOfService; } else { throw new ArgumentException("unexpected request count. expected 1, got " + packetPassed.Requests.Count.ToString()); } if (!string.IsNullOrEmpty(topicFilter)) { int packetId = Util.GetNextPacketId(); var subscribePacket = new SubscribePacket(packetId, new SubscriptionRequest(topicFilter, qos)); this.subscribeCompletions[packetId] = new TaskCompletionSource(); await Util.WriteMessageAsync(context, subscribePacket, ShutdownOnWriteErrorHandler).ConfigureAwait(true); await this.subscribeCompletions[packetId].Task.ConfigureAwait(true); } if (Logging.IsEnabled) { Logging.Exit(this, context.Name, packetPassed, nameof(SubscribeAsync)); } }
public static SubAckPacket AddSubscriptions(ISessionState session, SubscribePacket packet, QualityOfService maxSupportedQos) { IReadOnlyList <ISubscription> subscriptions = session.Subscriptions; var returnCodes = new List <QualityOfService>(subscriptions.Count); foreach (SubscriptionRequest request in packet.Requests) { QualityOfService finalQos = request.QualityOfService < maxSupportedQos ? request.QualityOfService : maxSupportedQos; session.AddOrUpdateSubscription(request.TopicFilter, finalQos); returnCodes.Add(finalQos); } var ack = new SubAckPacket { PacketId = packet.PacketId, ReturnCodes = returnCodes }; return(ack); }
public async Task SubscribeAsync(string topic, QualityOfService qos, Action <Packet> callback) { if (pendingSubscribeTopics.Contains(topic)) { foreach (var subscription in pendingSubscribes.Values) { if (subscription.Topic == topic) { subscription.AddCallback(callback); await subscription.Promise.Task; return; } } }//subscribe is pending, return pending task. if (subscribedTopics.Contains(topic)) { Subscription subscription = new Subscription(topic, callback); topicSubscriptions.Put(topic, subscription); callbackSubscriptions.Put(callback, subscription); return;//channel.newSucceededFuture()? }//already subscribed, add callback to topic's subscription. //send SubscribePacket and complete Task when SubAck received. TaskCompletionSource <object> future = new TaskCompletionSource <object>(); SubscribePacket subscribePacket = new SubscribePacket(PacketIdProvider.NewPacketId(), new SubscriptionRequest(topic, qos)); var pendingSubscription = new PendingSubscribe(future, topic, subscribePacket); pendingSubscription.AddCallback(callback); pendingSubscribes.TryAdd(subscribePacket.PacketId, pendingSubscription); pendingSubscribeTopics.Add(topic); var result = await sendAndFlushAsync(subscribePacket); pendingSubscription.Sent = result.Success;//If not sent, we will send it when the connection is opened pendingSubscription.Retransmit(eventLoopGroup.GetNext(), sendAndFlushAsync); await future.Task; }