예제 #1
0
        /// <inheritdoc/>
        public void PeerConnected(IPEndPoint endpoint, DateTimeOffset peerConnectedAt)
        {
            PeerAddress peer = this.FindPeer(endpoint);

            peer?.SetConnected(peerConnectedAt);
        }
예제 #2
0
        /// <inheritdoc/>
        public void PeerDiscoveredFrom(IPEndPoint endpoint, DateTime peerDiscoveredFrom)
        {
            PeerAddress peer = this.FindPeer(endpoint);

            peer?.SetDiscoveredFrom(peerDiscoveredFrom);
        }
        public override async Task OnConnectAsync()
        {
            this.logger.LogTrace("()");

            int peerSelectionFailed = 0;

            PeerAddress peer = null;

            while (!this.nodeLifetime.ApplicationStopping.IsCancellationRequested)
            {
                if (peerSelectionFailed > MaximumPeerSelectionAttempts)
                {
                    peerSelectionFailed = 0;
                    peer = null;

                    this.logger.LogTrace("Peer selection failed, maximum amount of selection attempts reached.");
                    break;
                }

                peer = this.peerAddressManager.PeerSelector.SelectPeer();
                if (peer == null)
                {
                    peerSelectionFailed++;
                    continue;
                }

                if (!peer.Endpoint.Address.IsValid())
                {
                    this.logger.LogTrace("Peer selection failed, peer endpoint is not valid '{0}'.", peer.Endpoint);
                    peerSelectionFailed++;
                    continue;
                }

                // If the peer is already connected just continue.
                if (this.IsPeerConnected(peer.Endpoint))
                {
                    this.logger.LogTrace("Peer selection failed, peer is already connected '{0}'.", peer.Endpoint);
                    peerSelectionFailed++;
                    continue;
                }

                // If the peer exists in the -addnode collection don't
                // try and connect to it.
                var peerExistsInAddNode = this.ConnectionSettings.AddNode.Any(p => p.MapToIpv6().Match(peer.Endpoint));
                if (peerExistsInAddNode)
                {
                    this.logger.LogTrace("Peer selection failed, peer exists in -addnode args '{0}'.", peer.Endpoint);
                    peerSelectionFailed++;
                    continue;
                }

                // If the peer exists in the -connect collection don't
                // try and connect to it.
                var peerExistsInConnectNode = this.ConnectionSettings.Connect.Any(p => p.MapToIpv6().Match(peer.Endpoint));
                if (peerExistsInConnectNode)
                {
                    this.logger.LogTrace("Peer selection failed, peer exists in -connect args '{0}'.", peer.Endpoint);
                    peerSelectionFailed++;
                    continue;
                }

                break;
            }

            //If the peer selector returns nothing, we wait 2 seconds to
            //effectively override the connector's burst mode.
            if (peer == null)
            {
                this.logger.LogTrace("Peer selection failed, executing selection delay...");
                await Task.Delay(2000, this.nodeLifetime.ApplicationStopping).ConfigureAwait(false);
            }
            else
            {
                await this.ConnectAsync(peer).ConfigureAwait(false);
            }

            this.logger.LogTrace("(-)");
        }
        /// <summary>Attempts to connect to a random peer.</summary>
        internal async Task ConnectAsync(PeerAddress peerAddress)
        {
            this.logger.LogTrace("({0}:'{1}')", nameof(peerAddress), peerAddress.Endpoint);

            if (this.selfEndpointTracker.IsSelf(peerAddress.Endpoint))
            {
                this.logger.LogTrace("{0} is self. Therefore not connecting.", peerAddress.Endpoint);
                this.logger.LogTrace("(-)");
                return;
            }

            // Connect if local, ip range filtering disabled or ip range filtering enabled and peer in a different group.
            if (peerAddress.Endpoint.Address.IsRoutable(false) && this.ConnectionSettings.IpRangeFiltering && this.PeerIsPartOfExistingGroup(peerAddress))
            {
                this.logger.LogTrace("(-)[RANGE_FILTERED]");
                return;
            }

            INetworkPeer peer = null;

            try
            {
                using (CancellationTokenSource timeoutTokenSource = CancellationTokenSource.CreateLinkedTokenSource(this.nodeLifetime.ApplicationStopping))
                {
                    this.peerAddressManager.PeerAttempted(peerAddress.Endpoint, this.dateTimeProvider.GetUtcNow());

                    NetworkPeerConnectionParameters clonedConnectParamaters = this.CurrentParameters.Clone();
                    timeoutTokenSource.CancelAfter(5000);
                    clonedConnectParamaters.ConnectCancellation = timeoutTokenSource.Token;

                    peer = await this.networkPeerFactory.CreateConnectedNetworkPeerAsync(peerAddress.Endpoint, clonedConnectParamaters, this.networkPeerDisposer).ConfigureAwait(false);

                    await peer.VersionHandshakeAsync(this.Requirements, timeoutTokenSource.Token).ConfigureAwait(false);

                    this.AddPeer(peer);
                }
            }
            catch (OperationCanceledException)
            {
                if (this.nodeLifetime.ApplicationStopping.IsCancellationRequested)
                {
                    this.logger.LogDebug("Peer {0} connection canceled because application is stopping.", peerAddress.Endpoint);
                    peer?.Disconnect("Application stopping");
                }
                else
                {
                    this.logger.LogDebug("Peer {0} connection timeout.", peerAddress.Endpoint);
                    peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                    peer?.Disconnect("Connection timeout");
                }
            }
            catch (NBitcoin.Protocol.ProtocolException)
            {
                this.logger.LogDebug("Handshake rejected by peer '{0}'.", peerAddress.Endpoint);
                peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                peer?.Disconnect("Error while handshaking");
            }
            catch (Exception exception)
            {
                this.logger.LogTrace("Exception occurred while connecting: {0}", exception.ToString());
                peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                peer?.Disconnect("Error while connecting", exception);
            }

            this.logger.LogTrace("(-)");
        }
