Exemple #1
0
        public void Listen()
        {
            if (socket != null)
            {
                throw new InvalidOperationException("Already listening");
            }
            using (_Trace.Open())
            {
                try
                {
                    socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
#if !NOIPDUALMODE
                    socket.DualMode = true;
#endif

                    socket.Bind(LocalEndpoint);
                    socket.Listen(8);
                    NodeServerTrace.Information("Listening...");
                    BeginAccept();
                }
                catch (Exception ex)
                {
                    NodeServerTrace.Error("Error while opening the Protocol server", ex);
                    throw;
                }
            }
        }
Exemple #2
0
        public void Listen()
        {
            if (socket != null)
            {
                throw new InvalidOperationException("Already listening");
            }
            using (_Trace.Open())
            {
                try
                {
                    socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);
                    socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);

                    socket.Bind(LocalEndpoint);
                    socket.Listen(8);
                    NodeServerTrace.Information("Listening...");
                    BeginAccept();
                }
                catch (Exception ex)
                {
                    NodeServerTrace.Error("Error while opening the Protocol server", ex);
                    throw;
                }
            }
        }
Exemple #3
0
 public void DisconnectAsync(string reason, Exception exception = null)
 {
     if (!IsConnected)
     {
         return;
     }
     if (Interlocked.CompareExchange(ref _Disconnecting, 1, 0) == 1)
     {
         return;
     }
     using (TraceCorrelation.Open())
     {
         NodeServerTrace.Information("Disconnection request " + reason);
         State = NodeState.Disconnecting;
         _Connection.Cancel.Cancel();
         if (DisconnectReason == null)
         {
             DisconnectReason = new NodeDisconnectReason()
             {
                 Reason    = reason,
                 Exception = exception
             }
         }
         ;
     }
 }
Exemple #4
0
        public void VersionHandshake(CancellationToken cancellationToken = default(CancellationToken))
        {
            using (var listener = CreateListener()
                                  .Where(p => p.Message.Payload is VersionPayload ||
                                         p.Message.Payload is RejectPayload ||
                                         p.Message.Payload is VerAckPayload))
            {
                using (TraceCorrelation.Open())
                {
                    SendMessage(MyVersion);

                    var payload = listener.ReceivePayload <Payload>(cancellationToken);
                    if (payload is RejectPayload)
                    {
                        throw new InvalidOperationException("Handshake rejected : " + ((RejectPayload)payload).Reason);
                    }
                    var version = (VersionPayload)payload;
                    _PeerVersion = version;
                    Version      = version.Version;
                    if (!version.AddressReceiver.Address.Equals(MyVersion.AddressFrom.Address))
                    {
                        NodeServerTrace.Warning("Different external address detected by the node " + version.AddressReceiver.Address + " instead of " + MyVersion.AddressFrom.Address);
                    }
                    if (version.Version < ProtocolVersion.MIN_PEER_PROTO_VERSION)
                    {
                        NodeServerTrace.Warning("Outdated version " + version.Version + " disconnecting");
                        Disconnect();
                        return;
                    }
                    SendMessage(new VerAckPayload());
                    listener.ReceivePayload <VerAckPayload>(cancellationToken);
                    State = NodeState.HandShaked;
                }
            }
        }
Exemple #5
0
        public Chain BuildChain(Chain chain, CancellationToken cancellationToken = default(CancellationToken))
        {
            AssertState(NodeState.HandShaked, cancellationToken);
            using (TraceCorrelation.Open())
            {
                NodeServerTrace.Information("Building chain");
                if (FullVersion.StartHeight <= chain.Height)
                {
                    NodeServerTrace.Information("Local chain already ahead");
                    return(chain);
                }

                while (chain.Height < FullVersion.StartHeight)
                {
                    NodeServerTrace.Information("Chain progress : " + chain.Height + "/" + FullVersion.StartHeight);
                    SendMessage(new GetHeadersPayload()
                    {
                        BlockLocators = chain.Tip.GetLocator()
                    });
                    var headers = this.RecieveMessage <HeadersPayload>(cancellationToken);
                    foreach (var header in headers.Headers)
                    {
                        var prev = chain.GetBlock(header.HashPrevBlock);
                        if (prev == null || prev.Height != chain.Height)
                        {
                            NodeServerTrace.Error("Block Header received out of order " + header.GetHash(), null);
                            throw new InvalidOperationException("Block Header received out of order");
                        }
                        var chained = chain.CreateChainedBlock(header);
                        chain.SetTip(chained);
                    }
                }
            }
            return(chain);
        }
Exemple #6
0
 public void Listen()
 {
     if (socket != null)
     {
         throw new InvalidOperationException("Already listening");
     }
     using (_Trace.Open())
     {
         try
         {
             socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
             socket.Bind(LocalEndpoint);
             socket.Listen(8);
             NodeServerTrace.Information("Listening...");
             BeginAccept();
         }
         catch (Exception ex)
         {
             NodeServerTrace.Error("Error while opening the Protocol server", ex);
             throw;
         }
     }
 }
