From 6e8c74e220656565cc456cc72a2cb194c52d27ff Mon Sep 17 00:00:00 2001 From: Erik van den Brink Date: Tue, 2 Apr 2019 11:52:06 +0200 Subject: [PATCH] Add ping/pong for updating node height (#673) --- neo/Network/P2P/Payloads/PingPayload.cs | 44 +++++++++++++++++++++++++ neo/Network/P2P/ProtocolHandler.cs | 25 ++++++++++---- neo/Network/P2P/RemoteNode.cs | 25 ++++++++++---- 3 files changed, 82 insertions(+), 12 deletions(-) create mode 100644 neo/Network/P2P/Payloads/PingPayload.cs diff --git a/neo/Network/P2P/Payloads/PingPayload.cs b/neo/Network/P2P/Payloads/PingPayload.cs new file mode 100644 index 0000000000..f702458b9c --- /dev/null +++ b/neo/Network/P2P/Payloads/PingPayload.cs @@ -0,0 +1,44 @@ +using Neo.IO; +using System; +using System.IO; + +namespace Neo.Network.P2P.Payloads +{ + public class PingPayload : ISerializable + { + public uint LastBlockIndex; + public uint Timestamp; + public uint Nonce; + + public int Size => + sizeof(uint) + //LastBlockIndex + sizeof(uint) + //Timestamp + sizeof(uint); //Nonce + + + public static PingPayload Create(uint height) + { + Random rand = new Random(); + return new PingPayload + { + LastBlockIndex = height, + Timestamp = DateTime.UtcNow.ToTimestamp(), + Nonce = (uint)rand.Next() + }; + } + + void ISerializable.Deserialize(BinaryReader reader) + { + LastBlockIndex = reader.ReadUInt32(); + Timestamp = reader.ReadUInt32(); + Nonce = reader.ReadUInt32(); + } + + void ISerializable.Serialize(BinaryWriter writer) + { + writer.Write(LastBlockIndex); + writer.Write(Timestamp); + writer.Write(Nonce); + } + } +} diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index a6549a417d..c1c2337598 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -18,8 +18,6 @@ namespace Neo.Network.P2P { internal class ProtocolHandler : UntypedActor { - public class SetVersion { public VersionPayload Version; } - public class SetVerack { } public class SetFilter { public BloomFilter Filter; } private readonly NeoSystem system; @@ -95,6 +93,12 @@ protected override void OnReceive(object message) case "mempool": OnMemPoolMessageReceived(); break; + case "ping": + OnPingMessageReceived(msg.GetPayload()); + break; + case "pong": + OnPongMessageReceived(msg.GetPayload()); + break; case "tx": if (msg.Payload.Length <= Transaction.MaxTransactionSize) OnInventoryReceived(msg.GetTransaction()); @@ -105,8 +109,6 @@ protected override void OnReceive(object message) case "alert": case "merkleblock": case "notfound": - case "ping": - case "pong": case "reject": default: //暂时忽略 @@ -272,16 +274,27 @@ private void OnMemPoolMessageReceived() Context.Parent.Tell(Message.Create("inv", payload)); } + private void OnPingMessageReceived(PingPayload payload) + { + Context.Parent.Tell(payload); + Context.Parent.Tell(Message.Create("pong", PingPayload.Create(Blockchain.Singleton.Height))); + } + + private void OnPongMessageReceived(PingPayload payload) + { + Context.Parent.Tell(payload); + } + private void OnVerackMessageReceived() { verack = true; - Context.Parent.Tell(new SetVerack()); + Context.Parent.Tell("verack"); } private void OnVersionMessageReceived(VersionPayload payload) { version = payload; - Context.Parent.Tell(new SetVersion { Version = payload }); + Context.Parent.Tell(payload); } public static Props Props(NeoSystem system) diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 9880339f73..65a384188a 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -29,6 +29,7 @@ internal class Relay { public IInventory Inventory; } public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerPort); public override int ListenerPort => Version?.Port ?? 0; public VersionPayload Version { get; private set; } + public uint LastBlockIndex { get; private set; } public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndPoint local) : base(connection, remote, local) @@ -63,6 +64,8 @@ private void EnqueueMessage(Message message) case "getblocks": case "getheaders": case "mempool": + case "ping": + case "pong": is_single = true; break; } @@ -114,18 +117,27 @@ protected override void OnReceive(object message) case Relay relay: OnRelay(relay.Inventory); break; - case ProtocolHandler.SetVersion setVersion: - OnSetVersion(setVersion.Version); + case VersionPayload payload: + OnVersionPayload(payload); break; - case ProtocolHandler.SetVerack _: - OnSetVerack(); + case "verack": + OnVerack(); break; case ProtocolHandler.SetFilter setFilter: OnSetFilter(setFilter.Filter); break; + case PingPayload payload: + OnPingPayload(payload); + break; } } + private void OnPingPayload(PingPayload payload) + { + if (payload.LastBlockIndex > LastBlockIndex) + LastBlockIndex = payload.LastBlockIndex; + } + private void OnRelay(IInventory inventory) { if (Version?.Relay != true) return; @@ -153,16 +165,17 @@ private void OnSetFilter(BloomFilter filter) bloom_filter = filter; } - private void OnSetVerack() + private void OnVerack() { verack = true; system.TaskManager.Tell(new TaskManager.Register { Version = Version }); CheckMessageQueue(); } - private void OnSetVersion(VersionPayload version) + private void OnVersionPayload(VersionPayload version) { this.Version = version; + this.LastBlockIndex = Version.StartHeight; if (version.Nonce == LocalNode.Nonce) { Disconnect(true);