예제 #1
0
        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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        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);
        }