Exemple #7
0
            public void BeginListen()
            {
                new Thread(() =>
                {
                    using (TraceCorrelation.Open(false))
                    {
                        NodeServerTrace.Information("Listening");
                        _PingListener = new EventLoopMessageListener <IncomingMessage>(MessageReceived);
                        Node.MessageProducer.AddMessageListener(_PingListener);
                        try
                        {
                            while (!Cancel.Token.IsCancellationRequested)
                            {
                                PerformanceCounter counter;
                                var message = Message.ReadNext(Socket, Node.Network, Node.Version, Cancel.Token, out counter);

                                Node.LastSeen = DateTimeOffset.UtcNow;
                                Node.MessageProducer.PushMessage(new IncomingMessage()
                                {
                                    Message = message,
                                    Socket  = Socket,
                                    Node    = Node
                                });
                                Node.Counter.Add(counter);
                            }
                        }
                        catch (OperationCanceledException)
                        {
                        }
                        catch (Exception ex)
                        {
                            if (Node.State != NodeState.Disconnecting)
                            {
                                Node.State = NodeState.Failed;
                                NodeServerTrace.Error("Connection to server stopped unexpectedly", ex);
                            }
                        }
                        NodeServerTrace.Information("Stop listening");
                        if (Node.State != NodeState.Failed)
                        {
                            Node.State = NodeState.Offline;
                        }
                        Dispose();

                        _Cancel.Cancel();
                        _Disconnected.Set();
                    }
                }).Start();
            }
Exemple #8
0
 public void RespondToHandShake(CancellationToken cancellation = default(CancellationToken))
 {
     using (TraceCorrelation.Open())
     {
         var listener = new PollMessageListener <IncomingMessage>();
         using (MessageProducer.AddMessageListener(listener))
         {
             NodeServerTrace.Information("Responding to handshake");
             SendMessage(MyVersion);
             listener.ReceiveMessage().AssertPayload <VerAckPayload>();
             SendMessage(new VerAckPayload());
             _State = NodeState.HandShaked;
         }
     }
 }
Exemple #9
0
 public void Disconnect()
 {
     if (State < NodeState.Connected)
     {
         _Connection.Disconnected.WaitOne();
         return;
     }
     using (TraceCorrelation.Open())
     {
         NodeServerTrace.Information("Disconnection request");
         State = NodeState.Disconnecting;
         _Connection.Cancel.Cancel();
         _Connection.Disconnected.WaitOne();
     }
 }
Exemple #10
0
        public Chain BuildChain(ObjectStream <ChainChange> changes = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (changes == null)
            {
                changes = new StreamObjectStream <ChainChange>();
            }
            var chain = new Chain(Network, changes);
            TraceCorrelation trace = new TraceCorrelation(NodeServerTrace.Trace, "Build chain");

            using (trace.Open())
            {
                using (var pool = CreateNodeSet(3))
                {
                    int height   = pool.GetNodes().Max(o => o.FullVersion.StartHeight);
                    var listener = new PollMessageListener <IncomingMessage>();

                    pool.SendMessage(new GetHeadersPayload()
                    {
                        BlockLocators = chain.Tip.GetLocator()
                    });

                    using (pool.MessageProducer.AddMessageListener(listener))
                    {
                        while (chain.Height != height)
                        {
                            var before  = chain.Tip;
                            var headers = listener.RecieveMessage(cancellationToken).Message.Payload as HeadersPayload;
                            if (headers != null)
                            {
                                foreach (var header in headers.Headers)
                                {
                                    chain.GetOrAdd(header);
                                }
                                if (before.HashBlock != chain.Tip.HashBlock)
                                {
                                    NodeServerTrace.Information("Chain progress : " + chain.Height + "/" + height);
                                    pool.SendMessage(new GetHeadersPayload()
                                    {
                                        BlockLocators = chain.Tip.GetLocator()
                                    });
                                }
                            }
                        }
                    }
                }
            }
            return(chain);
        }
Exemple #11
0
        public IEnumerable <Block> GetBlocks(IEnumerable <uint256> neededBlocks, CancellationToken cancellationToken = default(CancellationToken))
        {
            AssertState(NodeState.HandShaked, cancellationToken);
            using (TraceCorrelation.Open())
            {
                NodeServerTrace.Information("Downloading blocks");
                int simultaneous = 70;
                PerformanceSnapshot lastSpeed = null;
                using (var listener = CreateListener()
                                      .OfType <BlockPayload>())
                {
                    foreach (var invs in neededBlocks
                             .Select(b => new InventoryVector()
                    {
                        Type = InventoryType.MSG_BLOCK,
                        Hash = b
                    })
                             .Partition(simultaneous))
                    {
                        NodeServerTrace.Information("Speed " + lastSpeed);
                        var begin = Counter.Snapshot();

                        var invsByHash = invs.ToDictionary(k => k.Hash);

                        this.SendMessage(new GetDataPayload(invs.ToArray()));

                        Block[] downloadedBlocks = new Block[invs.Count];
                        while (invsByHash.Count != 0)
                        {
                            var block    = listener.ReceivePayload <BlockPayload>(cancellationToken).Object;
                            var thisHash = block.GetHash();
                            if (invsByHash.ContainsKey(thisHash))
                            {
                                downloadedBlocks[invs.IndexOf(invsByHash[thisHash])] = block;
                                invsByHash.Remove(thisHash);
                            }
                        }
                        var end = Counter.Snapshot();
                        lastSpeed = end - begin;

                        foreach (var downloadedBlock in downloadedBlocks)
                        {
                            yield return(downloadedBlock);
                        }
                    }
                }
            }
        }
