public async Task PublishAsync(string topic, byte[] payload, QualityOfService qos = QualityOfService.AtMostOnce, bool retain = false) { TaskCompletionSource <object> future = new TaskCompletionSource <object>(); PublishPacket packet = new PublishPacket(qos, false, retain); packet.TopicName = topic; packet.PacketId = PacketIdProvider.NewPacketId(); packet.Payload = Unpooled.WrappedBuffer(payload); packet.Retain(); WriteResult result = await sendAndFlushAsync(packet); if (!result.Success) { packet.Release();//needed? future.SetException(result.Exception); } else if (qos == QualityOfService.AtLeastOnce) { packet.Release(); //needed? future.SetResult(null); //We don't get an ACK for QOS 0 } else { PendingPublish pendingPublish = new PendingPublish(packet, future);//return after PubAct(QoS=1)/PubRel(QoS=2) received. pendingPublishes.TryAdd(packet.PacketId, pendingPublish); pendingPublish.RetransmitPublish(eventLoopGroup.GetNext(), sendAndFlushAsync); } await future.Task; }
private async Task checkSubscriptionsAsync(string topic, TaskCompletionSource <object> promise) { if (!topicSubscriptions.ContainsKey(topic) && subscribedTopics.Contains(topic)) { UnsubscribePacket packet = new UnsubscribePacket(PacketIdProvider.NewPacketId(), topic); PendingUnsubscribe pendingUnsubscribe = new PendingUnsubscribe(promise, topic, packet); pendingUnsubscribes.TryAdd(packet.PacketId, pendingUnsubscribe); pendingUnsubscribe.Retransmit(eventLoopGroup.GetNext(), sendAndFlushAsync); await sendAndFlushAsync(packet); } else { promise.SetResult(null); } }
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; }