public EventLoopMessageListener(Action <T> processMessage) { new Thread(new ThreadStart(() => { try { while (!cancellationSource.IsCancellationRequested) { var message = _MessageQueue.Take(cancellationSource.Token); if (message != null) { try { processMessage(message); } catch (Exception ex) { NodeServerTrace.Error("Unexpected expected during message loop", ex); } } } } catch (OperationCanceledException) { } })).Start(); }
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; } } }
public void Dispose() { if (!_Cancel.IsCancellationRequested) { _Cancel.Cancel(); _Trace.LogInside(() => NodeServerTrace.Information("Stopping node server...")); lock (_Resources) { foreach (var resource in _Resources) { resource.Dispose(); } } try { _ConnectedNodes.DisconnectAll(); } finally { if (socket != null) { Utils.SafeCloseSocket(socket); socket = null; } } } }
internal void ExternalAddressDetected(IPAddress iPAddress) { if (!ExternalEndpoint.Address.IsRoutable(AllowLocalPeers) && iPAddress.IsRoutable(AllowLocalPeers)) { NodeServerTrace.Information("New externalAddress detected " + iPAddress); ExternalEndpoint = new IPEndPoint(iPAddress, ExternalEndpoint.Port); } }
private void BeginAccept() { if (_Cancel.IsCancellationRequested) { NodeServerTrace.Information("Stop accepting connection..."); return; } NodeServerTrace.Information("Accepting connection..."); var args = new SocketAsyncEventArgs(); args.Completed += Accept_Completed; if (!socket.AcceptAsync(args)) { EndAccept(args); } }
public void PushMessage(T message) { if (message != null) { Task.Factory.StartNew(() => { try { _Process(message); } catch (Exception ex) { NodeServerTrace.Error("Unexpected expected during message loop", ex); } }); } }
internal 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; } } } } }
private void ProcessMessageCore(IncomingMessage message) { if (message.Message.Payload is VersionPayload) { var version = message.AssertPayload <VersionPayload>(); var connectedToSelf = version.Nonce == Nonce; if (message.Node != null && connectedToSelf) { NodeServerTrace.ConnectionToSelfDetected(); message.Node.DisconnectAsync(); return; } if (message.Node == null) { var remoteEndpoint = version.AddressFrom; if (!remoteEndpoint.Address.IsRoutable(AllowLocalPeers)) { //Send his own endpoint remoteEndpoint = new IPEndPoint(((IPEndPoint)message.Socket.RemoteEndPoint).Address, Network.DefaultPort); } var peer = new NetworkAddress() { Endpoint = remoteEndpoint, Time = DateTimeOffset.UtcNow }; var node = new Node(peer, Network, CreateNodeConnectionParameters(), message.Socket, version); if (connectedToSelf) { node.SendMessage(CreateNodeConnectionParameters().CreateVersion(node.Peer.Endpoint, Network)); NodeServerTrace.ConnectionToSelfDetected(); node.Disconnect(); return; } CancellationTokenSource cancel = new CancellationTokenSource(); cancel.CancelAfter(TimeSpan.FromSeconds(10.0)); try { ConnectedNodes.Add(node); node.StateChanged += node_StateChanged; node.RespondToHandShake(cancel.Token); } catch (OperationCanceledException ex) { NodeServerTrace.Error("The remote node did not respond fast enough (10 seconds) to the handshake completion, dropping connection", ex); node.DisconnectAsync(); throw; } catch (Exception) { node.DisconnectAsync(); throw; } } } var messageReceived = MessageReceived; if (messageReceived != null) { messageReceived(this, message); } }
private void EndAccept(SocketAsyncEventArgs args) { using (_Trace.Open()) { Socket client = null; try { if (args.SocketError != SocketError.Success) { throw new SocketException((int)args.SocketError); } client = args.AcceptSocket; if (_Cancel.IsCancellationRequested) { return; } NodeServerTrace.Information("Client connection accepted : " + client.RemoteEndPoint); var cancel = CancellationTokenSource.CreateLinkedTokenSource(_Cancel.Token); cancel.CancelAfter(TimeSpan.FromSeconds(10)); var stream = new NetworkStream(client, false); while (true) { cancel.Token.ThrowIfCancellationRequested(); PerformanceCounter counter; var message = Message.ReadNext(stream, Network, Version, cancel.Token, out counter); _MessageProducer.PushMessage(new IncomingMessage() { Socket = client, Message = message, Length = counter.ReadenBytes, Node = null, }); if (message.Payload is VersionPayload) { break; } else { NodeServerTrace.Error("The first message of the remote peer did not contained a Version payload", null); } } } catch (OperationCanceledException) { Utils.SafeCloseSocket(client); if (!_Cancel.Token.IsCancellationRequested) { NodeServerTrace.Error("The remote connecting failed to send a message within 10 seconds, dropping connection", null); } } catch (Exception ex) { if (_Cancel.IsCancellationRequested) { return; } if (client == null) { NodeServerTrace.Error("Error while accepting connection ", ex); Thread.Sleep(3000); } else { Utils.SafeCloseSocket(client); NodeServerTrace.Error("Invalid message received from the remote connecting node", ex); } } BeginAccept(); } }
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 { var groupSelector = CustomGroupSelector != null ? 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); }