Exemple #12
0
        private void ProcessMessage(IncomingMessage message)
        {
            this.AllMessages.PushMessage(message);
            TraceCorrelation trace = null;

            if (message.NetworkPeer != null)
            {
                trace = message.NetworkPeer.TraceCorrelation;
            }
            else
            {
                trace = new TraceCorrelation(NodeServerTrace.Trace, "Processing inbound message " + message.Message);
            }

            using (trace.Open(false))
            {
                this.ProcessMessageCore(message);
            }
        }
Exemple #13
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cancellation"></param>
        public void RespondToHandShake(CancellationToken cancellation = default(CancellationToken))
        {
            using (TraceCorrelation.Open())
            {
                using (var list = CreateListener().Where(m => m.IsPayloadTypeOf(typeof(VerAckPayload), typeof(RejectPayload))))
                {
                    NodeServerTrace.Information("Responding to handshake");
                    SendMessageAsync(MyVersion);
                    var message = list.ReceiveMessage(cancellation);

                    message.IfPayloadIs <RejectPayload>(reject =>
                    {
                        throw new ProtocolException("Version rejected " + reject.Code + " : " + reject.Reason);
                    });
                    SendMessageAsync(new VerAckPayload());
                    State = NodeState.HandShaked;
                }
            }
        }
Exemple #14
0
        internal Node(Peer peer, Network network, VersionPayload myVersion, CancellationToken cancellation)
        {
            _MyVersion = myVersion;
            Version    = _MyVersion.Version;
            Network    = network;
            _Peer      = peer;
            LastSeen   = peer.NetworkAddress.Time;

            var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);

#if !NOIPDUALMODE
            socket.DualMode = true;
#endif
            _Connection = new NodeConnection(this, socket);
            using (TraceCorrelation.Open())
            {
                try
                {
                    var ar = socket.BeginConnect(Peer.NetworkAddress.Endpoint, null, null);
                    WaitHandle.WaitAny(new WaitHandle[] { ar.AsyncWaitHandle, cancellation.WaitHandle });
                    cancellation.ThrowIfCancellationRequested();
                    socket.EndConnect(ar);
                    State = NodeState.Connected;
                    NodeServerTrace.Information("Outbound connection successfull");
                }
                catch (OperationCanceledException)
                {
                    Utils.SafeCloseSocket(socket);
                    NodeServerTrace.Information("Connection to node cancelled");
                    State = NodeState.Offline;
                    return;
                }
                catch (Exception ex)
                {
                    Utils.SafeCloseSocket(socket);
                    NodeServerTrace.Error("Error connecting to the remote endpoint ", ex);
                    State = NodeState.Failed;
                    throw;
                }
                _Connection.BeginListen();
            }
        }
Exemple #15
0
        public void VersionHandshake(CancellationToken cancellationToken = default(CancellationToken))
        {
            var listener = new PollMessageListener <IncomingMessage>();

            using (MessageProducer.AddMessageListener(listener))
            {
                using (TraceCorrelation.Open())
                {
                    var myVersion = CreateVersionPayload();
                    SendMessage(myVersion);

                    var version = listener.RecieveMessage(cancellationToken).AssertPayload <VersionPayload>();
                    _FullVersion = version;
                    Version      = version.Version;
                    if (version.Nonce == NodeServer.Nonce)
                    {
                        NodeServerTrace.ConnectionToSelfDetected();
                        Disconnect();
                        throw new InvalidOperationException("Impossible to connect to self");
                    }

                    if (!version.AddressReciever.Address.Equals(ExternalEndpoint.Address))
                    {
                        NodeServerTrace.Warning("Different external address detected by the node " + version.AddressReciever.Address + " instead of " + ExternalEndpoint.Address);
                    }
                    NodeServer.ExternalAddressDetected(version.AddressReciever.Address);
                    if (version.Version < ProtocolVersion.MIN_PEER_PROTO_VERSION)
                    {
                        NodeServerTrace.Warning("Outdated version " + version.Version + " disconnecting");
                        Disconnect();
                        return;
                    }
                    SendMessage(new VerAckPayload());
                    listener.RecieveMessage(cancellationToken).AssertPayload <VerAckPayload>();
                    State = NodeState.HandShaked;
                    if (NodeServer.AdvertizeMyself)
                    {
                        AdvertiseMyself();
                    }
                }
            }
        }
