#pragma warning disable VSTHRD100 // Avoid async void methods /// <summary> /// Raised when a connection is established to a remote peer. /// </summary> /// <param name="sender"></param> /// <param name="connection"></param> /// <remarks> /// Sends the hello message to the remote peer. The message contains /// all topics that are of interest to the local peer. /// </remarks> async void Swarm_ConnectionEstablished(object sender, PeerConnection connection) #pragma warning restore VSTHRD100 // Avoid async void methods { if (localTopics.Count == 0) { return; } try { var hello = new PubSubMessage { Subscriptions = localTopics.Values .Select(topic => new Subscription { Subscribe = true, Topic = topic }) .ToArray() }; await SendAsync(hello, new Peer[] { connection.RemotePeer }, CancellationToken.None).ConfigureAwait(false); } catch (Exception e) { log.Warn("Sending hello message failed", e); } }
/// <inheritdoc /> public async Task LeaveTopicAsync(string topic, CancellationToken cancel) { localTopics.TryRemove(topic, out _); var msg = new PubSubMessage { Subscriptions = new Subscription[] { new Subscription { Topic = topic, Subscribe = false } } }; try { var peers = Swarm.KnownPeers.Where(p => p.ConnectedAddress != null); await SendAsync(msg, peers, cancel).ConfigureAwait(false); } catch (Exception e) { log.Warn("Leave topic failed.", e); } }
Task SendAsync(PubSubMessage msg, IEnumerable<Peer> peers, CancellationToken cancel) { // Get binary representation byte[] bin; using (var ms = new MemoryStream()) { Serializer.SerializeWithLengthPrefix(ms, msg, PrefixStyle.Base128); bin = ms.ToArray(); } return Task.WhenAll(peers.Select(p => SendAsync(bin, p, cancel))); }
/// <inheritdoc /> public Task PublishAsync(PublishedMessage message, CancellationToken cancel) { if (tracker.RecentlySeen(message.MessageId)) return Task.CompletedTask; // Find a set of peers that are interested in the topic(s). // Exclude author and sender var peers = message.Topics .SelectMany(topic => RemoteTopics.GetPeers(topic)) .Where(peer => peer != message.Sender) .Where(peer => peer != message.Forwarder); // Forward the message. var forward = new PubSubMessage { PublishedMessages = new PublishedMessage[] { message } }; return SendAsync(forward, peers, cancel); }