public void IsPeerBlackListed_Test()
        {
            var host = "12.34.56.67";

            _peerPool.IsPeerBlackListed(host).ShouldBeFalse();
            _blackListProvider.AddHostToBlackList(host, NetworkConstants.DefaultPeerRemovalSeconds);
            _peerPool.IsPeerBlackListed(host).ShouldBeTrue();
        }
        private async Task <GrpcPeer> GetDialedPeerWithEndpointAsync(DnsEndPoint endpoint)
        {
            var peer = _peerPool.FindPeerByEndpoint(endpoint);

            if (peer != null)
            {
                if (peer.IsInvalid)
                {
                    _peerPool.RemovePeer(peer.Info.Pubkey);
                    await peer.DisconnectAsync(false);
                }
                else
                {
                    Logger.LogWarning($"Peer with endpoint {endpoint} is already in the pool.");
                    return(null);
                }
            }

            if (_peerPool.IsPeerBlackListed(endpoint.Host))
            {
                Logger.LogDebug($"Peer with endpoint {endpoint} is blacklisted.");
                return(null);
            }

            var dialedPeer = await _peerDialer.DialPeerAsync(endpoint);

            if (dialedPeer == null)
            {
                Logger.LogDebug($"Error dialing {endpoint}.");
                return(null);
            }

            return(dialedPeer);
        }
示例#3
0
        private async Task <GrpcPeer> GetDialedPeerWithEndpointAsync(DnsEndPoint endpoint)
        {
            if (_peerPool.FindPeerByEndpoint(endpoint) != null)
            {
                Logger.LogWarning($"Peer with endpoint {endpoint} is already in the pool.");
                return(null);
            }

            if (_peerPool.IsPeerBlackListed(endpoint.Host))
            {
                Logger.LogWarning($"Peer with endpoint {endpoint} is blacklisted.");
                return(null);
            }

            var dialedPeer = await _peerDialer.DialPeerAsync(endpoint);

            if (dialedPeer == null)
            {
                Logger.LogWarning($"Error dialing {endpoint}.");
                return(null);
            }

            return(dialedPeer);
        }
示例#4
0
        /// <summary>
        /// Connects to a node with the given ip address and adds it to the node's peer pool.
        /// </summary>
        /// <param name="endpoint">the ip address of the distant node</param>
        /// <returns>True if the connection was successful, false otherwise</returns>
        public async Task <bool> ConnectAsync(DnsEndPoint endpoint)
        {
            Logger.LogDebug($"Attempting to reach {endpoint}.");

            if (_peerPool.FindPeerByEndpoint(endpoint) != null)
            {
                Logger.LogWarning($"Peer with endpoint {endpoint} is already in the pool.");
                return(false);
            }

            if (_peerPool.IsPeerBlackListed(endpoint.Host))
            {
                Logger.LogWarning($"Peer with endpoint {endpoint} is blacklisted.");
                return(false);
            }

            var dialedPeer = await _peerDialer.DialPeerAsync(endpoint);

            if (dialedPeer == null)
            {
                Logger.LogWarning($"Error dialing {endpoint}.");
                return(false);
            }

            var inboundPeer = _peerPool.FindPeerByPublicKey(dialedPeer.Info.Pubkey) as GrpcPeer;

            /* A connection already exists, this can happen when both peers dial each other at the same time. To make
             * sure both sides close the same connection, they both decide based on the times of the handshakes.
             * Scenario steps, chronologically:
             *  1) P1 (hsk_time: t1) --> dials P2 --and-- P1 <-- P2 dials (hsk_time: t2)
             *  2) P2 receives P1s dial with t1 (in the hsk) and add to the pool
             *  3) P1 receives P2s dial with and adds to pool
             *  4) both dials finish and find that the pool already contains the dialed node.
             * To resolve this situation, both peers will choose the connection that was initiated the earliest,
             * so either P1s dial or P2s. */

            GrpcPeer currentPeer = dialedPeer;

            if (inboundPeer != null)
            {
                Logger.LogWarning("Duplicate peer connection detected: " +
                                  $"{inboundPeer} ({inboundPeer.LastReceivedHandshakeTime}) " +
                                  $"vs {dialedPeer} ({dialedPeer.LastSentHandshakeTime}).");

                if (inboundPeer.LastReceivedHandshakeTime > dialedPeer.LastSentHandshakeTime)
                {
                    // we started the dial first, replace the inbound connection with the dialed
                    if (!_peerPool.TryReplace(inboundPeer.Info.Pubkey, inboundPeer, dialedPeer))
                    {
                        Logger.LogWarning("Replacing the inbound connection failed.");
                    }

                    await inboundPeer.DisconnectAsync(false);

                    Logger.LogWarning($"Replaced the inbound connection with the dialed peer {inboundPeer} .");
                }
                else
                {
                    // keep the inbound connection
                    await dialedPeer.DisconnectAsync(false);

                    currentPeer = inboundPeer;

                    Logger.LogWarning($"Disconnected dialed peer {dialedPeer}.");
                }
            }
            else
            {
                if (!_peerPool.TryAddPeer(dialedPeer))
                {
                    Logger.LogWarning($"Peer add to the failed {dialedPeer.Info.Pubkey}.");
                    await dialedPeer.DisconnectAsync(false);

                    return(false);
                }

                Logger.LogDebug($"Added to pool {dialedPeer.RemoteEndpoint} - {dialedPeer.Info.Pubkey}.");
            }

            try
            {
                await currentPeer.ConfirmHandshakeAsync();
            }
            catch (Exception e)
            {
                Logger.LogError(e, $"Confirm handshake error. Peer: {currentPeer.Info.Pubkey}.");
                _peerPool.RemovePeer(currentPeer.Info.Pubkey);
                await currentPeer.DisconnectAsync(false);

                throw;
            }

            currentPeer.IsConnected = true;
            currentPeer.SyncState   = SyncState.Syncing;

            Logger.LogInformation($"Connected to: {currentPeer.RemoteEndpoint} - {currentPeer.Info.Pubkey.Substring(0, 45)}" +
                                  $" - in-token {currentPeer.InboundSessionId?.ToHex()}, out-token {currentPeer.OutboundSessionId?.ToHex()}" +
                                  $" - LIB height {currentPeer.LastKnownLibHeight}" +
                                  $" - best chain [{currentPeer.CurrentBlockHeight}, {currentPeer.CurrentBlockHash}]");

            FireConnectionEvent(currentPeer);

            return(true);
        }