Exemple #16
0
 public IEnumerable <ChainedBlock> GetHeadersFromFork(ChainedBlock currentTip,
                                                      uint256 hashStop = null,
                                                      CancellationToken cancellationToken = default(CancellationToken))
 {
     AssertState(NodeState.HandShaked, cancellationToken);
     using (TraceCorrelation.Open())
     {
         NodeServerTrace.Information("Building chain");
         using (var listener = this.CreateListener().OfType <HeadersPayload>())
         {
             while (true)
             {
                 SendMessage(new GetHeadersPayload()
                 {
                     BlockLocators = currentTip.GetLocator(),
                     HashStop      = hashStop
                 });
                 var headers = listener.ReceivePayload <HeadersPayload>(cancellationToken);
                 if (headers.Headers.Count == 0)
                 {
                     break;
                 }
                 foreach (var header in headers.Headers)
                 {
                     var prev = currentTip.FindAncestorOrSelf(header.HashPrevBlock);
                     if (prev == null)
                     {
                         NodeServerTrace.Error("Block Header received out of order " + header.GetHash(), null);
                         throw new InvalidOperationException("Block Header received out of order");
                     }
                     currentTip = new ChainedBlock(header, header.GetHash(), prev);
                     yield return(currentTip);
                 }
                 if (currentTip.HashBlock == hashStop)
                 {
                     break;
                 }
             }
         }
     }
 }
Exemple #17
0
        internal Node(NetworkAddress peer, NetworkInfo network, NodeConnectionParameters parameters)
        {
            parameters = parameters ?? new NodeConnectionParameters();
            var addrman = AddressManagerBehavior.GetAddrman(parameters);

            Inbound    = false;
            _Behaviors = new NodeBehaviorsCollection(this);
            _MyVersion = parameters.CreateVersion(peer.Endpoint, network);
            Network    = network;
            _Peer      = peer;
            LastSeen   = peer.Time;

            var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);

            socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);

            _Connection = new NodeConnection(this, socket);
            socket.ReceiveBufferSize = parameters.ReceiveBufferSize;
            socket.SendBufferSize    = parameters.SendBufferSize;
            using (TraceCorrelation.Open())
            {
                try
                {
                    var completed = new ManualResetEvent(false);
                    var args      = new SocketAsyncEventArgs();
                    args.RemoteEndPoint = peer.Endpoint;
                    args.Completed     += (s, a) =>
                    {
                        Utils.SafeSet(completed);
                    };
                    if (!socket.ConnectAsync(args))
                    {
                        completed.Set();
                    }
                    WaitHandle.WaitAny(new WaitHandle[] { completed, parameters.ConnectCancellation.WaitHandle });
                    parameters.ConnectCancellation.ThrowIfCancellationRequested();
                    if (args.SocketError != SocketError.Success)
                    {
                        throw new SocketException((int)args.SocketError);
                    }
                    var remoteEndpoint = (IPEndPoint)(socket.RemoteEndPoint ?? args.RemoteEndPoint);
                    _RemoteSocketAddress = remoteEndpoint.Address;
                    _RemoteSocketPort    = remoteEndpoint.Port;
                    State       = NodeState.Connected;
                    ConnectedAt = DateTimeOffset.UtcNow;
                    NodeServerTrace.Information("Outbound connection successfull");
                    if (addrman != null)
                    {
                        addrman.Attempt(Peer);
                    }
                }
                catch (OperationCanceledException)
                {
                    Utils.SafeCloseSocket(socket);
                    NodeServerTrace.Information("Connection to node cancelled");
                    State = NodeState.Offline;
                    if (addrman != null)
                    {
                        addrman.Attempt(Peer);
                    }
                    throw;
                }
                catch (Exception ex)
                {
                    Utils.SafeCloseSocket(socket);
                    NodeServerTrace.Error("Error connecting to the remote endpoint ", ex);
                    DisconnectReason = new NodeDisconnectReason()
                    {
                        Reason    = "Unexpected exception while connecting to socket",
                        Exception = ex
                    };
                    State = NodeState.Failed;
                    if (addrman != null)
                    {
                        addrman.Attempt(Peer);
                    }
                    throw;
                }
                InitDefaultBehaviors(parameters);
                _Connection.BeginListen();
            }
        }
Exemple #18
0
        public Chain BuildChain(ObjectStream<ChainChange> changes = null, CancellationToken cancellationToken = default(CancellationToken))
        {
            if(changes == null)
                changes = new StreamObjectStream<ChainChange>();
            var chain = new Chain(Network, changes);
            TraceCorrelation trace = new TraceCorrelation(NodeServerTrace.Trace, "Build chain");
            using(trace.Open())
            {
                using(var pool = CreateNodeSet(3))
                {
                    int height = pool.GetNodes().Max(o => o.FullVersion.StartHeight);
                    var listener = new PollMessageListener<IncomingMessage>();

                    pool.SendMessage(new GetHeadersPayload()
                    {
                        BlockLocators = chain.Tip.GetLocator()
                    });

                    using(pool.MessageProducer.AddMessageListener(listener))
                    {
                        while(chain.Height != height)
                        {
                            var before = chain.Tip;
                            var headers = listener.RecieveMessage(cancellationToken).Message.Payload as HeadersPayload;
                            if(headers != null)
                            {
                                foreach(var header in headers.Headers)
                                {
                                    chain.GetOrAdd(header);
                                }
                                if(before.HashBlock != chain.Tip.HashBlock)
                                {
                                    NodeServerTrace.Information("Chain progress : " + chain.Height + "/" + height);
                                    pool.SendMessage(new GetHeadersPayload()
                                    {
                                        BlockLocators = chain.Tip.GetLocator()
                                    });
                                }
                            }
                        }
                    }
                }
            }
            return chain;
        }
