Exemple #1
0
        /// <summary>
        /// Connect to a random node on the network
        /// </summary>
        /// <param name="network">The network to connect to</param>
        /// <param name="parameters">The parameters used by the found node, use AddressManagerBehavior.GetAddrman for finding peers</param>
        /// <param name="connectedAddresses">The already connected addresses, the new address will be select outside of existing groups</param>
        /// <returns></returns>
        public static Node Connect(NetworkInfo network, NodeConnectionParameters parameters = null, IPAddress[] connectedAddresses = null)
        {
            connectedAddresses = connectedAddresses ?? new IPAddress[0];
            parameters         = parameters ?? new NodeConnectionParameters();
            var            addrman = AddressManagerBehavior.GetAddrman(parameters) ?? new AddressManager();
            DateTimeOffset start   = DateTimeOffset.UtcNow;

            while (true)
            {
                parameters.ConnectCancellation.ThrowIfCancellationRequested();
                if (addrman.Count == 0 || DateTimeOffset.UtcNow - start > TimeSpan.FromSeconds(10))
                {
                    addrman.DiscoverPeers(network, parameters);
                    start = DateTimeOffset.UtcNow;
                }
                NetworkAddress addr = null;
                while (true)
                {
                    addr = addrman.Select();
                    if (addr == null)
                    {
                        break;
                    }
                    if (!addr.Endpoint.Address.IsValid())
                    {
                        continue;
                    }
                    var groupExist = connectedAddresses.Any(a => a.GetGroup().SequenceEqual(addr.Endpoint.Address.GetGroup()));
                    if (groupExist)
                    {
                        continue;
                    }
                    break;
                }
                if (addr == null)
                {
                    continue;
                }
                try
                {
                    var timeout = new CancellationTokenSource(5000);
                    var param2  = parameters.Clone();
                    param2.ConnectCancellation = CancellationTokenSource.CreateLinkedTokenSource(parameters.ConnectCancellation, timeout.Token).Token;
                    var node = Node.Connect(network, addr.Endpoint, param2);
                    return(node);
                }
                catch (OperationCanceledException ex)
                {
                    if (ex.CancellationToken == parameters.ConnectCancellation)
                    {
                        throw;
                    }
                }
                catch (SocketException)
                {
                    parameters.ConnectCancellation.WaitHandle.WaitOne(500);
                }
            }
        }
Exemple #2
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;
                    try
                    {
                        while (!_Disconnect.IsCancellationRequested && _ConnectedNodes.Count < MaximumNodeConnection)
                        {
                            Logs.NodeServer.LogInformation("Connected nodes {connectedNodeCount} / {maximumNodeCount} ", _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
                            {
                                var groupSelector = CustomGroupSelector != null ? CustomGroupSelector :
                                                    AllowSameGroup ? WellKnownGroupSelectors.ByRandom : null;

                                var connectedPeers = _ConnectedNodes.Where(n => n.Peer is { }).Select(n => n.Peer.Endpoint).ToArray();
                                node = Node.Connect(_Network, parameters, connectedPeers, groupSelector);
                                using (var timeout = CancellationTokenSource.CreateLinkedTokenSource(_Disconnect.Token))
                                {
                                    timeout.CancelAfter(5000);
                                    node.VersionHandshake(_Requirements, timeout.Token);
                                    Logs.NodeServer.LogInformation("Node successfully connected to and handshaked");
                                }
                            }
                            catch (OperationCanceledException ex)
                            {
                                if (_Disconnect.Token.IsCancellationRequested)
                                {
                                    break;
                                }
                                Logs.NodeServer.LogError(default, ex, "Timeout for picked node");
Exemple #3
0
 public NodesGroup(
     Network network,
     NodeConnectionParameters connectionParameters = null,
     NodeRequirement requirements = null)
 {
     AllowSameGroup        = false;
     MaximumNodeConnection = 8;
     _Network              = network;
     cs                    = new object();
     _ConnectedNodes       = new NodesCollection();
     _ConnectionParameters = connectionParameters ?? new NodeConnectionParameters();
     _ConnectionParameters = _ConnectionParameters.Clone();
     _Requirements         = requirements ?? new NodeRequirement();
     _Disconnect           = new CancellationTokenSource();
 }
Exemple #4
0
		public NodesGroup(
			Network network,
			NodeConnectionParameters connectionParameters = null,
			NodeRequirement requirements = null)
		{
			AllowSameGroup = false;
			MaximumNodeConnection = 8;
			_Network = network;
			cs = new object();
			_ConnectedNodes = new NodesCollection();
			_ConnectionParameters = connectionParameters ?? new NodeConnectionParameters();
			_ConnectionParameters = _ConnectionParameters.Clone();
			_Requirements = requirements ?? new NodeRequirement();
			_Disconnect = new CancellationTokenSource();
		}
		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 #6
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);
        }
Exemple #7
0
        public void DiscoverPeers(Network network, NodeConnectionParameters parameters, int peerToFind)
        {
            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()));
                        if (peers.Count == 0)
                        {
                            return;
                        }
                    }


                    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;
                        }
                    }
                }
            }
        }
        internal void DiscoverPeers(Network network, NodeConnectionParameters parameters, int peerToFind)
        {
            TimeSpan backoff = TimeSpan.Zero;

            Logs.NodeServer.LogTrace("Discovering nodes");

            int found = 0;

            {
                while (found < peerToFind)
                {
                    Thread.Sleep(backoff);
                    backoff = backoff == TimeSpan.Zero ? TimeSpan.FromSeconds(1.0) : TimeSpan.FromSeconds(backoff.TotalSeconds * 2);
                    if (backoff > TimeSpan.FromSeconds(10.0))
                    {
                        backoff = TimeSpan.FromSeconds(10.0);
                    }

                    parameters.ConnectCancellation.ThrowIfCancellationRequested();

                    Logs.NodeServer.LogTrace("Remaining peer to get {remainingPeerCount}", (-found + peerToFind));

                    List <NetworkAddress> peers = new List <NetworkAddress>();
                    peers.AddRange(this.GetAddr());
                    if (peers.Count == 0)
                    {
                        PopulateTableWithDNSNodes(network, peers).GetAwaiter().GetResult();
                        PopulateTableWithHardNodes(network, peers);
                        peers = new List <NetworkAddress>(peers.OrderBy(a => RandomUtils.GetInt32()));
                        if (peers.Count == 0)
                        {
                            return;
                        }
                    }

                    CancellationTokenSource peerTableFull = new CancellationTokenSource();
                    CancellationToken       loopCancel    = CancellationTokenSource.CreateLinkedTokenSource(peerTableFull.Token, parameters.ConnectCancellation).Token;
                    try
                    {
                        Parallel.ForEach(peers, new ParallelOptions()
                        {
                            MaxDegreeOfParallelism = 5,
                            CancellationToken      = loopCancel,
                        }, p =>
                        {
                            using (CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
                                using (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);
                                                backoff = TimeSpan.FromSeconds(0);
                                                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
                            {
                                Logs.NodeServer.LogInformation("Need {neededPeerCount} more peers", (-found + peerToFind));
                            }
                        });
                    }
                    catch (OperationCanceledException)
                    {
                        if (parameters.ConnectCancellation.IsCancellationRequested)
                        {
                            throw;
                        }
                    }
                }
            }
        }