/// <summary> /// Send an announcement message, and schedule the next such message. /// </summary> /// <remarks> /// After constructing a Peer, generally one calls Announce() just once /// to start the perpetual cycle of announcements that each Peer makes. /// </remarks> public void Announce(bool isHostingAudio = false) { logger?.WriteNet(NetLogLevel.Trace, $"DistributedHost.Announce()"); AnnounceMessage message = new AnnounceMessage { AnnouncerSocketAddress = SocketAddress, AnnouncerIsHostingAudio = isHostingAudio, KnownPeers = netManager .ConnectedPeerList .Select(peer => new SerializedSocketAddress(peer.EndPoint.Serialize())) .ToArray() }; SendBroadcastMessage(message); // schedule next announcement workQueue.RunLater(() => Announce(isHostingAudio), AnnounceDelayMsec); }
/// <summary> /// An announcement has been received (via broadcast); react accordingly. /// </summary> private void OnAnnounceReceived(AnnounceMessage message, IPEndPoint endpoint) { // heed only ipv4 for now... TBD what to do about this if (endpoint.AddressFamily == AddressFamily.InterNetwork) { // is this actually our own announcement!? SerializedSocketAddress incomingAddress = new SerializedSocketAddress(endpoint.Serialize()); if (incomingAddress == this.SocketAddress) { // ignore this, we're talking to ourselves return; } PeerAnnounceCount++; // do we know this peer already? // (could happen in race scenario) if (netManager.ConnectedPeerList.Any(peer => peer.EndPoint.Equals(endpoint))) { return; } // did we already respond to this peer? if (AnnouncedEndPoints.Contains(endpoint)) { return; } // did this peer know us already? (typical scenario given re-announcements) if (message.KnownPeers.Contains(SocketAddress)) { return; } logger?.WriteNet(NetLogLevel.Trace, $"DistributedHost.OnAnnounceReceived({endpoint}) -- responding. {ConnectionsStatusString()}]"); // send announce response AnnounceResponseMessage response = new AnnounceResponseMessage { }; SendUnconnectedMessage(response, endpoint); } }