Exemple #19
0
        internal void DiscoverPeers(Network network, NodeConnectionParameters parameters, int peerToFind)
        {
            var traceCorrelation = new TraceCorrelation(NodeServerTrace.Trace, "Discovering nodes");
            var found            = 0;

            using (traceCorrelation.Open())
            {
                while (found < peerToFind)
                {
                    parameters.ConnectCancellation.ThrowIfCancellationRequested();
                    NodeServerTrace.PeerTableRemainingPeerToGet(-found + peerToFind);
                    var peers = new List <NetworkAddress>();
                    peers.AddRange(GetAddr());
                    if (peers.Count == 0)
                    {
                        PopulateTableWithDNSNodes(network, peers);
                        PopulateTableWithHardNodes(network, peers);
                        peers = new List <NetworkAddress>(peers.OrderBy(a => RandomUtils.GetInt32()));
                        if (peers.Count == 0)
                        {
                            return;
                        }
                    }


                    var peerTableFull = new CancellationTokenSource();
                    var loopCancel    = CancellationTokenSource
                                        .CreateLinkedTokenSource(peerTableFull.Token, parameters.ConnectCancellation).Token;
                    try
                    {
                        Parallel.ForEach(peers, new ParallelOptions
                        {
                            MaxDegreeOfParallelism = 5,
                            CancellationToken      = loopCancel
                        }, p =>
                        {
                            var timeout          = new CancellationTokenSource(TimeSpan.FromSeconds(5));
                            var cancelConnection =
                                CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, loopCancel);
                            Node n = null;
                            try
                            {
                                var param2 = parameters.Clone();
                                param2.ConnectCancellation = cancelConnection.Token;
                                var addrman = param2.TemplateBehaviors.Find <AddressManagerBehavior>();
                                param2.TemplateBehaviors.Clear();
                                param2.TemplateBehaviors.Add(addrman);
                                n = Node.Connect(network, p.Endpoint, param2);
                                n.VersionHandshake(cancelConnection.Token);
                                n.MessageReceived += (s, a) =>
                                {
                                    var addr = a.Message.Payload as AddrPayload;
                                    if (addr != null)
                                    {
                                        Interlocked.Add(ref found, addr.Addresses.Length);
                                        if (found >= peerToFind)
                                        {
                                            peerTableFull.Cancel();
                                        }
                                    }
                                };
                                n.SendMessageAsync(new GetAddrPayload());
                                loopCancel.WaitHandle.WaitOne(2000);
                            }
                            catch
                            {
                            }
                            finally
                            {
                                if (n != null)
                                {
                                    n.DisconnectAsync();
                                }
                            }

                            if (found >= peerToFind)
                            {
                                peerTableFull.Cancel();
                            }
                            else
                            {
                                NodeServerTrace.Information("Need " + (-found + peerToFind) + " more peers");
                            }
                        });
                    }
                    catch (OperationCanceledException)
                    {
                        if (parameters.ConnectCancellation.IsCancellationRequested)
                        {
                            throw;
                        }
                    }
                }
            }
        }
Exemple #20
0
        /// <summary>
        /// Fill the PeerTable with fresh addresses
        /// </summary>
        public void DiscoverPeers(int peerToFind = 990)
        {
            TraceCorrelation traceCorrelation = new TraceCorrelation(NodeServerTrace.Trace, "Discovering nodes");
            List <Task>      tasks            = new List <Task>();

            using (traceCorrelation.Open())
            {
                while (CountPeerRequired(peerToFind) != 0)
                {
                    NodeServerTrace.PeerTableRemainingPeerToGet(CountPeerRequired(peerToFind));
                    CancellationTokenSource cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(40));
                    var peers = PeerTable.GetActivePeers(1000);
                    if (peers.Length == 0)
                    {
                        PopulateTableWithDNSNodes();
                        PopulateTableWithHardNodes();
                        peers = PeerTable.GetActivePeers(1000);
                    }


                    CancellationTokenSource peerTableFull = new CancellationTokenSource();
                    NodeSet connected = new NodeSet();
                    try
                    {
                        Parallel.ForEach(peers, new ParallelOptions()
                        {
                            MaxDegreeOfParallelism = 5,
                            CancellationToken      = peerTableFull.Token,
                        }, p =>
                        {
                            Node n = null;
                            try
                            {
                                n = GetNodeByPeer(p, cancellation.Token);
                                if (n.State < NodeState.HandShaked)
                                {
                                    connected.AddNode(n);
                                    n.VersionHandshake(cancellation.Token);
                                }
                                n.SendMessage(new GetAddrPayload());
                                Thread.Sleep(2000);
                            }
                            catch (Exception)
                            {
                                if (n != null)
                                {
                                    n.Disconnect();
                                }
                            }
                            if (CountPeerRequired(peerToFind) == 0)
                            {
                                peerTableFull.Cancel();
                            }
                            else
                            {
                                NodeServerTrace.Information("Need " + CountPeerRequired(peerToFind) + " more peers");
                            }
                        });
                    }
                    catch (OperationCanceledException)
                    {
                    }
                    finally
                    {
                        connected.DisconnectAll();
                    }
                }
                NodeServerTrace.Trace.TraceInformation("Peer table is now full");
            }
        }
