public void VersionHandshake(CancellationToken cancellationToken = default(CancellationToken)) { using (var listener = CreateListener() .Where(p => p.Message.Payload is VersionPayload || p.Message.Payload is RejectPayload || p.Message.Payload is VerAckPayload)) { using (TraceCorrelation.Open()) { SendMessage(MyVersion); var payload = listener.ReceivePayload <Payload>(cancellationToken); if (payload is RejectPayload) { throw new InvalidOperationException("Handshake rejected : " + ((RejectPayload)payload).Reason); } var version = (VersionPayload)payload; _PeerVersion = version; Version = version.Version; if (!version.AddressReciever.Address.Equals(MyVersion.AddressFrom.Address)) { NodeServerTrace.Warning("Different external address detected by the node " + version.AddressReciever.Address + " instead of " + MyVersion.AddressFrom.Address); } if (version.Version < ProtocolVersion.MIN_PEER_PROTO_VERSION) { NodeServerTrace.Warning("Outdated version " + version.Version + " disconnecting"); Disconnect(); return; } SendMessage(new VerAckPayload()); listener.ReceivePayload <VerAckPayload>(cancellationToken); State = NodeState.HandShaked; } } }
public static Node Connect(Network network, IPEndPoint endpoint, ProtocolVersion myVersion = ProtocolVersion.PROTOCOL_VERSION, bool isRelay = true, CancellationToken cancellation = default(CancellationToken)) { var peer = new Peer(PeerOrigin.Manual, new NetworkAddress() { Time = DateTimeOffset.UtcNow, Endpoint = endpoint }); VersionPayload version = new VersionPayload() { Nonce = 12345, UserAgent = VersionPayload.GetNBitcoinUserAgent(), Version = myVersion, StartHeight = 0, Timestamp = DateTimeOffset.UtcNow, AddressReciever = peer.NetworkAddress.Endpoint, AddressFrom = new IPEndPoint(IPAddress.Parse("0.0.0.0").MapToIPv6(), network.DefaultPort), Relay = isRelay }; return(new Node(peer, network, version, cancellation)); }
public NodeConnectionParameters() { ReuseBuffer = true; TemplateBehaviors.Add(new PingPongBehavior()); Version = ProtocolVersion.PROTOCOL_VERSION; IsRelay = true; Services = NodeServices.Nothing; ConnectCancellation = default(CancellationToken); ReceiveBufferSize = 1000 * 5000; SendBufferSize = 1000 * 1000; UserAgent = VersionPayload.GetNBitcoinUserAgent(); }
public NodeConnectionParameters() { this.ReuseBuffer = true; this.TemplateBehaviors.Add(new PingPongBehavior()); this.Version = ProtocolVersion.PROTOCOL_VERSION; this.IsRelay = true; this.Services = NodeServices.Nothing; this.ConnectCancellation = default(CancellationToken); this.ReceiveBufferSize = 1000 * 5000; this.SendBufferSize = 1000 * 1000; this.UserAgent = VersionPayload.GetNBitcoinUserAgent(); this.PreferredTransactionOptions = TransactionOptions.All; }
public NodeConnectionParameters() { TemplateBehaviors.Add(new PingPongBehavior()); Version = null; IsRelay = true; Services = NodeServices.Nothing; ConnectCancellation = default(CancellationToken); // Use max supported by MAC OSX Yosemite/Mavericks/Sierra (https://fasterdata.es.net/host-tuning/osx/) this.SocketSettings.ReceiveBufferSize = 1048576; this.SocketSettings.SendBufferSize = 1048576; //////////////////////// UserAgent = VersionPayload.GetNBitcoinUserAgent(); PreferredTransactionOptions = TransactionOptions.All; }
internal Node(Peer peer, NodeServer nodeServer, Socket socket, VersionPayload version) { _Peer = peer; _NodeServer = nodeServer; _Connection = new NodeConnection(this, socket); _FullVersion = version; Version = version.Version; LastSeen = peer.NetworkAddress.Time; TraceCorrelation.LogInside(() => { NodeServerTrace.Information("Connected to advertised node " + _Peer.NetworkAddress.Endpoint); State = NodeState.Connected; }); _Connection.BeginListen(); }
public VersionPayload CreateVersion(IPEndPoint peer, Network network) { VersionPayload version = new VersionPayload() { Nonce = Nonce == null?RandomUtils.GetUInt64() : Nonce.Value, UserAgent = UserAgent, Version = Version, Timestamp = DateTimeOffset.UtcNow, AddressReceiver = peer, AddressFrom = AddressFrom ?? new IPEndPoint(IPAddress.Parse("0.0.0.0").MapToIPv6Ex(), network.DefaultPort), Relay = IsRelay, Services = Services }; return(version); }
public void VersionHandshake(NodeRequirement requirements, CancellationToken cancellationToken = default(CancellationToken)) { requirements = requirements ?? new NodeRequirement(); using (var listener = CreateListener() .Where(p => p.IsPayloadTypeOf(typeof(VersionPayload), typeof(RejectPayload), typeof(VerAckPayload)))) { SendMessageAsync(MyVersion); var payload = listener.ReceivePayload <Object>(cancellationToken); if (payload is RejectPayload) { throw new ProtocolException("Handshake rejected : " + ((RejectPayload)payload).Reason); } var version = (VersionPayload)payload; _PeerVersion = version; if (!version.AddressReceiver.Address.Equals(MyVersion.AddressFrom.Address)) { NodeServerTrace.Warning("Different external address detected by the node " + version.AddressReceiver.Address + " instead of " + MyVersion.AddressFrom.Address); } if (version.Version < ProtocolVersion.MIN_PEER_PROTO_VERSION) { NodeServerTrace.Warning("Outdated version " + version.Version + " disconnecting"); Disconnect("Outdated version"); return; } if (!requirements.Check(version)) { Disconnect("The peer does not support the required services requirement"); return; } SendMessageAsync(new VerAckPayload()); listener.ReceivePayload <VerAckPayload>(cancellationToken); State = NodeState.HandShaked; if (Advertize && MyVersion.AddressFrom.Address.IsRoutable(true)) { SendMessageAsync(new AddrPayload(new NetworkAddress[] { new NetworkAddress(MyVersion.AddressFrom) { Time = DateTimeOffset.UtcNow } })); } } }
internal Node(Peer peer, Network network, VersionPayload myVersion, CancellationToken cancellation) { _MyVersion = myVersion; Version = _MyVersion.Version; Network = network; _Peer = peer; LastSeen = peer.NetworkAddress.Time; var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp); #if !NOIPDUALMODE socket.DualMode = true; #endif _Connection = new NodeConnection(this, socket); using (TraceCorrelation.Open()) { try { var ar = socket.BeginConnect(Peer.NetworkAddress.Endpoint, null, null); WaitHandle.WaitAny(new WaitHandle[] { ar.AsyncWaitHandle, cancellation.WaitHandle }); cancellation.ThrowIfCancellationRequested(); socket.EndConnect(ar); State = NodeState.Connected; NodeServerTrace.Information("Outbound connection successfull"); } catch (OperationCanceledException) { Utils.SafeCloseSocket(socket); NodeServerTrace.Information("Connection to node cancelled"); State = NodeState.Offline; return; } catch (Exception ex) { Utils.SafeCloseSocket(socket); NodeServerTrace.Error("Error connecting to the remote endpoint ", ex); State = NodeState.Failed; throw; } _Connection.BeginListen(); } }
public void VersionHandshake(CancellationToken cancellationToken = default(CancellationToken)) { var listener = new PollMessageListener <IncomingMessage>(); using (MessageProducer.AddMessageListener(listener)) { using (TraceCorrelation.Open()) { var myVersion = CreateVersionPayload(); SendMessage(myVersion); var version = listener.RecieveMessage(cancellationToken).AssertPayload <VersionPayload>(); _FullVersion = version; Version = version.Version; if (version.Nonce == NodeServer.Nonce) { NodeServerTrace.ConnectionToSelfDetected(); Disconnect(); throw new InvalidOperationException("Impossible to connect to self"); } if (!version.AddressReciever.Address.Equals(ExternalEndpoint.Address)) { NodeServerTrace.Warning("Different external address detected by the node " + version.AddressReciever.Address + " instead of " + ExternalEndpoint.Address); } NodeServer.ExternalAddressDetected(version.AddressReciever.Address); if (version.Version < ProtocolVersion.MIN_PEER_PROTO_VERSION) { NodeServerTrace.Warning("Outdated version " + version.Version + " disconnecting"); Disconnect(); return; } SendMessage(new VerAckPayload()); listener.RecieveMessage(cancellationToken).AssertPayload <VerAckPayload>(); State = NodeState.HandShaked; if (NodeServer.AdvertizeMyself) { AdvertiseMyself(); } } } }
internal Node(NetworkAddress peer, NetworkInfo network, NodeConnectionParameters parameters, Socket socket, VersionPayload peerVersion) { _RemoteSocketAddress = ((IPEndPoint)socket.RemoteEndPoint).Address; _RemoteSocketPort = ((IPEndPoint)socket.RemoteEndPoint).Port; Inbound = true; _Behaviors = new NodeBehaviorsCollection(this); _MyVersion = parameters.CreateVersion(peer.Endpoint, network); Network = network; _Peer = peer; _Connection = new NodeConnection(this, socket); _PeerVersion = peerVersion; LastSeen = peer.Time; ConnectedAt = DateTimeOffset.UtcNow; TraceCorrelation.LogInside(() => { NodeServerTrace.Information("Connected to advertised node " + _Peer.Endpoint); State = NodeState.Connected; }); InitDefaultBehaviors(parameters); _Connection.BeginListen(); }
public VersionPayload CreateVersion(IPEndPoint peer, Network network) { VersionPayload version = new VersionPayload() { Nonce = Nonce == null ? RandomUtils.GetUInt64() : Nonce.Value, UserAgent = UserAgent, Version = Version, Timestamp = DateTimeOffset.UtcNow, AddressReceiver = peer, AddressFrom = AddressFrom ?? new IPEndPoint(IPAddress.Parse("0.0.0.0").MapToIPv6(), network.DefaultPort), Relay = IsRelay, Services = Services }; return version; }
private void ProcessMessageCore(IncomingMessage message) { if (message.Message.Payload is VersionPayload) { VersionPayload version = message.AssertPayload <VersionPayload>(); bool connectedToSelf = version.Nonce == this.Nonce; if ((message.Node != null) && connectedToSelf) { NodeServerTrace.ConnectionToSelfDetected(); message.Node.DisconnectAsync(); return; } if (message.Node == null) { IPEndPoint remoteEndpoint = version.AddressFrom; if (!remoteEndpoint.Address.IsRoutable(this.AllowLocalPeers)) { // Send his own endpoint. remoteEndpoint = new IPEndPoint(((IPEndPoint)message.Socket.RemoteEndPoint).Address, this.Network.DefaultPort); } var peer = new NetworkAddress() { Endpoint = remoteEndpoint, Time = DateTimeOffset.UtcNow }; var node = new Node(peer, this.Network, CreateNodeConnectionParameters(), message.Socket, version); if (connectedToSelf) { node.SendMessage(CreateNodeConnectionParameters().CreateVersion(node.Peer.Endpoint, this.Network)); NodeServerTrace.ConnectionToSelfDetected(); node.Disconnect(); return; } CancellationTokenSource cancel = new CancellationTokenSource(); cancel.CancelAfter(TimeSpan.FromSeconds(10.0)); try { this.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; } } } this.MessageReceived?.Invoke(this, message); }