private void SelectAndRankCandidates() { _currentSelection.PreCandidates.Clear(); _currentSelection.Candidates.Clear(); _currentSelection.Incompatible.Clear(); foreach (ActivePeerSelectionCounter value in Enum.GetValues(typeof(ActivePeerSelectionCounter))) { _currentSelection.Counters[value] = 0; } var availableActiveCount = _networkConfig.ActivePeersMaxCount + _staticNodes.Count - _activePeers.Count; if (availableActiveCount <= 0) { return; } foreach ((PublicKey key, Peer peer) in _candidatePeers) { if (_activePeers.ContainsKey(key)) { continue; } if (peer.Node.Port > 65535) { continue; } _currentSelection.PreCandidates.Add(peer); } var hasOnlyStaticNodes = false; if (!_currentSelection.PreCandidates.Any() && _staticNodes.Values.Any()) { _currentSelection.Candidates.AddRange(_staticNodes.Values); hasOnlyStaticNodes = true; } if (!_currentSelection.PreCandidates.Any() && !hasOnlyStaticNodes) { return; } _currentSelection.Counters[ActivePeerSelectionCounter.AllNonActiveCandidates] = _currentSelection.PreCandidates.Count; foreach (Peer preCandidate in _currentSelection.PreCandidates) { if (preCandidate.Node.Port == 0) { _currentSelection.Counters[ActivePeerSelectionCounter.FilteredByZeroPort]++; continue; } var delayResult = _stats.IsConnectionDelayed(preCandidate.Node); if (delayResult.Result) { if (delayResult.DelayReason == NodeStatsEventType.Disconnect) { _currentSelection.Counters[ActivePeerSelectionCounter.FilteredByDisconnect]++; } else if (delayResult.DelayReason == NodeStatsEventType.ConnectionFailed) { _currentSelection.Counters[ActivePeerSelectionCounter.FilteredByFailedConnection]++; } continue; } if (_stats.FindCompatibilityValidationResult(preCandidate.Node).HasValue) { _currentSelection.Incompatible.Add(preCandidate); continue; } if (!PeerIsDisconnected(preCandidate)) { // in transition continue; } _currentSelection.Candidates.Add(preCandidate); } if (!hasOnlyStaticNodes) { _currentSelection.Candidates.AddRange(_staticNodes.Values); } _currentSelection.Candidates.Sort(_peerComparer); }
private void SelectAndRankCandidates() { if (AvailableActivePeersCount <= 0) { return; } _currentSelection.PreCandidates.Clear(); _currentSelection.Candidates.Clear(); _currentSelection.Incompatible.Clear(); for (int i = 0; i < _enumValues.Length; i++) { _currentSelection.Counters[_enumValues[i]] = 0; } foreach ((_, Peer peer) in _peerPool.AllPeers) { // node can be connected but a candidate (for some short times) // [describe when] // node can be active but not connected (for some short times between sending connection request and // establishing a session) if (peer.IsAwaitingConnection || IsConnected(peer) || _activePeers.TryGetValue(peer.Node.Id, out _)) { continue; } if (peer.Node.Port > 65535) { continue; } _currentSelection.PreCandidates.Add(peer); } bool hasOnlyStaticNodes = false; List <Peer> staticPeers = _peerPool.StaticPeers; if (!_currentSelection.PreCandidates.Any() && staticPeers.Any()) { _currentSelection.Candidates.AddRange(staticPeers.Where(sn => !_activePeers.ContainsKey(sn.Node.Id))); hasOnlyStaticNodes = true; } if (!_currentSelection.PreCandidates.Any() && !hasOnlyStaticNodes) { return; } _currentSelection.Counters[ActivePeerSelectionCounter.AllNonActiveCandidates] = _currentSelection.PreCandidates.Count; foreach (Peer preCandidate in _currentSelection.PreCandidates) { if (preCandidate.Node.Port == 0) { _currentSelection.Counters[ActivePeerSelectionCounter.FilteredByZeroPort]++; continue; } (bool Result, NodeStatsEventType? DelayReason)delayResult = _stats.IsConnectionDelayed(preCandidate.Node); if (delayResult.Result) { if (delayResult.DelayReason == NodeStatsEventType.Disconnect) { _currentSelection.Counters[ActivePeerSelectionCounter.FilteredByDisconnect]++; } else if (delayResult.DelayReason == NodeStatsEventType.ConnectionFailed) { _currentSelection.Counters[ActivePeerSelectionCounter.FilteredByFailedConnection]++; } continue; } if (_stats.FindCompatibilityValidationResult(preCandidate.Node).HasValue) { _currentSelection.Incompatible.Add(preCandidate); continue; } if (IsConnected(preCandidate)) { // in transition continue; } _currentSelection.Candidates.Add(preCandidate); } if (!hasOnlyStaticNodes) { _currentSelection.Candidates.AddRange(staticPeers.Where(sn => !_activePeers.ContainsKey(sn.Node.Id))); } _currentSelection.Candidates.Sort(_peerComparer); }
private (IReadOnlyCollection <Peer> Candidates, IDictionary <ActivePeerSelectionCounter, int> Counters, IReadOnlyCollection <Peer> IncompatiblePeers) SelectAndRankCandidates() { var counters = Enum.GetValues(typeof(ActivePeerSelectionCounter)).OfType <ActivePeerSelectionCounter>().ToDictionary(x => x, y => 0); var availableActiveCount = _networkConfig.ActivePeersMaxCount - _activePeers.Count; if (availableActiveCount <= 0) { return(Array.Empty <Peer>(), counters, Array.Empty <Peer>()); } var candidatesSnapshot = _candidatePeers.Where(x => !_activePeers.ContainsKey(x.Key)).ToArray(); if (!candidatesSnapshot.Any()) { return(Array.Empty <Peer>(), counters, Array.Empty <Peer>()); } counters[ActivePeerSelectionCounter.AllNonActiveCandidates] = candidatesSnapshot.Length; List <Peer> candidates = new List <Peer>(); List <Peer> incompatiblePeers = new List <Peer>(); for (int i = 0; i < candidatesSnapshot.Length; i++) { var candidate = candidatesSnapshot[i]; if (candidate.Value.Node.Port == 0) { counters[ActivePeerSelectionCounter.FilteredByZeroPort] = counters[ActivePeerSelectionCounter.FilteredByZeroPort] + 1; continue; } var delayResult = _stats.IsConnectionDelayed(candidate.Value.Node); if (delayResult.Result) { if (delayResult.DelayReason == NodeStatsEventType.Disconnect) { counters[ActivePeerSelectionCounter.FilteredByDisconnect] = counters[ActivePeerSelectionCounter.FilteredByDisconnect] + 1; } else if (delayResult.DelayReason == NodeStatsEventType.ConnectionFailed) { counters[ActivePeerSelectionCounter.FilteredByFailedConnection] = counters[ActivePeerSelectionCounter.FilteredByFailedConnection] + 1; } continue; } if (_stats.FindCompatibilityValidationResult(candidate.Value.Node).HasValue) { incompatiblePeers.Add(candidate.Value); continue; } if (!PeerIsDisconnected(candidate.Value)) { // in transition continue; } candidates.Add(candidate.Value); } return(candidates.OrderBy(x => x.Node.IsTrusted).ThenByDescending(x => _stats.GetCurrentReputation(x.Node)).ToList(), counters, incompatiblePeers); }