Exemple #21
0
        /// <summary>
        /// Fill the PeerTable with fresh addresses
        /// </summary>
        public void DiscoverPeers(int peerToFind = 990)
        {
            TraceCorrelation traceCorrelation = new TraceCorrelation(NodeServerTrace.Trace, "Discovering nodes");
            List<Task> tasks = new List<Task>();
            using(traceCorrelation.Open())
            {
                while(CountPeerRequired(peerToFind) != 0)
                {
                    NodeServerTrace.PeerTableRemainingPeerToGet(CountPeerRequired(peerToFind));
                    CancellationTokenSource cancellation = new CancellationTokenSource(TimeSpan.FromSeconds(40));
                    var peers = PeerTable.GetActivePeers(1000);
                    if(peers.Length == 0)
                    {
                        PopulateTableWithDNSNodes();
                        PopulateTableWithHardNodes();
                        peers = PeerTable.GetActivePeers(1000);
                    }

                    CancellationTokenSource peerTableFull = new CancellationTokenSource();
                    NodeSet connected = new NodeSet();
                    try
                    {
                        Parallel.ForEach(peers, new ParallelOptions()
                        {
                            MaxDegreeOfParallelism = 5,
                            CancellationToken = peerTableFull.Token,
                        }, p =>
                        {
                            Node n = null;
                            try
                            {
                                n = GetNodeByPeer(p, cancellation.Token);
                                if(n.State < NodeState.HandShaked)
                                {
                                    connected.AddNode(n);
                                    n.VersionHandshake(cancellation.Token);
                                }
                                n.SendMessage(new GetAddrPayload());
                                Thread.Sleep(2000);
                            }
                            catch(Exception)
                            {
                                if(n != null)
                                    n.Disconnect();
                            }
                            if(CountPeerRequired(peerToFind) == 0)
                                peerTableFull.Cancel();
                            else
                                NodeServerTrace.Information("Need " + CountPeerRequired(peerToFind) + " more peers");
                        });
                    }
                    catch(OperationCanceledException)
                    {
                    }
                    finally
                    {
                        connected.DisconnectAll();
                    }
                }
                NodeServerTrace.Trace.TraceInformation("Peer table is now full");
            }
        }
Exemple #22
0
        public NodeSet CreateNodeSet(int size)
        {
            if(size > 1000)
                throw new ArgumentOutOfRangeException("size", "size should be less than 1000");
            TraceCorrelation trace = new TraceCorrelation(NodeServerTrace.Trace, "Creating node set of size " + size);
            NodeSet set = new NodeSet();
            using(trace.Open())
            {
                while(set.Count() < size)
                {
                    var peerToGet = size - set.Count();
                    var activePeers = PeerTable.GetActivePeers(1000);
                    activePeers = activePeers.Where(p => !set.Contains(p.NetworkAddress.Endpoint)).ToArray();
                    if(activePeers.Length < peerToGet)
                    {
                        DiscoverPeers(size);
                        continue;
                    }
                    NodeServerTrace.Information("Need " + peerToGet + " more nodes");

                    BlockingCollection<Node> handshakedNodes = new BlockingCollection<Node>(peerToGet);
                    CancellationTokenSource handshakedFull = new CancellationTokenSource();

                    try
                    {
                        Parallel.ForEach(activePeers,
                            new ParallelOptions()
                            {
                                MaxDegreeOfParallelism = 10,
                                CancellationToken = handshakedFull.Token
                            }, p =>
                        {
                            if(set.Contains(p.NetworkAddress.Endpoint))
                                return;
                            Node node = null;
                            try
                            {
                                node = GetNodeByPeer(p, handshakedFull.Token);
                                node.VersionHandshake(handshakedFull.Token);
                                if(node != null && node.State != NodeState.HandShaked)
                                    node.Disconnect();
                                if(!handshakedNodes.TryAdd(node))
                                {
                                    handshakedFull.Cancel();
                                    node.Disconnect();
                                }
                                else
                                {
                                    var remaining = (size - set.Count() - handshakedNodes.Count);
                                    if(remaining == 0)
                                    {
                                        handshakedFull.Cancel();
                                    }
                                    else
                                        NodeServerTrace.Information("Need " + remaining + " more nodes");
                                }
                            }
                            catch(Exception)
                            {
                                if(node != null)
                                    node.Disconnect();
                            }
                        });
                    }
                    catch(OperationCanceledException)
                    {
                    }
                    set.AddNodes(handshakedNodes.ToArray());
                }
            }
            return set;
        }
