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(); }
public NodeConnectionParameters(NodeConnectionParameters other) { Version = other.Version; IsRelay = other.IsRelay; Services = other.Services; ReceiveBufferSize = other.ReceiveBufferSize; SendBufferSize = other.SendBufferSize; ConnectCancellation = other.ConnectCancellation; UserAgent = other.UserAgent; AddressFrom = other.AddressFrom; Nonce = other.Nonce; Advertize = other.Advertize; ReuseBuffer = other.ReuseBuffer; PreferredTransactionOptions = other.PreferredTransactionOptions; foreach (var behavior in other.TemplateBehaviors) { TemplateBehaviors.Add(behavior.Clone()); } }
public NodeServer(Network network, uint?version = null, int internalPort = -1) { AllowLocalPeers = true; InboundNodeConnectionParameters = new NodeConnectionParameters(); internalPort = internalPort == -1 ? network.DefaultPort : internalPort; _localEndpoint = new IPEndPoint(IPAddress.Parse("0.0.0.0").MapToIPv6Ex(), internalPort); MaxConnections = 125; Network = network; _externalEndpoint = new IPEndPoint(_localEndpoint.Address, Network.DefaultPort); Version = version ?? network.MaxP2PVersion; var listener = new EventLoopMessageListener <IncomingMessage>(ProcessMessage); _messageProducer.AddMessageListener(listener); OwnResource(listener); ConnectedNodes = new NodesCollection(); ConnectedNodes.Added += _Nodes_NodeAdded; ConnectedNodes.Removed += _Nodes_NodeRemoved; ConnectedNodes.MessageProducer.AddMessageListener(listener); _trace = new TraceCorrelation(NodeServerTrace.Trace, "Node server listening on " + LocalEndpoint); }
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; } } } } }
public static NodesGroup GetNodeGroup(NodeConnectionParameters parameters) { return(GetNodeGroup(parameters.TemplateBehaviors)); }
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); }