// Adds a peer to the candidate list or updates an existing candidate private void AddPeerCandidate(PeerCandidate Peer) { // Lock peer candidate list to prevent race conditions lock (PeerCandidatesGreyList) { // Peer exists in the list already if (PeerCandidatesGreyList.Any(x => x.Id == Peer.Id)) { // Find peer in the list var LocalPeer = PeerCandidatesGreyList.First(x => x.Id == Peer.Id); // Update peer's last seen time if (LocalPeer.LastSeen < Peer.LastSeen) { LocalPeer.LastSeen = Peer.LastSeen; } } // Peer has not yet been added else { // Add peer to the candidate list PeerCandidatesGreyList.Add(Peer); } } }
// Returns whether or not a peer is connected already private bool IsPeerConnected(PeerCandidate Peer) { // Check whether the peer candidate is this node if (Peer.Id == Id) { return(true); } // Lock peer list to prevent race conditions lock (PeerList) { // Check if the connected peer list contains this peer if (PeerList.Any(x => x.Id == Peer.Id)) { return(true); } // Check if any incoming connections have this address + port if (P2pServer.PendingConnections.Any(x => x.Client.RemoteEndPoint.ToString() == $"{Peer.Address}:{Peer.Port}")) { return(true); } } // Peer is not connected return(false); }
// Returns whether or not a peer is blacklisted private bool IsPeerAllowed(PeerCandidate Peer) { // Lock list to prevent race conditions lock (RecentlyTriedPeerCandidates) { // Return whether or not the recently tried peer list contains this peer return(RecentlyTriedPeerCandidates.Contains(Peer.Id)); } }
// Adds a peer to the list of recently tried peers private void AddRecentlyTriedPeer(PeerCandidate Peer) { // Lock list to prevent race conditions lock (RecentlyTriedPeerCandidates) { // Add the peer id to the list RecentlyTriedPeerCandidates.Add(Peer.Id); } }
// Returns whether or not a peer is blacklisted private bool IsPeerBlacklisted(PeerCandidate Peer) { // Lock blacklist to prevent race conditions lock (PeerBlackList) { // Return whether or not the blacklist contains this peer return(PeerBlackList.Contains(Peer.Id)); } }
// Adds a peer to the list of blacklisted peers private void AddBlacklistedPeer(PeerCandidate Peer) { // Lock blacklist to prevent race conditions lock (PeerBlackList) { // Add the peer id to the list PeerBlackList.Add(Peer.Id); } }
// Returns whether or not a peer is connected already private bool IsPeerConnected(PeerCandidate Peer) { // Check whether the peer candidate is this node if (Peer.Id == Id) { return(true); } // Lock peer list to prevent race conditions lock (PeerList) { // Check if the connected peer list contains this peer if (PeerList.Any(x => x.Id == Peer.Id)) { return(true); } // TODO - check if incoming connections has this address+port } // Peer is not connected return(false); }
// Attempts to connect to a new peer on the peer candidate list private void DiscoverNewPeer() { // Do nothing if not running if (Stopped) { return; } // Check if discovery is enabled if (!Globals.P2P_DISCOVERY_ENABLED) { return; } // Check if discovery is already active if (DiscoveryActive) { return; } DiscoveryActive = true; // Check if the peer list has space for a new peer if (GetPeerCount() >= Globals.P2P_MAX_PEER_CONNECTIONS) { return; } // Get the peer candidate list List <PeerCandidate> Candidates = GetPeerCandidates(); // Check if there are candidates in the list if (Candidates.Count == 0) { return; } // Setup variables int TryCount = 0; int RandomCount = 0; int MaxIndex = Math.Min(Candidates.Count - 1, 50); List <int> TriedIndexes = new List <int>(); // Loop to try a selection of candidates while (RandomCount < (MaxIndex + 1) * 3 && TryCount < 10 && !Stopped) { // Increment random count and get net random index RandomCount++; int RandomIndex = SecureRandom.Integer(0, MaxIndex + 1); RandomIndex = (RandomIndex * RandomIndex * RandomIndex) / (MaxIndex * MaxIndex); // Check if this index has been tried previously if (TriedIndexes.Contains(RandomIndex)) { continue; } // Add this index to the tried indexes list TriedIndexes.Add(RandomIndex); // Get the peer candidate PeerCandidate Peer = Candidates[RandomIndex]; // Increment try count TryCount++; // Check if this peer is already connected if (IsPeerConnected(Peer)) { continue; } // TODO - check if we are allowing remote connections?? // Check if this peer has previously been blacklists if (IsPeerAllowed(Peer)) { return; } // Attempt to add this peer candidate Logger.Debug($"[{TryCount}/10] Trying candidate #{RandomIndex} {Peer.Address}:{Peer.Port}, last seen {GetTimeDelta(Peer.LastSeen)} seconds ago"); if (!AddPeer(Peer.Address, (int)Peer.Port)) { // Add to failed connection list AddRecentlyTriedPeer(Peer); } } // Discovery process finished DiscoveryActive = false; }