Exemple #23
0
		internal void DiscoverPeers(Network network, NodeConnectionParameters parameters)
		{
			int peerToFind = 1000;
			TraceCorrelation traceCorrelation = new TraceCorrelation(NodeServerTrace.Trace, "Discovering nodes");
			int found = 0;

			using(traceCorrelation.Open())
			{
				while(found < peerToFind)
				{
					parameters.ConnectCancellation.ThrowIfCancellationRequested();
					NodeServerTrace.PeerTableRemainingPeerToGet(-found + peerToFind);
					List<NetworkAddress> peers = new List<NetworkAddress>();
					peers.AddRange(this.GetAddr());
					if(peers.Count == 0)
					{
						PopulateTableWithDNSNodes(network, peers);
						PopulateTableWithHardNodes(network, peers);
						peers = new List<NetworkAddress>(peers.OrderBy(a => RandomUtils.GetInt32()));
					}


					CancellationTokenSource peerTableFull = new CancellationTokenSource();
					CancellationToken loopCancel = CancellationTokenSource.CreateLinkedTokenSource(peerTableFull.Token, parameters.ConnectCancellation).Token;
					try
					{
						Parallel.ForEach(peers, new ParallelOptions()
						{
							MaxDegreeOfParallelism = 5,
							CancellationToken = loopCancel,
						}, p =>
						{
							CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
							var cancelConnection = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, loopCancel);
							Node n = null;
							try
							{
								var param2 = parameters.Clone();
								param2.ConnectCancellation = cancelConnection.Token;
								var addrman = param2.TemplateBehaviors.Find<AddressManagerBehavior>();
								param2.TemplateBehaviors.Clear();
								param2.TemplateBehaviors.Add(addrman);
								n = Node.Connect(network, p.Endpoint, param2);
								n.VersionHandshake(cancelConnection.Token);
								n.MessageReceived += (s, a) =>
								{
									var addr = (a.Message.Payload as AddrPayload);
									if(addr != null)
									{
										Interlocked.Add(ref found, addr.Addresses.Length);
										if(found >= peerToFind)
											peerTableFull.Cancel();
									}
								};
								n.SendMessageAsync(new GetAddrPayload());
								loopCancel.WaitHandle.WaitOne(2000);
							}
							catch
							{
							}
							finally
							{
								if(n != null)
									n.DisconnectAsync();
							}
							if(found >= peerToFind)
								peerTableFull.Cancel();
							else
								NodeServerTrace.Information("Need " + (-found + peerToFind) + " more peers");
						});
					}
					catch(OperationCanceledException)
					{
						if(parameters.ConnectCancellation.IsCancellationRequested)
							throw;
					}
				}
			}
		}
Exemple #24
0
        public NodeSet CreateNodeSet(int size)
        {
            if (size > 1000)
            {
                throw new ArgumentOutOfRangeException("size", "size should be less than 1000");
            }
            TraceCorrelation trace = new TraceCorrelation(NodeServerTrace.Trace, "Creating node set of size " + size);
            NodeSet          set   = new NodeSet();

            using (trace.Open())
            {
                while (set.Count() < size)
                {
                    var peerToGet   = size - set.Count();
                    var activePeers = PeerTable.GetActivePeers(1000);
                    activePeers = activePeers.Where(p => !set.Contains(p.NetworkAddress.Endpoint)).ToArray();
                    if (activePeers.Length < peerToGet)
                    {
                        DiscoverPeers(size);
                        continue;
                    }
                    NodeServerTrace.Information("Need " + peerToGet + " more nodes");

                    BlockingCollection <Node> handshakedNodes = new BlockingCollection <Node>(peerToGet);
                    CancellationTokenSource   handshakedFull  = new CancellationTokenSource();

                    try
                    {
                        Parallel.ForEach(activePeers,
                                         new ParallelOptions()
                        {
                            MaxDegreeOfParallelism = 10,
                            CancellationToken      = handshakedFull.Token
                        }, p =>
                        {
                            if (set.Contains(p.NetworkAddress.Endpoint))
                            {
                                return;
                            }
                            Node node = null;
                            try
                            {
                                node = GetNodeByPeer(p, handshakedFull.Token);
                                node.VersionHandshake(handshakedFull.Token);
                                if (node != null && node.State != NodeState.HandShaked)
                                {
                                    node.Disconnect();
                                }
                                if (!handshakedNodes.TryAdd(node))
                                {
                                    handshakedFull.Cancel();
                                    node.Disconnect();
                                }
                                else
                                {
                                    var remaining = (size - set.Count() - handshakedNodes.Count);
                                    if (remaining == 0)
                                    {
                                        handshakedFull.Cancel();
                                    }
                                    else
                                    {
                                        NodeServerTrace.Information("Need " + remaining + " more nodes");
                                    }
                                }
                            }
                            catch (Exception)
                            {
                                if (node != null)
                                {
                                    node.Disconnect();
                                }
                            }
                        });
                    }
                    catch (OperationCanceledException)
                    {
                    }
                    set.AddNodes(handshakedNodes.ToArray());
                }
            }
            return(set);
        }