예제 #5
0
        /// <inheritdoc/>
        public override async Task OnConnectAsync()
        {
            int peerSelectionFailed = 0;

            PeerAddress peer = null;

            while (!this.NodeLifetime.ApplicationStopping.IsCancellationRequested)
            {
                if (peerSelectionFailed > MaximumPeerSelectionAttempts)
                {
                    peerSelectionFailed = 0;
                    peer = null;

                    this.logger.LogTrace("Selection failed, maximum amount of selection attempts reached.");
                    break;
                }

                peer = this.PeerAddressManager.PeerSelector.SelectPeer();
                if (peer == null)
                {
                    this.logger.LogTrace("Selection failed, selector returned nothing.");
                    peerSelectionFailed++;
                    continue;
                }

                if (!peer.Endpoint.Address.IsValid())
                {
                    this.logger.LogTrace("Selection failed, peer endpoint is not valid '{0}'.", peer.Endpoint);
                    peerSelectionFailed++;
                    continue;
                }

                // If the peer exists in the -addnode collection don't
                // try and connect to it.
                bool peerExistsInAddNode = this.ConnectionSettings.AddNode.Any(p => p.MapToIpv6().Match(peer.Endpoint));
                if (peerExistsInAddNode)
                {
                    this.logger.LogTrace("Selection failed, peer exists in -addnode args '{0}'.", peer.Endpoint);
                    peerSelectionFailed++;
                    continue;
                }

                // If the peer exists in the -connect collection don't
                // try and connect to it.
                bool peerExistsInConnectNode = this.ConnectionSettings.Connect.Any(p => p.MapToIpv6().Match(peer.Endpoint));
                if (peerExistsInConnectNode)
                {
                    this.logger.LogTrace("Selection failed, peer exists in -connect args '{0}'.", peer.Endpoint);
                    peerSelectionFailed++;
                    continue;
                }

                break;
            }

            // If the peer selector returns nothing, we wait 2 seconds to
            // effectively override the connector's initial connection interval.
            if (peer == null)
            {
                this.logger.LogTrace("Selection failed, executing selection delay.");
                await Task.Delay(2000, this.NodeLifetime.ApplicationStopping).ConfigureAwait(false);
            }
            else
            {
                // Connect if local, ip range filtering disabled or ip range filtering enabled and peer in a different group.
                if (peer.Endpoint.Address.IsRoutable(false) && this.ConnectionSettings.IpRangeFiltering && this.PeerIsPartOfExistingGroup(peer))
                {
                    this.logger.LogTrace("(-)[RANGE_FILTERED]");
                    return;
                }

                this.logger.LogDebug("Attempting connection to {0}.", peer.Endpoint);

                await this.ConnectAsync(peer).ConfigureAwait(false);
            }
        }
