예제 #1
0
            public int Compare(Peer x, Peer y)
            {
                if (x == null)
                {
                    return(y == null ? 0 : 1);
                }

                if (y == null)
                {
                    return(-1);
                }

                int staticValue = -x.Node.IsStatic.CompareTo(y.Node.IsStatic);

                if (staticValue != 0)
                {
                    return(staticValue);
                }

                int trust = -x.Node.IsTrusted.CompareTo(y.Node.IsTrusted);

                if (trust != 0)
                {
                    return(trust);
                }

                int reputation = -_stats.GetCurrentReputation(x.Node).CompareTo(_stats.GetCurrentReputation(y.Node));

                return(reputation);
            }
예제 #2
0
        private async Task SetupPeerConnection(Peer peer)
        {
            // Can happen when In connection is received from the same peer and is initialized before we get here
            // In this case we do not initialize OUT connection
            if (!AddActivePeer(peer.Node.Id, peer, "upgrading candidate"))
            {
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Active peer was already added to collection: {peer.Node.Id}");
                }
                return;
            }

            Interlocked.Increment(ref _tryCount);
            Interlocked.Increment(ref _pending);
            bool result = await InitializePeerConnection(peer);

            // for some time we will have a peer in active that has no session assigned - analyze this?

            Interlocked.Decrement(ref _pending);
            if (_logger.IsTrace)
            {
                _logger.Trace($"Connecting to {_stats.GetCurrentReputation(peer.Node)} rep node - {result}, ACTIVE: {_activePeers.Count}, CAND: {_peerPool.CandidatePeerCount}");
            }

            if (!result)
            {
                _stats.ReportEvent(peer.Node, NodeStatsEventType.ConnectionFailed);
                Interlocked.Increment(ref _failedInitialConnect);
                if (peer.OutSession != null)
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Timeout, doing additional disconnect: {peer.Node.Id}");
                    }
                    peer.OutSession?.MarkDisconnected(DisconnectReason.ReceiveMessageTimeout, DisconnectType.Local, "timeout");
                }

                peer.IsAwaitingConnection = false;
                DeactivatePeerIfDisconnected(peer, "Failed to initialize connections");
                return;
            }

            Interlocked.Increment(ref _newActiveNodes);
        }
예제 #3
0
        public void Can_sort_by_Reputation()
        {
            Node a     = new Node(TestItem.PublicKeyA, "127.0.0.1", 30303);
            Peer peerA = new Peer(a);

            Node b     = new Node(TestItem.PublicKeyB, "127.0.0.1", 30303);
            Peer peerB = new Peer(b);

            Node c     = new Node(TestItem.PublicKeyC, "127.0.0.1", 30303);
            Peer peerC = new Peer(c);

            _statsManager.GetCurrentReputation(a).Returns(100);
            _statsManager.GetCurrentReputation(b).Returns(50);
            _statsManager.GetCurrentReputation(c).Returns(200);

            Assert.AreEqual(-1, _comparer.Compare(peerA, peerB));
            Assert.AreEqual(1, _comparer.Compare(peerA, peerC));
            Assert.AreEqual(1, _comparer.Compare(peerB, peerC));
            Assert.AreEqual(0, _comparer.Compare(peerA, peerA));
            Assert.AreEqual(0, _comparer.Compare(peerB, peerB));
            Assert.AreEqual(0, _comparer.Compare(peerC, peerC));
        }
예제 #4
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);
        }