Exemple #1
0
        /// <summary>
        /// Initializes an instance of the object.
        /// </summary>
        /// <param name="network">Specification of the network the node runs on - regtest/testnet/mainnet.</param>
        /// <param name="peer">Network peer the node is connected to, or will connect to.</param>
        /// <param name="client">Initialized TCP client, which may or may not be already connected.</param>
        /// <param name="clientId">Unique identifier of the connection.</param>
        /// <param name="processMessageAsync">Callback to be called when a new message arrives from the peer.</param>
        /// <param name="dateTimeProvider">Provider of time functions.</param>
        /// <param name="loggerFactory">Factory for creating loggers.</param>
        public NetworkPeerConnection(Network network, NetworkPeer peer, TcpClient client, int clientId, ProcessMessageAsync <IncomingMessage> processMessageAsync, IDateTimeProvider dateTimeProvider, ILoggerFactory loggerFactory)
        {
            this.loggerFactory = loggerFactory;
            this.logger        = this.loggerFactory.CreateLogger(this.GetType().FullName, $"[{clientId}-{peer.PeerAddress.Endpoint}] ");

            this.network          = network;
            this.dateTimeProvider = dateTimeProvider;

            this.peer = peer;
            this.setPeerStateOnShutdown = NetworkPeerState.Offline;
            this.tcpClient = client;
            this.Id        = clientId;

            this.stream           = this.tcpClient.Connected ? this.tcpClient.GetStream() : null;
            this.ShutdownComplete = new TaskCompletionSource <bool>();

            this.writeLock = new AsyncLock();

            this.CancellationSource = new CancellationTokenSource();

            this.MessageProducer             = new MessageProducer <IncomingMessage>();
            this.messageListener             = new CallbackMessageListener <IncomingMessage>(processMessageAsync);
            this.messageProducerRegistration = this.MessageProducer.AddMessageListener(this.messageListener);
        }
Exemple #2
0
 public NetworkPeerEventArgs(NetworkPeer peer, bool added)
 {
     this.Added = added;
     this.peer  = peer;
 }
 public NetworkPeerListener(NetworkPeer peer)
 {
     this.subscription = peer.MessageProducer.AddMessageListener(this);
     this.Peer         = peer;
 }
        /// <summary>
        /// Implements loop accepting connections from newly connected clients.
        /// </summary>
        private async Task AcceptClientsAsync()
        {
            this.logger.LogTrace("()");

            this.logger.LogTrace("Accepting incoming connections.");

            try
            {
                while (!this.serverCancel.IsCancellationRequested)
                {
                    // Used to record any errors occurring in the thread pool task.
                    Exception error = null;

                    TcpClient tcpClient = await Task.Run(() =>
                    {
                        try
                        {
                            Task <TcpClient> acceptTask = this.tcpListener.AcceptTcpClientAsync();
                            acceptTask.Wait(this.serverCancel.Token);
                            return(acceptTask.Result);
                        }
                        catch (Exception e)
                        {
                            // Record the error.
                            error = e;
                            return(null);
                        }
                    }).ConfigureAwait(false);

                    // Raise the error.
                    if (error != null)
                    {
                        throw error;
                    }

                    NetworkPeerClient client = this.networkPeerFactory.CreateNetworkPeerClient(tcpClient);

                    this.logger.LogTrace("Connection accepted from client '{0}'.", client.RemoteEndPoint);

                    var peerAddress = new NetworkAddress()
                    {
                        Endpoint = client.RemoteEndPoint,
                        Time     = this.dateTimeProvider.GetUtcNow()
                    };

                    NetworkPeer networkPeer = this.networkPeerFactory.CreateNetworkPeer(peerAddress, this.Network, client, this.CreateNetworkPeerConnectionParameters());

                    this.ConnectedNetworkPeers.Add(networkPeer);
                    networkPeer.StateChanged += this.Peer_StateChanged;

                    this.AddConnectedClient(client);
                }
            }
            catch (OperationCanceledException)
            {
                this.logger.LogDebug("Shutdown detected, stop accepting connections.");
            }
            catch (Exception e)
            {
                this.logger.LogDebug("Exception occurred: {0}", e.ToString());
            }

            this.logger.LogTrace("(-)");
        }