Exemple #25
0
        /// <summary>
        /// Try to connect to a single endpoint
        /// The connected endpoint will be added to the nodes collection
        /// </summary>
        /// <param name="force">Connect even if MaximumNodeConnection limit was reached</param>
        /// <returns>A connected node or null</returns>
        public Node TryConnectNode(IPEndPoint endPoint, bool force = false)
        {
            // this is not expected to be performance critical so
            // only use a single lock. placing a lock before the
            // check should avoid connecting to a node already connected
            lock (tcs)
            {
                // first look for the node maybe its already connected
                var node = this.ConnectedNodes.FindByEndpoint(endPoint);
                if (node != null)
                {
                    return(node);
                }

                if (!force && _ConnectedNodes.Count >= MaximumNodeConnection)
                {
                    return(null);
                }

                var scope = _Trace.Open();

                NodeServerTrace.Information("Connected nodes : " + _ConnectedNodes.Count + "/" + MaximumNodeConnection);
                var parameters = _ConnectionParameters.Clone();
                parameters.TemplateBehaviors.Add(new NodesGroupBehavior(this));
                parameters.ConnectCancellation = _Disconnect.Token;

                try
                {
                    node = Node.Connect(_Network, endPoint, parameters);
                    var timeout = CancellationTokenSource.CreateLinkedTokenSource(_Disconnect.Token);
                    timeout.CancelAfter(5000);
                    node.VersionHandshake(_Requirements, timeout.Token);
                    NodeServerTrace.Information("Node successfully connected to and handshaked");
                }
                catch (OperationCanceledException ex)
                {
                    if (_Disconnect.Token.IsCancellationRequested)
                    {
                        throw;
                    }
                    NodeServerTrace.Error("Timeout for picked node", ex);
                    if (node != null)
                    {
                        node.DisconnectAsync("Handshake timeout", ex);
                    }
                }
                catch (SocketException)
                {
                    _ConnectionParameters.ConnectCancellation.WaitHandle.WaitOne(500);
                }
                catch (Exception ex)
                {
                    NodeServerTrace.Error("Error while connecting to node", ex);
                    if (node != null)
                    {
                        node.DisconnectAsync("Error while connecting", ex);
                    }
                }
                finally
                {
                    scope?.Dispose();
                }

                return(node);
            }
        }
Exemple #26
0
        internal void StartConnecting()
        {
            if (_Disconnect.IsCancellationRequested)
            {
                return;
            }
            if (_ConnectedNodes.Count >= MaximumNodeConnection)
            {
                return;
            }
            if (_Connecting)
            {
                return;
            }
            Task.Factory.StartNew(() =>
            {
                if (Monitor.TryEnter(cs))
                {
                    _Connecting = true;
                    TraceCorrelationScope scope = null;
                    try
                    {
                        while (!_Disconnect.IsCancellationRequested && _ConnectedNodes.Count < MaximumNodeConnection)
                        {
                            scope = scope ?? _Trace.Open();

                            NodeServerTrace.Information("Connected nodes : " + _ConnectedNodes.Count + "/" + MaximumNodeConnection);
                            var parameters = _ConnectionParameters.Clone();
                            parameters.TemplateBehaviors.Add(new NodesGroupBehavior(this));
                            parameters.ConnectCancellation = _Disconnect.Token;
                            var addrman = AddressManagerBehavior.GetAddrman(parameters);

                            if (addrman == null)
                            {
                                addrman = _DefaultAddressManager;
                                AddressManagerBehavior.SetAddrman(parameters, addrman);
                            }

                            Node node = null;
                            try
                            {
                                node        = Node.Connect(_Network, parameters, AllowSameGroup ? null : _ConnectedNodes.Select(n => n.RemoteSocketAddress).ToArray());
                                var timeout = CancellationTokenSource.CreateLinkedTokenSource(_Disconnect.Token);
                                timeout.CancelAfter(5000);
                                node.VersionHandshake(_Requirements, timeout.Token);
                                NodeServerTrace.Information("Node successfully connected to and handshaked");
                            }
                            catch (OperationCanceledException ex)
                            {
                                if (_Disconnect.Token.IsCancellationRequested)
                                {
                                    throw;
                                }
                                NodeServerTrace.Error("Timeout for picked node", ex);
                                if (node != null)
                                {
                                    node.DisconnectAsync("Handshake timeout", ex);
                                }
                            }
                            catch (Exception ex)
                            {
                                NodeServerTrace.Error("Error while connecting to node", ex);
                                if (node != null)
                                {
                                    node.DisconnectAsync("Error while connecting", ex);
                                }
                            }
                        }
                    }
                    finally
                    {
                        Monitor.Exit(cs);
                        _Connecting = false;
                        if (scope != null)
                        {
                            scope.Dispose();
                        }
                    }
                }
            }, TaskCreationOptions.LongRunning);
        }