public void AddNodeAddress(IPEndPoint endpoint) { AddressManager addrman = AddressManagerBehavior.GetAddrman(this.AddNodeNodeGroup.NodeConnectionParameters); addrman.Add(new NetworkAddress(endpoint)); this.AddNodeNodeGroup.MaximumNodeConnection++; }
/// <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); } } }
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");
public void AddNodeAddress(IPEndPoint endpoint) { this.logger.LogTrace("({0}:'{1}')", nameof(endpoint), endpoint); AddressManager addrman = AddressManagerBehavior.GetAddrman(this.AddNodeNodeGroup.NodeConnectionParameters); addrman.Add(new NetworkAddress(endpoint)); this.AddNodeNodeGroup.MaximumNodeConnection++; this.logger.LogTrace("(-)"); }
public Server(IPAddress externalAddress, NetworkInfo network, NodeConnectionParameters nodeConnectionParameters) { _Server = new NodeServer(network, internalPort: network.DefaultPort); OwnResource(_Server); if (externalAddress != null) { var externalEndpoint = new IPEndPoint(externalAddress, network.DefaultPort); AddressManager addressManager = AddressManagerBehavior.GetAddrman(nodeConnectionParameters); addressManager.Add(new NetworkAddress(externalEndpoint)); addressManager.Connected(new NetworkAddress(externalEndpoint)); _Server.ExternalEndpoint = externalEndpoint; } _Server.InboundNodeConnectionParameters = nodeConnectionParameters; _Server.AllowLocalPeers = false; //TODO NodeServerTrace.Information($"Server setup at {externalAddress}"); }
protected bool AddressManagerContains(NodeServer nodeServer, IPEndPoint ipEndPoint) { return(AddressManagerContains(AddressManagerBehavior.GetAddrman(nodeServer.InboundNodeConnectionParameters.TemplateBehaviors), ipEndPoint)); }
protected bool AddressManagerContains(Node node, IPEndPoint ipEndPoint) { return(AddressManagerContains(AddressManagerBehavior.GetAddrman(node), ipEndPoint)); }
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); }
public async Task Connect(NetworkInfo networkInfo) { IPAddress ipAddress = null; WireSerialization.Instance.Magic = networkInfo.Magic; NodeServerTrace.Information($"Magic is {networkInfo.Magic}"); var natManager = new NATManager(networkInfo.DefaultPort); #if DEBUG if (networkInfo.IsLANHost) { ipAddress = natManager.InternalIPAddress ?? IPAddress.Loopback; networkInfo.PeersToFind = 0; } else if (networkInfo.IsLANClient) { var ipAddressStr = (natManager.InternalIPAddress ?? IPAddress.Loopback).ToString(); networkInfo.PeersToFind = 1; if (networkInfo.Seeds.Count == 0 && !networkInfo.Seeds.Contains(ipAddressStr)) { networkInfo.Seeds.Add(ipAddressStr); } } else #endif if (!string.IsNullOrEmpty(networkInfo.ExternalIPAddress)) { ipAddress = IPAddress.Parse(networkInfo.ExternalIPAddress); } else if (networkInfo.DisableUPnP) { StatusMessageProducer.OutboundStatus = OutboundStatusEnum.Disabled; } else { StatusMessageProducer.OutboundStatus = OutboundStatusEnum.Initializing; await natManager.Init(); if (natManager.DeviceFound && natManager.Mapped.Value && natManager.ExternalIPVerified.HasValue && natManager.ExternalIPVerified.Value) { StatusMessageProducer.OutboundStatus = OutboundStatusEnum.HasValidAddress; ipAddress = natManager.ExternalIPAddress; } else { StatusMessageProducer.OutboundStatus = OutboundStatusEnum.HasInvalidAddress; } } _BroadcastHubBehavior = new BroadcastHubBehavior(); _MinerBehavior = new MinerBehavior(); _NodeConnectionParameters.TemplateBehaviors.Add(_BroadcastHubBehavior); _NodeConnectionParameters.TemplateBehaviors.Add(_MinerBehavior); _NodeConnectionParameters.TemplateBehaviors.Add(new SPVBehavior(_BlockChain, _BroadcastHubBehavior.BroadcastHub)); _NodeConnectionParameters.TemplateBehaviors.Add(new ChainBehavior(_BlockChain)); AddressManagerBehavior.GetAddrman(_NodeConnectionParameters).PeersToFind = networkInfo.PeersToFind; if (ipAddress != null) { _NodeConnectionParameters.TemplateBehaviors.Find <AddressManagerBehavior>().Mode = AddressManagerBehaviorMode.AdvertizeDiscover; //parameters.Advertize = true; _NodeConnectionParameters.AddressFrom = new System.Net.IPEndPoint(ipAddress, networkInfo.DefaultPort); } else { _NodeConnectionParameters.TemplateBehaviors.Find <AddressManagerBehavior>().Mode = AddressManagerBehaviorMode.Discover; } if (ipAddress != null) { _Server = new Server(ipAddress, networkInfo, _NodeConnectionParameters); OwnResource(_Server); if (_Server.Start()) { NodeServerTrace.Information($"Server started at {ipAddress}:{networkInfo.DefaultPort}"); StatusMessageProducer.OutboundStatus = OutboundStatusEnum.Accepting; } else { NodeServerTrace.Information($"Could not start server at {ipAddress}:{networkInfo.DefaultPort}"); } } if (networkInfo.Seeds.Count == 0) { NodeServerTrace.Information("No seeds defined"); } else { _NodesGroup = new NodesGroup(networkInfo, _NodeConnectionParameters); OwnResource(_NodesGroup); _NodesGroup.AllowSameGroup = true; //TODO _NodesGroup.MaximumNodeConnection = networkInfo.MaximumNodeConnection; #if TRACE _NodesGroup.ConnectedNodes.Added += (object sender, NodeEventArgs e) => { NodeServerTrace.Information("Peer found: " + e.Node.RemoteSocketAddress + ":" + e.Node.RemoteSocketPort); }; #endif _NodesGroup.Connect(); } }
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(); } }