Exemple #5
0
        private void ProcessMessageCore(IncomingMessage message)
        {
            if (message.Message.Payload is VersionPayload)
            {
                VersionPayload version         = message.AssertPayload <VersionPayload>();
                bool           connectedToSelf = version.Nonce == this.Nonce;
                if ((message.NetworkPeer != null) && connectedToSelf)
                {
                    NodeServerTrace.ConnectionToSelfDetected();
                    message.NetworkPeer.DisconnectAsync();
                    return;
                }

                if (message.NetworkPeer == null)
                {
                    IPEndPoint remoteEndpoint = version.AddressFrom;
                    if (!remoteEndpoint.Address.IsRoutable(this.AllowLocalPeers))
                    {
                        // Send his own endpoint.
                        remoteEndpoint = new IPEndPoint(((IPEndPoint)message.Socket.RemoteEndPoint).Address, this.Network.DefaultPort);
                    }

                    var peerAddress = new NetworkAddress()
                    {
                        Endpoint = remoteEndpoint,
                        Time     = DateTimeOffset.UtcNow
                    };

                    NetworkPeer networkPeer = this.networkPeerFactory.CreateNetworkPeer(peerAddress, this.Network, CreateNetworkPeerConnectionParameters(), message.Socket, version);
                    if (connectedToSelf)
                    {
                        networkPeer.SendMessage(CreateNetworkPeerConnectionParameters().CreateVersion(networkPeer.PeerAddress.Endpoint, this.Network));
                        NodeServerTrace.ConnectionToSelfDetected();
                        networkPeer.Disconnect();
                        return;
                    }

                    CancellationTokenSource cancel = new CancellationTokenSource();
                    cancel.CancelAfter(TimeSpan.FromSeconds(10.0));
                    try
                    {
                        this.ConnectedNetworkPeers.Add(networkPeer);
                        networkPeer.StateChanged += Peer_StateChanged;
                        networkPeer.RespondToHandShake(cancel.Token);
                    }
                    catch (OperationCanceledException ex)
                    {
                        NodeServerTrace.Error("The remote peer did not respond fast enough (10 seconds) to the handshake completion, dropping connection", ex);
                        networkPeer.DisconnectAsync();
                        throw;
                    }
                    catch (Exception)
                    {
                        networkPeer.DisconnectAsync();
                        throw;
                    }
                }
            }

            this.MessageReceived?.Invoke(this, message);
        }
Exemple #6
0
 /// <summary>
 /// Initializes the instance of the object and subscribes to the peer's message producer.
 /// </summary>
 /// <param name="peer">Connected network peer that we receive messages from.</param>
 public NetworkPeerListener(NetworkPeer peer)
 {
     this.asyncQueue = new AsyncQueue <IncomingMessage>();
     this.messageProducerRegistration = peer.MessageProducer.AddMessageListener(this);
     this.peer = peer;
 }
        /// <summary>
        /// Processes a new message received from a connected client peer.
        /// </summary>
        /// <param name="message">Message received from the client.</param>
        private void ProcessMessageCore(IncomingMessage message)
        {
            this.logger.LogTrace("({0}:'{1}')", nameof(message), message.Message.Command);

            if (message.Message.Payload is VersionPayload)
            {
                VersionPayload version         = message.AssertPayload <VersionPayload>();
                bool           connectedToSelf = version.Nonce == this.Nonce;

                if (connectedToSelf)
                {
                    this.logger.LogDebug("Connection to self detected and will be aborted.");
                }

                if ((message.NetworkPeer != null) && connectedToSelf)
                {
                    message.NetworkPeer.DisconnectWithException();

                    this.logger.LogTrace("(-)[CONNECTED_TO_SELF]");
                    return;
                }

                if (message.NetworkPeer == null)
                {
                    this.logger.LogDebug("First message received from peer '{0}'.", version.AddressFrom);

                    IPEndPoint remoteEndpoint = version.AddressFrom;
                    if (!remoteEndpoint.Address.IsRoutable(this.AllowLocalPeers))
                    {
                        // Send his own endpoint.
                        remoteEndpoint = new IPEndPoint(((IPEndPoint)message.Socket.RemoteEndPoint).Address, this.Network.DefaultPort);
                    }

                    var peerAddress = new NetworkAddress()
                    {
                        Endpoint = remoteEndpoint,
                        Time     = this.dateTimeProvider.GetUtcNow()
                    };

                    NetworkPeer networkPeer = this.networkPeerFactory.CreateNetworkPeer(peerAddress, this.Network, CreateNetworkPeerConnectionParameters(), message.Socket, version);
                    if (connectedToSelf)
                    {
                        networkPeer.SendMessage(CreateNetworkPeerConnectionParameters().CreateVersion(networkPeer.PeerAddress.Endpoint, this.Network, this.dateTimeProvider.GetTimeOffset()));
                        networkPeer.Disconnect();

                        this.logger.LogTrace("(-)[CONNECTED_TO_SELF_2]");
                        return;
                    }

                    using (CancellationTokenSource cancel = new CancellationTokenSource())
                    {
                        cancel.CancelAfter(TimeSpan.FromSeconds(10.0));
                        try
                        {
                            this.ConnectedNetworkPeers.Add(networkPeer);
                            networkPeer.StateChanged += Peer_StateChanged;
                            networkPeer.RespondToHandShake(cancel.Token);
                        }
                        catch (OperationCanceledException)
                        {
                            this.logger.LogTrace("Remote peer haven't responded within 10 seconds of the handshake completion, dropping connection.");

                            networkPeer.DisconnectWithException();

                            this.logger.LogTrace("(-)[HANDSHAKE_TIMEDOUT]");
                            throw;
                        }
                        catch (Exception ex)
                        {
                            this.logger.LogTrace("Exception occurred: {0}", ex.ToString());

                            networkPeer.DisconnectWithException();

                            this.logger.LogTrace("(-)[HANDSHAKE_EXCEPTION]");
                            throw;
                        }
                    }
                }
            }

            this.logger.LogTrace("(-)");
        }