Пример #1
0
 public NodesGroup(
     Network network,
     NodeConnectionParameters connectionParameters = null,
     NodeRequirement requirements = null)
 {
     AllowSameGroup        = false;
     MaximumNodeConnection = 8;
     _network                 = network;
     _cs                      = new object();
     ConnectedNodes           = new NodesCollection();
     NodeConnectionParameters = connectionParameters ?? new NodeConnectionParameters();
     NodeConnectionParameters = NodeConnectionParameters.Clone();
     Requirements             = requirements ?? new NodeRequirement();
     _disconnect              = new CancellationTokenSource();
 }
Пример #2
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;
                        }
                    }
                }
            }
        }
Пример #3
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 = NodeConnectionParameters.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
                            {
                                var groupSelector = CustomGroupSelector ??
                                                    (AllowSameGroup ? WellKnownGroupSelectors.ByRandom : null);
                                node = Node.Connect(_network, parameters,
                                                    ConnectedNodes.Select(n => n.RemoteSocketEndpoint).ToArray(), groupSelector);
                                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)
                                {
                                    break;
                                }

                                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);
        }