예제 #6
0
        /// <inheritdoc/>
        public void PeerSeen(IPEndPoint endpoint, DateTime peerSeenAt)
        {
            PeerAddress peer = this.FindPeer(endpoint);

            peer?.SetLastSeen(peerSeenAt);
        }
예제 #7
0
        /// <inheritdoc/>
        public void PeerHandshaked(IPEndPoint endpoint, DateTimeOffset peerHandshakedAt)
        {
            PeerAddress peer = this.FindPeer(endpoint);

            peer?.SetHandshaked(peerHandshakedAt);
        }
예제 #8
0
 private bool IsBanned(PeerAddress peerAddress)
 {
     return(peerAddress.BanUntil > this.dateTimeProvider.GetUtcNow());
 }
예제 #9
0
        /// <summary>Attempts to connect to a random peer.</summary>
        public async Task ConnectAsync(PeerAddress peerAddress)
        {
            if (this.selfEndpointTracker.IsSelf(peerAddress.Endpoint))
            {
                this.logger.LogDebug("Connect aborted: {0} is self.", peerAddress.Endpoint);
                return;
            }

            if (this.IsPeerConnected(peerAddress.Endpoint))
            {
                this.logger.LogDebug("Connect aborted: {0} is already connected.", peerAddress.Endpoint);
                return;
            }

            if (peerAddress.IsBanned(this.dateTimeProvider.GetUtcNow()))
            {
                this.logger.LogDebug("Connect aborted: {0} is banned until {1}.", peerAddress.Endpoint, peerAddress.BanUntil);
                return;
            }

            INetworkPeer peer = null;

            try
            {
                using (CancellationTokenSource timeoutTokenSource = CancellationTokenSource.CreateLinkedTokenSource(this.NodeLifetime.ApplicationStopping))
                {
                    this.PeerAddressManager.PeerAttempted(peerAddress.Endpoint, this.dateTimeProvider.GetUtcNow());

                    NetworkPeerConnectionParameters clonedConnectParamaters = this.CurrentParameters.Clone();
                    timeoutTokenSource.CancelAfter(5000);
                    clonedConnectParamaters.ConnectCancellation = timeoutTokenSource.Token;

                    peer = await this.networkPeerFactory.CreateConnectedNetworkPeerAsync(peerAddress.Endpoint, clonedConnectParamaters, this.networkPeerDisposer).ConfigureAwait(false);

                    await peer.VersionHandshakeAsync(this.Requirements, timeoutTokenSource.Token).ConfigureAwait(false);

                    this.AddPeer(peer);
                }
            }
            catch (OperationCanceledException)
            {
                if (this.NodeLifetime.ApplicationStopping.IsCancellationRequested)
                {
                    this.logger.LogDebug("Peer {0} connection canceled because application is stopping.", peerAddress.Endpoint);
                    peer?.Disconnect("Application stopping");
                }
                else
                {
                    this.logger.LogDebug("Peer {0} connection timeout.", peerAddress.Endpoint);
                    peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                    peer?.Disconnect("Connection timeout");
                }
            }
            catch (NBitcoin.Protocol.ProtocolException)
            {
                this.logger.LogDebug("Handshake rejected by peer '{0}'.", peerAddress.Endpoint);
                peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                peer?.Disconnect("Error while handshaking");
            }
            catch (Exception exception)
            {
                this.logger.LogDebug("Exception occurred while connecting: {0}", exception is SocketException ? exception.Message : exception.ToString());
                peerAddress.SetHandshakeAttempted(this.dateTimeProvider.GetUtcNow());
                peer?.Disconnect("Error while connecting", exception);
            }
        }