From f884a176db001fb6c7dbed048aea0d11ef260e5c Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 10:10:57 +0200 Subject: [PATCH 01/42] Udp support --- neo/EndPointConfig.cs | 27 ++++++++++++++++ neo/NeoSystem.cs | 15 +++------ neo/Network/P2P/LocalNode.cs | 51 +++++++++++++++++++++++++---- neo/Network/P2P/Peer.cs | 63 ++++++++++++++++++++++++++++-------- neo/NodeStartConfig.cs | 37 +++++++++++++++++++++ 5 files changed, 162 insertions(+), 31 deletions(-) create mode 100644 neo/EndPointConfig.cs create mode 100644 neo/NodeStartConfig.cs diff --git a/neo/EndPointConfig.cs b/neo/EndPointConfig.cs new file mode 100644 index 0000000000..4c6690ac02 --- /dev/null +++ b/neo/EndPointConfig.cs @@ -0,0 +1,27 @@ +using System.Net; + +namespace Neo +{ + public class EndPointConfig + { + /// + /// Address + /// + public string Address { get; set; } = "0.0.0.0"; + + /// + /// Port + /// + public ushort Port { get; set; } = 0; + + /// + /// Ip EndPoint + /// + public IPEndPoint EndPoint => new IPEndPoint(IPAddress.Parse(Address), Port); + + /// + /// Return true if the address and port are valid + /// + public bool IsValid => IPAddress.TryParse(Address, out var addr) && Port > 0; + } +} \ No newline at end of file diff --git a/neo/NeoSystem.cs b/neo/NeoSystem.cs index 1e157486e2..439b4cbe77 100644 --- a/neo/NeoSystem.cs +++ b/neo/NeoSystem.cs @@ -28,7 +28,7 @@ public class NeoSystem : IDisposable public RpcServer RpcServer { get; private set; } private readonly Store store; - private Peer.Start start_message = null; + private NodeStartConfig start_message = null; private bool suspend = false; public NeoSystem(Store store) @@ -74,17 +74,10 @@ public void StartConsensus(Wallet wallet, Store consensus_store = null, bool ign Consensus.Tell(new ConsensusService.Start { IgnoreRecoveryLogs = ignoreRecoveryLogs }, Blockchain); } - public void StartNode(int port = 0, int wsPort = 0, int minDesiredConnections = Peer.DefaultMinDesiredConnections, - int maxConnections = Peer.DefaultMaxConnections, int maxConnectionsPerAddress = 3) + public void StartNode(NodeStartConfig cfg) { - start_message = new Peer.Start - { - Port = port, - WsPort = wsPort, - MinDesiredConnections = minDesiredConnections, - MaxConnections = maxConnections, - MaxConnectionsPerAddress = maxConnectionsPerAddress - }; + start_message = cfg; + if (!suspend) { LocalNode.Tell(start_message); diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index 489ca68d72..d3a6207f9f 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -1,4 +1,5 @@ using Akka.Actor; +using Akka.IO; using Neo.IO; using Neo.Ledger; using Neo.Network.P2P.Payloads; @@ -30,13 +31,13 @@ internal class SendDirectly { public IInventory Inventory; } public static readonly uint Nonce; public static string UserAgent { get; set; } - private static LocalNode singleton { get; set; } + private static LocalNode _singleton; public static LocalNode Singleton { get { - while (singleton == null) Thread.Sleep(10); - return singleton; + while (_singleton == null) Thread.Sleep(10); + return _singleton; } } @@ -51,10 +52,10 @@ public LocalNode(NeoSystem system) { lock (lockObj) { - if (singleton != null) + if (_singleton != null) throw new InvalidOperationException(); this.system = system; - singleton = this; + _singleton = this; } } @@ -75,7 +76,7 @@ private static IPEndPoint GetIPEndpointFromHostPort(string hostNameOrAddress, in IPHostEntry entry; try { - entry = Dns.GetHostEntry(hostNameOrAddress); + entry = System.Net.Dns.GetHostEntry(hostNameOrAddress); } catch (SocketException) { @@ -156,6 +157,44 @@ protected override void OnReceive(object message) } } + protected override void OnUdpMessage(IPEndPoint remote, ByteString data) + { + if (Message.TryDeserialize(data, out var msg) != data.Count) return; + + switch (msg.Command) + { + case MessageCommand.Transaction: + { + if (msg.Payload.Size <= Transaction.MaxTransactionSize) + system.LocalNode.Tell(new LocalNode.Relay { Inventory = (Transaction)msg.Payload }); + + break; + } + case MessageCommand.Ping: + { + var payload = (PingPayload)msg.Payload; + msg = Message.Create(MessageCommand.Pong, PingPayload.Create(Blockchain.Singleton.Height, payload.Nonce)); + SendUdp(remote, ByteString.FromBytes(msg.ToArray())); + break; + } + case MessageCommand.GetAddr: + { + Random rand = new Random(); + IEnumerable peers = LocalNode.Singleton.RemoteNodes.Values + .Where(p => p.ListenerPort > 0) + .GroupBy(p => p.Remote.Address, (k, g) => g.First()) + .OrderBy(p => rand.Next()) + .Take(AddrPayload.MaxCountToSend); + NetworkAddressWithTime[] networkAddresses = peers.Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Services, p.Version.Timestamp)).ToArray(); + if (networkAddresses.Length == 0) return; + + msg = Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses)); + SendUdp(remote, ByteString.FromBytes(msg.ToArray())); + break; + } + } + } + private void OnRelay(IInventory inventory) { if (inventory is Transaction transaction) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index e2b60d5777..c57b101eda 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -3,6 +3,9 @@ using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; +using Neo.IO; +using Neo.Ledger; +using Neo.Network.P2P.Payloads; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -18,7 +21,6 @@ namespace Neo.Network.P2P { public abstract class Peer : UntypedActor { - public class Start { public int Port; public int WsPort; public int MinDesiredConnections; public int MaxConnections; public int MaxConnectionsPerAddress; } public class Peers { public IEnumerable EndPoints; } public class Connect { public IPEndPoint EndPoint; public bool IsTrusted = false; } private class Timer { } @@ -28,7 +30,10 @@ private class WsConnected { public WebSocket Socket; public IPEndPoint Remote; p public const int DefaultMaxConnections = DefaultMinDesiredConnections * 4; private static readonly IActorRef tcp_manager = Context.System.Tcp(); + private static readonly IActorRef udp_manager = Context.System.Udp(); + private IActorRef tcp_listener; + private IActorRef udp_listener; private IWebHost ws_host; private ICancelable timer; protected ActorSelection Connections => Context.ActorSelection("connection_*"); @@ -101,8 +106,14 @@ protected override void OnReceive(object message) { switch (message) { - case Start start: - OnStart(start.Port, start.WsPort, start.MinDesiredConnections, start.MaxConnections, start.MaxConnectionsPerAddress); + case NodeStartConfig start: + OnStart + ( + start.Tcp != null && start.Tcp.IsValid ? start.Tcp.EndPoint : null, + start.Udp != null && start.Udp.IsValid ? start.Udp.EndPoint : null, + start.WebSocket != null && start.WebSocket.IsValid ? start.WebSocket.EndPoint : null, + start.MinDesiredConnections, start.MaxConnections, start.MaxConnectionsPerAddress + ); break; case Timer _: OnTimer(); @@ -122,6 +133,12 @@ protected override void OnReceive(object message) case Tcp.Bound _: tcp_listener = Sender; break; + case Udp.Bound _: + udp_listener = Sender; + break; + case Udp.Received udpmsg: + OnUdpMessage((IPEndPoint)udpmsg.Sender, udpmsg.Data); + break; case Tcp.CommandFailed commandFailed: OnTcpCommandFailed(commandFailed.Cmd); break; @@ -131,39 +148,56 @@ protected override void OnReceive(object message) } } - private void OnStart(int port, int wsPort, int minDesiredConnections, int maxConnections, int maxConnectionsPerAddress) + private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesiredConnections, int maxConnections, int maxConnectionsPerAddress) { - ListenerPort = port; + ListenerPort = tcp == null ? 0 : tcp.Port; MinDesiredConnections = minDesiredConnections; MaxConnections = maxConnections; MaxConnectionsPerAddress = maxConnectionsPerAddress; timer = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(0, 5000, Context.Self, new Timer(), ActorRefs.NoSender); - if ((port > 0 || wsPort > 0) + if ((ListenerPort > 0 || (ws != null && ws.Port > 0)) && localAddresses.All(p => !p.IsIPv4MappedToIPv6 || IsIntranetAddress(p)) && UPnP.Discover()) { try { localAddresses.Add(UPnP.GetExternalIP()); - if (port > 0) - UPnP.ForwardPort(port, ProtocolType.Tcp, "NEO"); - if (wsPort > 0) - UPnP.ForwardPort(wsPort, ProtocolType.Tcp, "NEO WebSocket"); + if (ListenerPort > 0) + UPnP.ForwardPort(ListenerPort, ProtocolType.Tcp, "NEO"); + if (ws != null && ws.Port > 0) + UPnP.ForwardPort(ws.Port, ProtocolType.Tcp, "NEO WebSocket"); } catch { } } - if (port > 0) + if (ListenerPort > 0) { - tcp_manager.Tell(new Tcp.Bind(Self, new IPEndPoint(IPAddress.Any, port), options: new[] { new Inet.SO.ReuseAddress(true) })); + tcp_manager.Tell(new Tcp.Bind(Self, tcp, options: new[] { new Inet.SO.ReuseAddress(true) })); } - if (wsPort > 0) + if (ws != null && ws.Port > 0) { - ws_host = new WebHostBuilder().UseKestrel().UseUrls($"http://*:{wsPort}").Configure(app => app.UseWebSockets().Run(ProcessWebSocketAsync)).Build(); + var host = "*"; + + if (!ws.Address.GetAddressBytes().SequenceEqual(IPAddress.Any.GetAddressBytes())) + { + // Is not for all interfaces + + host = ws.Address.ToString(); + } + + ws_host = new WebHostBuilder().UseKestrel().UseUrls($"http://{host}:{ws.Port}").Configure(app => app.UseWebSockets().Run(ProcessWebSocketAsync)).Build(); ws_host.Start(); } + if (udp != null && udp.Port > 0) + { + udp_manager.Tell(new Udp.Bind(Self, udp)); + } } + protected virtual void OnUdpMessage(IPEndPoint remote, ByteString data) { } + + protected void SendUdp(IPEndPoint remote, ByteString data) => udp_listener.Tell(Udp.Send.Create(data, remote)); + private void OnTcpConnected(IPEndPoint remote, IPEndPoint local) { ImmutableInterlocked.Update(ref ConnectingPeers, p => p.Remove(remote)); @@ -243,6 +277,7 @@ protected override void PostStop() timer.CancelIfNotNull(); ws_host?.Dispose(); tcp_listener?.Tell(Tcp.Unbind.Instance); + udp_listener?.Tell(Tcp.Unbind.Instance); base.PostStop(); } diff --git a/neo/NodeStartConfig.cs b/neo/NodeStartConfig.cs new file mode 100644 index 0000000000..026c02dcdd --- /dev/null +++ b/neo/NodeStartConfig.cs @@ -0,0 +1,37 @@ +using Neo.Network.P2P; + +namespace Neo +{ + public class NodeStartConfig + { + /// + /// Tcp configuration + /// + public EndPointConfig Tcp { get; set; } = new EndPointConfig() { }; + + /// + /// Udp configuration + /// + public EndPointConfig Udp { get; set; } = new EndPointConfig() { }; + + /// + /// Web socket configuration + /// + public EndPointConfig WebSocket { get; set; } = new EndPointConfig() { }; + + /// + /// Minimum desired connections + /// + public int MinDesiredConnections { get; set; } = Peer.DefaultMinDesiredConnections; + + /// + /// Maxx allowed connections + /// + public int MaxConnections { get; set; } = Peer.DefaultMaxConnections; + + /// + /// Maxx allowed connections per address + /// + public int MaxConnectionsPerAddress { get; set; } = 3; + } +} \ No newline at end of file From b8b814e45d87e2e9237b65dde45a029c4851e88d Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 13:45:17 +0200 Subject: [PATCH 02/42] Fix unbind --- neo/Network/P2P/Peer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index c57b101eda..0a24f1478c 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -277,7 +277,7 @@ protected override void PostStop() timer.CancelIfNotNull(); ws_host?.Dispose(); tcp_listener?.Tell(Tcp.Unbind.Instance); - udp_listener?.Tell(Tcp.Unbind.Instance); + udp_listener?.Tell(Udp.Unbind.Instance); base.PostStop(); } From f7a4958882f1e35d3ee864b55a8aab52c85947a8 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 14:16:14 +0200 Subject: [PATCH 03/42] typo --- neo/NodeStartConfig.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/neo/NodeStartConfig.cs b/neo/NodeStartConfig.cs index 026c02dcdd..5473bca22d 100644 --- a/neo/NodeStartConfig.cs +++ b/neo/NodeStartConfig.cs @@ -25,12 +25,12 @@ public class NodeStartConfig public int MinDesiredConnections { get; set; } = Peer.DefaultMinDesiredConnections; /// - /// Maxx allowed connections + /// Max allowed connections /// public int MaxConnections { get; set; } = Peer.DefaultMaxConnections; /// - /// Maxx allowed connections per address + /// Max allowed connections per address /// public int MaxConnectionsPerAddress { get; set; } = 3; } From 0170488118f3494f27deb5e8808944878844a5b2 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 16:59:12 +0200 Subject: [PATCH 04/42] Unify GetPeers --- neo/Network/P2P/LocalNode.cs | 23 ++++++++++++++--------- neo/Network/P2P/ProtocolHandler.cs | 8 +------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index d3a6207f9f..7e1cd3cf14 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -166,7 +166,7 @@ protected override void OnUdpMessage(IPEndPoint remote, ByteString data) case MessageCommand.Transaction: { if (msg.Payload.Size <= Transaction.MaxTransactionSize) - system.LocalNode.Tell(new LocalNode.Relay { Inventory = (Transaction)msg.Payload }); + system.LocalNode.Tell(new Relay { Inventory = (Transaction)msg.Payload }); break; } @@ -179,15 +179,8 @@ protected override void OnUdpMessage(IPEndPoint remote, ByteString data) } case MessageCommand.GetAddr: { - Random rand = new Random(); - IEnumerable peers = LocalNode.Singleton.RemoteNodes.Values - .Where(p => p.ListenerPort > 0) - .GroupBy(p => p.Remote.Address, (k, g) => g.First()) - .OrderBy(p => rand.Next()) - .Take(AddrPayload.MaxCountToSend); - NetworkAddressWithTime[] networkAddresses = peers.Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Services, p.Version.Timestamp)).ToArray(); + NetworkAddressWithTime[] networkAddresses = GetPeers(); if (networkAddresses.Length == 0) return; - msg = Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses)); SendUdp(remote, ByteString.FromBytes(msg.ToArray())); break; @@ -195,6 +188,18 @@ protected override void OnUdpMessage(IPEndPoint remote, ByteString data) } } + public NetworkAddressWithTime[] GetPeers() + { + Random rand = new Random(); + IEnumerable peers = RemoteNodes.Values + .Where(p => p.ListenerPort > 0) + .GroupBy(p => p.Remote.Address, (k, g) => g.First()) + .OrderBy(p => rand.Next()) + .Take(AddrPayload.MaxCountToSend); + + return peers.Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Services, p.Version.Timestamp)).ToArray(); + } + private void OnRelay(IInventory inventory) { if (inventory is Transaction transaction) diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index a38ad60580..1c52cf2f6f 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -144,13 +144,7 @@ private void OnFilterLoadMessageReceived(FilterLoadPayload payload) private void OnGetAddrMessageReceived() { - Random rand = new Random(); - IEnumerable peers = LocalNode.Singleton.RemoteNodes.Values - .Where(p => p.ListenerPort > 0) - .GroupBy(p => p.Remote.Address, (k, g) => g.First()) - .OrderBy(p => rand.Next()) - .Take(AddrPayload.MaxCountToSend); - NetworkAddressWithTime[] networkAddresses = peers.Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Services, p.Version.Timestamp)).ToArray(); + NetworkAddressWithTime[] networkAddresses = LocalNode.Singleton.GetPeers(); if (networkAddresses.Length == 0) return; Context.Parent.Tell(Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses))); } From 1192b3fae24aed26386843411d2ac4c9a8bdb5ed Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 17:00:39 +0200 Subject: [PATCH 05/42] Clean Peer --- neo/Network/P2P/Peer.cs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index 0a24f1478c..b216c42f77 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -4,8 +4,6 @@ using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; using Neo.IO; -using Neo.Ledger; -using Neo.Network.P2P.Payloads; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -194,7 +192,7 @@ private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesir } } - protected virtual void OnUdpMessage(IPEndPoint remote, ByteString data) { } + protected abstract void OnUdpMessage(IPEndPoint remote, ByteString data) { } protected void SendUdp(IPEndPoint remote, ByteString data) => udp_listener.Tell(Udp.Send.Create(data, remote)); From e284c3703d8103cfff0cd6b775de26c9003fd0ae Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 17:00:56 +0200 Subject: [PATCH 06/42] Fix clean --- neo/Network/P2P/Peer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index b216c42f77..be26420911 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -192,7 +192,7 @@ private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesir } } - protected abstract void OnUdpMessage(IPEndPoint remote, ByteString data) { } + protected abstract void OnUdpMessage(IPEndPoint remote, ByteString data); protected void SendUdp(IPEndPoint remote, ByteString data) => udp_listener.Tell(Udp.Send.Create(data, remote)); From fe42fcd7206876e4cfad646719dfda9d200eded6 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 17:53:08 +0200 Subject: [PATCH 07/42] Refactor VersionPayload --- .../P2P/Capabilities/INodeCapability.cs | 6 +++ .../P2P/Capabilities/NodeCapabilities.cs | 19 +++++++ .../P2P/Capabilities/StringCapability.cs | 38 ++++++++++++++ .../P2P/Capabilities/UInt16Capability.cs | 35 +++++++++++++ neo/Network/P2P/Connection.cs | 2 +- neo/Network/P2P/LocalNode.cs | 2 +- neo/Network/P2P/Payloads/VersionPayload.cs | 51 ++++++++++++++++--- neo/Network/P2P/Peer.cs | 27 ++++++---- neo/Network/P2P/RemoteNode.cs | 18 +++++-- neo/Network/RPC/RpcServer.cs | 6 ++- 10 files changed, 179 insertions(+), 25 deletions(-) create mode 100644 neo/Network/P2P/Capabilities/INodeCapability.cs create mode 100644 neo/Network/P2P/Capabilities/NodeCapabilities.cs create mode 100644 neo/Network/P2P/Capabilities/StringCapability.cs create mode 100644 neo/Network/P2P/Capabilities/UInt16Capability.cs diff --git a/neo/Network/P2P/Capabilities/INodeCapability.cs b/neo/Network/P2P/Capabilities/INodeCapability.cs new file mode 100644 index 0000000000..99753412bd --- /dev/null +++ b/neo/Network/P2P/Capabilities/INodeCapability.cs @@ -0,0 +1,6 @@ +using Neo.IO; + +namespace Neo.Network.P2P.Capabilities +{ + public interface INodeCapability : ISerializable { } +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/NodeCapabilities.cs b/neo/Network/P2P/Capabilities/NodeCapabilities.cs new file mode 100644 index 0000000000..ab50c4fa30 --- /dev/null +++ b/neo/Network/P2P/Capabilities/NodeCapabilities.cs @@ -0,0 +1,19 @@ +using Neo.IO.Caching; + +namespace Neo.Network.P2P.Capabilities +{ + public enum NodeCapabilities : byte + { + [ReflectionCache(typeof(UInt16Capability))] + TcpPort = 0x00, + + [ReflectionCache(typeof(UInt16Capability))] + UdpPort = 0x01, + + [ReflectionCache(typeof(UInt16Capability))] + WebsocketPort = 0x02, + + [ReflectionCache(typeof(StringCapability))] + RpcServerAddress = 0x03 + } +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/StringCapability.cs b/neo/Network/P2P/Capabilities/StringCapability.cs new file mode 100644 index 0000000000..af6e003d39 --- /dev/null +++ b/neo/Network/P2P/Capabilities/StringCapability.cs @@ -0,0 +1,38 @@ +using Neo.IO; +using System.IO; + +namespace Neo.Network.P2P.Capabilities +{ + public class StringCapability : INodeCapability + { + const int MaxStringCapability = byte.MaxValue; + + public string Value { get; set; } + + public int Size => Value.GetVarSize(); + + /// + /// Constructor + /// + public StringCapability() { } + + /// + /// Constructor + /// + /// Value + public StringCapability(string value) + { + Value = value + } + + public void Deserialize(BinaryReader reader) + { + Value = reader.ReadVarString(MaxStringCapability); + } + + public void Serialize(BinaryWriter writer) + { + writer.WriteVarString(Value); + } + } +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/UInt16Capability.cs b/neo/Network/P2P/Capabilities/UInt16Capability.cs new file mode 100644 index 0000000000..efc521e9a4 --- /dev/null +++ b/neo/Network/P2P/Capabilities/UInt16Capability.cs @@ -0,0 +1,35 @@ +using System.IO; + +namespace Neo.Network.P2P.Capabilities +{ + public class UInt16Capability : INodeCapability + { + public ushort Value { get; set; } + + public int Size => sizeof(ushort); + + /// + /// Constructor + /// + public UInt16Capability() { } + + /// + /// Constructor + /// + /// Value + public UInt16Capability(ushort value) + { + Value = value; + } + + public void Deserialize(BinaryReader reader) + { + Value = reader.ReadUInt16(); + } + + public void Serialize(BinaryWriter writer) + { + writer.Write(Value); + } + } +} \ No newline at end of file diff --git a/neo/Network/P2P/Connection.cs b/neo/Network/P2P/Connection.cs index e4c8becec6..10405c94ea 100644 --- a/neo/Network/P2P/Connection.cs +++ b/neo/Network/P2P/Connection.cs @@ -14,7 +14,7 @@ public abstract class Connection : UntypedActor public IPEndPoint Remote { get; } public IPEndPoint Local { get; } - public abstract int ListenerPort { get; } + public abstract int ListenerTcpPort { get; } private ICancelable timer; private readonly IActorRef tcp; diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index 7e1cd3cf14..11fb2be389 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -192,7 +192,7 @@ public NetworkAddressWithTime[] GetPeers() { Random rand = new Random(); IEnumerable peers = RemoteNodes.Values - .Where(p => p.ListenerPort > 0) + .Where(p => p.ListenerTcpPort > 0) .GroupBy(p => p.Remote.Address, (k, g) => g.First()) .OrderBy(p => rand.Next()) .Take(AddrPayload.MaxCountToSend); diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index 0125e4eee0..ee456476a9 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -1,31 +1,42 @@ using Neo.IO; +using Neo.IO.Caching; +using Neo.Network.P2P.Capabilities; using System; +using System.Collections.Generic; using System.IO; +using System.Linq; namespace Neo.Network.P2P.Payloads { public class VersionPayload : ISerializable { + /// + /// Reflection cache for ConsensusMessageType + /// + private static readonly ReflectionCache ReflectionCache = ReflectionCache.CreateFromEnum(); + + const int MaxCapabilities = 32; + public uint Magic; public uint Version; public VersionServices Services; public uint Timestamp; - public ushort Port; public uint Nonce; public string UserAgent; public uint StartHeight; + public Dictionary Capabilities; public int Size => sizeof(uint) + //Magic sizeof(uint) + //Version sizeof(VersionServices) + //Services sizeof(uint) + //Timestamp - sizeof(ushort) + //Port sizeof(uint) + //Nonce UserAgent.GetVarSize() + //UserAgent - sizeof(uint); //StartHeight + sizeof(uint) + //StartHeight + (IO.Helper.GetVarSize(Capabilities.Count) + Capabilities.Values.Sum(u => 1 /*key*/ + u.Size)); //Capabilities - public static VersionPayload Create(int port, uint nonce, string userAgent, uint startHeight) + public static VersionPayload Create(uint nonce, string userAgent, uint startHeight, Dictionary capabilities) { return new VersionPayload { @@ -33,10 +44,10 @@ public static VersionPayload Create(int port, uint nonce, string userAgent, uint Version = LocalNode.ProtocolVersion, Services = VersionServices.FullNode, Timestamp = DateTime.Now.ToTimestamp(), - Port = (ushort)port, Nonce = nonce, UserAgent = userAgent, StartHeight = startHeight, + Capabilities = capabilities, }; } @@ -46,10 +57,28 @@ void ISerializable.Deserialize(BinaryReader reader) Version = reader.ReadUInt32(); Services = (VersionServices)reader.ReadUInt64(); Timestamp = reader.ReadUInt32(); - Port = reader.ReadUInt16(); Nonce = reader.ReadUInt32(); UserAgent = reader.ReadVarString(1024); StartHeight = reader.ReadUInt32(); + + // Capabilities + + Capabilities = new Dictionary(); + + for (var x = reader.ReadVarInt(MaxCapabilities); x > 0; x--) + { + var type = reader.ReadByte(); + + if (!ReflectionCache.TryGetValue(type, out var objType)) + { + throw new FormatException(); + } + + var value = (INodeCapability)Activator.CreateInstance(objType); + value.Deserialize(reader); + + Capabilities.Add((NodeCapabilities)type, value); + } } void ISerializable.Serialize(BinaryWriter writer) @@ -58,10 +87,18 @@ void ISerializable.Serialize(BinaryWriter writer) writer.Write(Version); writer.Write((ulong)Services); writer.Write(Timestamp); - writer.Write(Port); writer.Write(Nonce); writer.WriteVarString(UserAgent); writer.Write(StartHeight); + + // Capabilities + + writer.WriteVarInt(Capabilities.Count); + foreach (var keyValue in Capabilities) + { + writer.Write((byte)keyValue.Key); + keyValue.Value.Serialize(writer); + } } } } diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index be26420911..b0d0dc396e 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -43,7 +43,9 @@ private class WsConnected { public WebSocket Socket; public IPEndPoint Remote; p protected ImmutableHashSet ConnectingPeers = ImmutableHashSet.Empty; protected HashSet TrustedIpAddresses { get; } = new HashSet(); - public int ListenerPort { get; private set; } + public int ListenerTcpPort { get; private set; } + public int ListenerUdpPort { get; private set; } + public int ListenerWsPort { get; private set; } public int MaxConnectionsPerAddress { get; private set; } = 3; public int MinDesiredConnections { get; private set; } = DefaultMinDesiredConnections; public int MaxConnections { get; private set; } = DefaultMaxConnections; @@ -68,7 +70,7 @@ protected void AddPeers(IEnumerable peers) { if (UnconnectedPeers.Count < UnconnectedMax) { - peers = peers.Where(p => p.Port != ListenerPort || !localAddresses.Contains(p.Address)); + peers = peers.Where(p => p.Port != ListenerTcpPort || !localAddresses.Contains(p.Address)); ImmutableInterlocked.Update(ref UnconnectedPeers, p => p.Union(peers)); } } @@ -76,7 +78,7 @@ protected void AddPeers(IEnumerable peers) protected void ConnectToPeer(IPEndPoint endPoint, bool isTrusted = false) { endPoint = endPoint.Unmap(); - if (endPoint.Port == ListenerPort && localAddresses.Contains(endPoint.Address)) return; + if (endPoint.Port == ListenerTcpPort && localAddresses.Contains(endPoint.Address)) return; if (isTrusted) TrustedIpAddresses.Add(endPoint.Address); if (ConnectedAddresses.TryGetValue(endPoint.Address, out int count) && count >= MaxConnectionsPerAddress) @@ -148,31 +150,34 @@ protected override void OnReceive(object message) private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesiredConnections, int maxConnections, int maxConnectionsPerAddress) { - ListenerPort = tcp == null ? 0 : tcp.Port; + ListenerTcpPort = tcp == null ? 0 : tcp.Port; + ListenerTcpPort = udp == null ? 0 : udp.Port; + ListenerWsPort = ws == null ? 0 : ws.Port; + MinDesiredConnections = minDesiredConnections; MaxConnections = maxConnections; MaxConnectionsPerAddress = maxConnectionsPerAddress; timer = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(0, 5000, Context.Self, new Timer(), ActorRefs.NoSender); - if ((ListenerPort > 0 || (ws != null && ws.Port > 0)) + if ((ListenerTcpPort > 0 || ListenerWsPort > 0) && localAddresses.All(p => !p.IsIPv4MappedToIPv6 || IsIntranetAddress(p)) && UPnP.Discover()) { try { localAddresses.Add(UPnP.GetExternalIP()); - if (ListenerPort > 0) - UPnP.ForwardPort(ListenerPort, ProtocolType.Tcp, "NEO"); + if (ListenerTcpPort > 0) + UPnP.ForwardPort(ListenerTcpPort, ProtocolType.Tcp, "NEO"); if (ws != null && ws.Port > 0) UPnP.ForwardPort(ws.Port, ProtocolType.Tcp, "NEO WebSocket"); } catch { } } - if (ListenerPort > 0) + if (ListenerTcpPort > 0) { tcp_manager.Tell(new Tcp.Bind(Self, tcp, options: new[] { new Inet.SO.ReuseAddress(true) })); } - if (ws != null && ws.Port > 0) + if (ListenerWsPort > 0) { var host = "*"; @@ -183,10 +188,10 @@ private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesir host = ws.Address.ToString(); } - ws_host = new WebHostBuilder().UseKestrel().UseUrls($"http://{host}:{ws.Port}").Configure(app => app.UseWebSockets().Run(ProcessWebSocketAsync)).Build(); + ws_host = new WebHostBuilder().UseKestrel().UseUrls($"http://{host}:{ListenerWsPort}").Configure(app => app.UseWebSockets().Run(ProcessWebSocketAsync)).Build(); ws_host.Start(); } - if (udp != null && udp.Port > 0) + if (ListenerUdpPort > 0) { udp_manager.Tell(new Udp.Bind(Self, udp)); } diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 5a0381e04f..6c7378860c 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -5,6 +5,7 @@ using Neo.IO; using Neo.IO.Actors; using Neo.Ledger; +using Neo.Network.P2P.Capabilities; using Neo.Network.P2P.Payloads; using System.Collections.Generic; using System.Linq; @@ -25,8 +26,12 @@ internal class Relay { public IInventory Inventory; } private bool ack = true; private bool verack = false; - public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerPort); - public override int ListenerPort => Version?.Port ?? 0; + public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); + public override int ListenerTcpPort => Version?.Capabilities + .Where(u => u.Key == NodeCapabilities.TcpPort) + .Select(u => u.Value) + .Cast() + .First()?.Value ?? 0; public VersionPayload Version { get; private set; } public uint LastBlockIndex { get; private set; } @@ -37,7 +42,14 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP this.protocol = Context.ActorOf(ProtocolHandler.Props(system)); LocalNode.Singleton.RemoteNodes.TryAdd(Self, this); - SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Singleton.ListenerPort, LocalNode.Nonce, LocalNode.UserAgent, Blockchain.Singleton.Height))); + var capabilities = new Dictionary(); + + if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(NodeCapabilities.TcpPort, new UInt16Capability((ushort)LocalNode.Singleton.ListenerTcpPort)); + if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(NodeCapabilities.UdpPort, new UInt16Capability((ushort)LocalNode.Singleton.ListenerUdpPort)); + if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(NodeCapabilities.WebsocketPort, new UInt16Capability((ushort)LocalNode.Singleton.ListenerWsPort)); + + SendMessage(Message.Create(MessageCommand.Version, + VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, Blockchain.Singleton.Height, capabilities))); } private void CheckMessageQueue() diff --git a/neo/Network/RPC/RpcServer.cs b/neo/Network/RPC/RpcServer.cs index b3b14470f7..8066acd54b 100644 --- a/neo/Network/RPC/RpcServer.cs +++ b/neo/Network/RPC/RpcServer.cs @@ -503,7 +503,7 @@ private JObject GetPeers() { JObject peerJson = new JObject(); peerJson["address"] = p.Remote.Address.ToString(); - peerJson["port"] = p.ListenerPort; + peerJson["tcpPort"] = p.ListenerTcpPort; return peerJson; })); return json; @@ -586,7 +586,9 @@ private JObject GetValidators() private JObject GetVersion() { JObject json = new JObject(); - json["port"] = LocalNode.Singleton.ListenerPort; + json["tcpPort"] = LocalNode.Singleton.ListenerTcpPort; + json["udpPort"] = LocalNode.Singleton.ListenerUdpPort; + json["wsPort"] = LocalNode.Singleton.ListenerWsPort; json["nonce"] = LocalNode.Nonce; json["useragent"] = LocalNode.UserAgent; return json; From b466f9d60c8a9acebc6f346951b069cb42ec24bb Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 17:56:31 +0200 Subject: [PATCH 08/42] Fix --- neo/Network/P2P/Peer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index b0d0dc396e..fbadd688cd 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -151,7 +151,7 @@ protected override void OnReceive(object message) private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesiredConnections, int maxConnections, int maxConnectionsPerAddress) { ListenerTcpPort = tcp == null ? 0 : tcp.Port; - ListenerTcpPort = udp == null ? 0 : udp.Port; + ListenerUdpPort = udp == null ? 0 : udp.Port; ListenerWsPort = ws == null ? 0 : ws.Port; MinDesiredConnections = minDesiredConnections; From 3a54118f3c002088aa96040bf4acc77e948f37ee Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 17:57:30 +0200 Subject: [PATCH 09/42] Unit test --- neo.UnitTests/UT_P2PMessage.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/UT_P2PMessage.cs index ee27228a2e..494754c8f4 100644 --- a/neo.UnitTests/UT_P2PMessage.cs +++ b/neo.UnitTests/UT_P2PMessage.cs @@ -3,7 +3,9 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using Neo.IO; using Neo.Network.P2P; +using Neo.Network.P2P.Capabilities; using Neo.Network.P2P.Payloads; +using System.Collections.Generic; namespace Neo.UnitTests { @@ -81,12 +83,17 @@ public void Compression() { UserAgent = "".PadLeft(1024, '0'), Nonce = 1, - Port = 2, + Magic = 2, Services = VersionServices.FullNode, StartHeight = 4, Timestamp = 5, - Version = 6 + Version = 6, + Capabilities = new Dictionary() }; + + payload.Capabilities.Add(NodeCapabilities.TcpPort, new UInt16Capability() { Value = 25 }); + payload.Capabilities.Add(NodeCapabilities.RpcServerAddress, new StringCapability() { Value = "".PadLeft(32, 'Z') }); + var msg = Message.Create(MessageCommand.Version, payload); var buffer = msg.ToArray(); @@ -100,11 +107,16 @@ public void Compression() payloadCopy.UserAgent.Should().Be(payload.UserAgent); payloadCopy.Nonce.Should().Be(payload.Nonce); - payloadCopy.Port.Should().Be(payload.Port); + payloadCopy.Magic.Should().Be(payload.Magic); payloadCopy.Services.Should().Be(payload.Services); payloadCopy.StartHeight.Should().Be(payload.StartHeight); payloadCopy.Timestamp.Should().Be(payload.Timestamp); payloadCopy.Version.Should().Be(payload.Version); + + payloadCopy.Capabilities.Count.Should().Be(2); + ((UInt16Capability)payloadCopy.Capabilities[NodeCapabilities.TcpPort]).Value.Should().Be(25); + ((StringCapability)payloadCopy.Capabilities[NodeCapabilities.RpcServerAddress]).Value.Should().Be("".PadLeft(32, 'Z')); + } } } \ No newline at end of file From 54a3087e17fdeb16a524988270567d7d3a76afe6 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 17:59:28 +0200 Subject: [PATCH 10/42] Clean code --- neo/Network/P2P/Peer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index fbadd688cd..dc2cef54d7 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -168,7 +168,7 @@ private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesir localAddresses.Add(UPnP.GetExternalIP()); if (ListenerTcpPort > 0) UPnP.ForwardPort(ListenerTcpPort, ProtocolType.Tcp, "NEO"); - if (ws != null && ws.Port > 0) + if (ListenerWsPort > 0) UPnP.ForwardPort(ws.Port, ProtocolType.Tcp, "NEO WebSocket"); } catch { } From 2c4fc4151b86fdea0f8d0d167227f5efa5bd2bd8 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 18:09:00 +0200 Subject: [PATCH 11/42] Clean line --- neo/Network/P2P/Peer.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index dc2cef54d7..65b7dfa9b3 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -184,7 +184,6 @@ private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesir if (!ws.Address.GetAddressBytes().SequenceEqual(IPAddress.Any.GetAddressBytes())) { // Is not for all interfaces - host = ws.Address.ToString(); } From ee2c9f0fa4bbeea73196658d4e793a7373681542 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 20:28:40 +0200 Subject: [PATCH 12/42] Fix ut --- neo/Network/P2P/Capabilities/StringCapability.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/neo/Network/P2P/Capabilities/StringCapability.cs b/neo/Network/P2P/Capabilities/StringCapability.cs index af6e003d39..e99cf9b01c 100644 --- a/neo/Network/P2P/Capabilities/StringCapability.cs +++ b/neo/Network/P2P/Capabilities/StringCapability.cs @@ -22,7 +22,7 @@ public StringCapability() { } /// Value public StringCapability(string value) { - Value = value + Value = value; } public void Deserialize(BinaryReader reader) From 77a0b1c3a177e0a1eaa643d219b95edd9689a18d Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 10 May 2019 20:48:12 +0200 Subject: [PATCH 13/42] Simplify VersionPayload capabilities --- neo.UnitTests/UT_P2PMessage.cs | 11 +++--- .../P2P/Capabilities/INodeCapability.cs | 5 ++- .../P2P/Capabilities/NodeCapabilities.cs | 13 +------ ...Int16Capability.cs => ServerCapability.cs} | 21 ++++++++-- .../P2P/Capabilities/StringCapability.cs | 38 ------------------- neo/Network/P2P/Payloads/VersionPayload.cs | 16 ++++---- neo/Network/P2P/RemoteNode.cs | 13 +++---- 7 files changed, 42 insertions(+), 75 deletions(-) rename neo/Network/P2P/Capabilities/{UInt16Capability.cs => ServerCapability.cs} (51%) delete mode 100644 neo/Network/P2P/Capabilities/StringCapability.cs diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/UT_P2PMessage.cs index 494754c8f4..038a1f612e 100644 --- a/neo.UnitTests/UT_P2PMessage.cs +++ b/neo.UnitTests/UT_P2PMessage.cs @@ -88,11 +88,10 @@ public void Compression() StartHeight = 4, Timestamp = 5, Version = 6, - Capabilities = new Dictionary() + Capabilities = new List() }; - payload.Capabilities.Add(NodeCapabilities.TcpPort, new UInt16Capability() { Value = 25 }); - payload.Capabilities.Add(NodeCapabilities.RpcServerAddress, new StringCapability() { Value = "".PadLeft(32, 'Z') }); + payload.Capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Tcp, 25)); var msg = Message.Create(MessageCommand.Version, payload); var buffer = msg.ToArray(); @@ -113,9 +112,9 @@ public void Compression() payloadCopy.Timestamp.Should().Be(payload.Timestamp); payloadCopy.Version.Should().Be(payload.Version); - payloadCopy.Capabilities.Count.Should().Be(2); - ((UInt16Capability)payloadCopy.Capabilities[NodeCapabilities.TcpPort]).Value.Should().Be(25); - ((StringCapability)payloadCopy.Capabilities[NodeCapabilities.RpcServerAddress]).Value.Should().Be("".PadLeft(32, 'Z')); + payloadCopy.Capabilities.Count.Should().Be(1); + ((ServerCapability)payloadCopy.Capabilities[0]).Channel.Should().Be(ServerCapability.ChannelType.Tcp); + ((ServerCapability)payloadCopy.Capabilities[0]).Value.Should().Be(25); } } diff --git a/neo/Network/P2P/Capabilities/INodeCapability.cs b/neo/Network/P2P/Capabilities/INodeCapability.cs index 99753412bd..6f47a56316 100644 --- a/neo/Network/P2P/Capabilities/INodeCapability.cs +++ b/neo/Network/P2P/Capabilities/INodeCapability.cs @@ -2,5 +2,8 @@ namespace Neo.Network.P2P.Capabilities { - public interface INodeCapability : ISerializable { } + public interface INodeCapability : ISerializable + { + NodeCapabilities Type { get; } + } } \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/NodeCapabilities.cs b/neo/Network/P2P/Capabilities/NodeCapabilities.cs index ab50c4fa30..4577472c53 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilities.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilities.cs @@ -4,16 +4,7 @@ namespace Neo.Network.P2P.Capabilities { public enum NodeCapabilities : byte { - [ReflectionCache(typeof(UInt16Capability))] - TcpPort = 0x00, - - [ReflectionCache(typeof(UInt16Capability))] - UdpPort = 0x01, - - [ReflectionCache(typeof(UInt16Capability))] - WebsocketPort = 0x02, - - [ReflectionCache(typeof(StringCapability))] - RpcServerAddress = 0x03 + [ReflectionCache(typeof(ServerCapability))] + Server = 0x00, } } \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/UInt16Capability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs similarity index 51% rename from neo/Network/P2P/Capabilities/UInt16Capability.cs rename to neo/Network/P2P/Capabilities/ServerCapability.cs index efc521e9a4..83e6b23f63 100644 --- a/neo/Network/P2P/Capabilities/UInt16Capability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -2,33 +2,46 @@ namespace Neo.Network.P2P.Capabilities { - public class UInt16Capability : INodeCapability + public class ServerCapability : INodeCapability { - public ushort Value { get; set; } + public enum ChannelType : byte + { + Tcp = 0x00, + Udp = 0x01, + Websocket = 0x02 + } + public ChannelType Channel { get; set; } + public ushort Value { get; set; } public int Size => sizeof(ushort); + public NodeCapabilities Type => NodeCapabilities.Server; + /// /// Constructor /// - public UInt16Capability() { } + public ServerCapability() { } /// /// Constructor /// + /// Type /// Value - public UInt16Capability(ushort value) + public ServerCapability(ChannelType type, ushort value) { + Channel = type; Value = value; } public void Deserialize(BinaryReader reader) { + Channel = (ChannelType)reader.ReadByte(); Value = reader.ReadUInt16(); } public void Serialize(BinaryWriter writer) { + writer.Write((byte)Type); writer.Write(Value); } } diff --git a/neo/Network/P2P/Capabilities/StringCapability.cs b/neo/Network/P2P/Capabilities/StringCapability.cs deleted file mode 100644 index e99cf9b01c..0000000000 --- a/neo/Network/P2P/Capabilities/StringCapability.cs +++ /dev/null @@ -1,38 +0,0 @@ -using Neo.IO; -using System.IO; - -namespace Neo.Network.P2P.Capabilities -{ - public class StringCapability : INodeCapability - { - const int MaxStringCapability = byte.MaxValue; - - public string Value { get; set; } - - public int Size => Value.GetVarSize(); - - /// - /// Constructor - /// - public StringCapability() { } - - /// - /// Constructor - /// - /// Value - public StringCapability(string value) - { - Value = value; - } - - public void Deserialize(BinaryReader reader) - { - Value = reader.ReadVarString(MaxStringCapability); - } - - public void Serialize(BinaryWriter writer) - { - writer.WriteVarString(Value); - } - } -} \ No newline at end of file diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index ee456476a9..76ec728791 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -24,7 +24,7 @@ public class VersionPayload : ISerializable public uint Nonce; public string UserAgent; public uint StartHeight; - public Dictionary Capabilities; + public List Capabilities; public int Size => sizeof(uint) + //Magic @@ -34,9 +34,9 @@ public class VersionPayload : ISerializable sizeof(uint) + //Nonce UserAgent.GetVarSize() + //UserAgent sizeof(uint) + //StartHeight - (IO.Helper.GetVarSize(Capabilities.Count) + Capabilities.Values.Sum(u => 1 /*key*/ + u.Size)); //Capabilities + (IO.Helper.GetVarSize(Capabilities.Count) + Capabilities.Sum(u => 1 /* Type */ + u.Size)); //Capabilities - public static VersionPayload Create(uint nonce, string userAgent, uint startHeight, Dictionary capabilities) + public static VersionPayload Create(uint nonce, string userAgent, uint startHeight, List capabilities) { return new VersionPayload { @@ -63,7 +63,7 @@ void ISerializable.Deserialize(BinaryReader reader) // Capabilities - Capabilities = new Dictionary(); + Capabilities = new List(); for (var x = reader.ReadVarInt(MaxCapabilities); x > 0; x--) { @@ -77,7 +77,7 @@ void ISerializable.Deserialize(BinaryReader reader) var value = (INodeCapability)Activator.CreateInstance(objType); value.Deserialize(reader); - Capabilities.Add((NodeCapabilities)type, value); + Capabilities.Add(value); } } @@ -94,10 +94,10 @@ void ISerializable.Serialize(BinaryWriter writer) // Capabilities writer.WriteVarInt(Capabilities.Count); - foreach (var keyValue in Capabilities) + foreach (var value in Capabilities) { - writer.Write((byte)keyValue.Key); - keyValue.Value.Serialize(writer); + writer.Write((byte)value.Type); + value.Serialize(writer); } } } diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 6c7378860c..f01b0c8d5e 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -28,9 +28,8 @@ internal class Relay { public IInventory Inventory; } public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); public override int ListenerTcpPort => Version?.Capabilities - .Where(u => u.Key == NodeCapabilities.TcpPort) - .Select(u => u.Value) - .Cast() + .Where(u => u.Type == NodeCapabilities.Server) + .Cast() .First()?.Value ?? 0; public VersionPayload Version { get; private set; } public uint LastBlockIndex { get; private set; } @@ -42,11 +41,11 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP this.protocol = Context.ActorOf(ProtocolHandler.Props(system)); LocalNode.Singleton.RemoteNodes.TryAdd(Self, this); - var capabilities = new Dictionary(); + var capabilities = new List(); - if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(NodeCapabilities.TcpPort, new UInt16Capability((ushort)LocalNode.Singleton.ListenerTcpPort)); - if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(NodeCapabilities.UdpPort, new UInt16Capability((ushort)LocalNode.Singleton.ListenerUdpPort)); - if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(NodeCapabilities.WebsocketPort, new UInt16Capability((ushort)LocalNode.Singleton.ListenerWsPort)); + if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Tcp, (ushort)LocalNode.Singleton.ListenerTcpPort)); + if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Udp, (ushort)LocalNode.Singleton.ListenerUdpPort)); + if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Websocket, (ushort)LocalNode.Singleton.ListenerWsPort)); SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, Blockchain.Singleton.Height, capabilities))); From 2215a55a70bbd8ebda7fd99166e00d60a688c42c Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 11 May 2019 10:46:42 +0200 Subject: [PATCH 14/42] Refactor VersionPayload capabilities --- neo.UnitTests/UT_P2PMessage.cs | 11 +++--- .../P2P/Capabilities/INodeCapability.cs | 9 ----- .../P2P/Capabilities/NodeCapabilityBase.cs | 38 +++++++++++++++++++ .../P2P/Capabilities/ServerCapability.cs | 33 +++++++++------- neo/Network/P2P/Payloads/VersionPayload.cs | 23 ++++++----- neo/Network/P2P/RemoteNode.cs | 4 +- 6 files changed, 76 insertions(+), 42 deletions(-) delete mode 100644 neo/Network/P2P/Capabilities/INodeCapability.cs create mode 100644 neo/Network/P2P/Capabilities/NodeCapabilityBase.cs diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/UT_P2PMessage.cs index 038a1f612e..6b10b6beba 100644 --- a/neo.UnitTests/UT_P2PMessage.cs +++ b/neo.UnitTests/UT_P2PMessage.cs @@ -88,11 +88,12 @@ public void Compression() StartHeight = 4, Timestamp = 5, Version = 6, - Capabilities = new List() + Capabilities = new NodeCapabilityBase[] + { + new ServerCapability(ServerCapability.ChannelType.Tcp, 25) + } }; - payload.Capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Tcp, 25)); - var msg = Message.Create(MessageCommand.Version, payload); var buffer = msg.ToArray(); @@ -112,9 +113,9 @@ public void Compression() payloadCopy.Timestamp.Should().Be(payload.Timestamp); payloadCopy.Version.Should().Be(payload.Version); - payloadCopy.Capabilities.Count.Should().Be(1); + payloadCopy.Capabilities.Length.Should().Be(1); ((ServerCapability)payloadCopy.Capabilities[0]).Channel.Should().Be(ServerCapability.ChannelType.Tcp); - ((ServerCapability)payloadCopy.Capabilities[0]).Value.Should().Be(25); + ((ServerCapability)payloadCopy.Capabilities[0]).Port.Should().Be(25); } } diff --git a/neo/Network/P2P/Capabilities/INodeCapability.cs b/neo/Network/P2P/Capabilities/INodeCapability.cs deleted file mode 100644 index 6f47a56316..0000000000 --- a/neo/Network/P2P/Capabilities/INodeCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Neo.IO; - -namespace Neo.Network.P2P.Capabilities -{ - public interface INodeCapability : ISerializable - { - NodeCapabilities Type { get; } - } -} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs new file mode 100644 index 0000000000..bedd6fcc72 --- /dev/null +++ b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs @@ -0,0 +1,38 @@ +using Neo.IO; +using System; +using System.IO; + +namespace Neo.Network.P2P.Capabilities +{ + public abstract class NodeCapabilityBase : ISerializable + { + public virtual int Size => 1; + + /// + /// Type + /// + public NodeCapabilities Type { get; } + + /// + /// Constructor + /// + /// Type + protected NodeCapabilityBase(NodeCapabilities type) + { + Type = type; + } + + public virtual void Deserialize(BinaryReader reader) + { + if (reader.ReadByte() != (byte)Type) + { + throw new FormatException(); + } + } + + public virtual void Serialize(BinaryWriter writer) + { + writer.Write((byte)Type); + } + } +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index 83e6b23f63..f16947282f 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -2,7 +2,7 @@ namespace Neo.Network.P2P.Capabilities { - public class ServerCapability : INodeCapability + public class ServerCapability : NodeCapabilityBase { public enum ChannelType : byte { @@ -12,37 +12,42 @@ public enum ChannelType : byte } public ChannelType Channel { get; set; } - public ushort Value { get; set; } - public int Size => sizeof(ushort); - - public NodeCapabilities Type => NodeCapabilities.Server; + public ushort Port { get; set; } + public override int Size => + base.Size + // Type + sizeof(byte) + // Channel + sizeof(ushort); //Port /// /// Constructor /// - public ServerCapability() { } + public ServerCapability() : base(NodeCapabilities.Server) { } /// /// Constructor /// - /// Type - /// Value - public ServerCapability(ChannelType type, ushort value) + /// Channel + /// Port + public ServerCapability(ChannelType type, ushort port) : base(NodeCapabilities.Server) { Channel = type; - Value = value; + Port = port; } - public void Deserialize(BinaryReader reader) + public override void Deserialize(BinaryReader reader) { + base.Deserialize(reader); + Channel = (ChannelType)reader.ReadByte(); - Value = reader.ReadUInt16(); + Port = reader.ReadUInt16(); } - public void Serialize(BinaryWriter writer) + public override void Serialize(BinaryWriter writer) { + base.Serialize(writer); + writer.Write((byte)Type); - writer.Write(Value); + writer.Write(Port); } } } \ No newline at end of file diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index 76ec728791..00829dd22f 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -24,7 +24,7 @@ public class VersionPayload : ISerializable public uint Nonce; public string UserAgent; public uint StartHeight; - public List Capabilities; + public NodeCapabilityBase[] Capabilities; public int Size => sizeof(uint) + //Magic @@ -34,9 +34,9 @@ public class VersionPayload : ISerializable sizeof(uint) + //Nonce UserAgent.GetVarSize() + //UserAgent sizeof(uint) + //StartHeight - (IO.Helper.GetVarSize(Capabilities.Count) + Capabilities.Sum(u => 1 /* Type */ + u.Size)); //Capabilities + Capabilities.GetVarSize(); //Capabilities - public static VersionPayload Create(uint nonce, string userAgent, uint startHeight, List capabilities) + public static VersionPayload Create(uint nonce, string userAgent, uint startHeight, IEnumerable capabilities) { return new VersionPayload { @@ -47,7 +47,7 @@ public static VersionPayload Create(uint nonce, string userAgent, uint startHeig Nonce = nonce, UserAgent = userAgent, StartHeight = startHeight, - Capabilities = capabilities, + Capabilities = capabilities.ToArray(), }; } @@ -63,21 +63,21 @@ void ISerializable.Deserialize(BinaryReader reader) // Capabilities - Capabilities = new List(); + Capabilities = new NodeCapabilityBase[reader.ReadVarInt(MaxCapabilities)]; - for (var x = reader.ReadVarInt(MaxCapabilities); x > 0; x--) + for (int x = 0, max = Capabilities.Length; x < max; x++) { - var type = reader.ReadByte(); + var type = reader.PeekChar(); - if (!ReflectionCache.TryGetValue(type, out var objType)) + if (!ReflectionCache.TryGetValue((byte)type, out var objType)) { throw new FormatException(); } - var value = (INodeCapability)Activator.CreateInstance(objType); + var value = (NodeCapabilityBase)Activator.CreateInstance(objType); value.Deserialize(reader); - Capabilities.Add(value); + Capabilities[x] = value; } } @@ -93,10 +93,9 @@ void ISerializable.Serialize(BinaryWriter writer) // Capabilities - writer.WriteVarInt(Capabilities.Count); + writer.WriteVarInt(Capabilities.Length); foreach (var value in Capabilities) { - writer.Write((byte)value.Type); value.Serialize(writer); } } diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index f01b0c8d5e..86d1ac836b 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -30,7 +30,7 @@ internal class Relay { public IInventory Inventory; } public override int ListenerTcpPort => Version?.Capabilities .Where(u => u.Type == NodeCapabilities.Server) .Cast() - .First()?.Value ?? 0; + .First()?.Port ?? 0; public VersionPayload Version { get; private set; } public uint LastBlockIndex { get; private set; } @@ -41,7 +41,7 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP this.protocol = Context.ActorOf(ProtocolHandler.Props(system)); LocalNode.Singleton.RemoteNodes.TryAdd(Self, this); - var capabilities = new List(); + var capabilities = new List(); if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Tcp, (ushort)LocalNode.Singleton.ListenerTcpPort)); if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Udp, (ushort)LocalNode.Singleton.ListenerUdpPort)); From ace3153ce2a660ba75602f50393d407898625636 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 11 May 2019 10:49:33 +0200 Subject: [PATCH 15/42] rename NodeConfig to ChannelsStartConfig --- neo/{NodeStartConfig.cs => ChannelsStartConfig.cs} | 2 +- neo/NeoSystem.cs | 4 ++-- neo/Network/P2P/Peer.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) rename neo/{NodeStartConfig.cs => ChannelsStartConfig.cs} (96%) diff --git a/neo/NodeStartConfig.cs b/neo/ChannelsStartConfig.cs similarity index 96% rename from neo/NodeStartConfig.cs rename to neo/ChannelsStartConfig.cs index 5473bca22d..c66c74c59c 100644 --- a/neo/NodeStartConfig.cs +++ b/neo/ChannelsStartConfig.cs @@ -2,7 +2,7 @@ namespace Neo { - public class NodeStartConfig + public class ChannelsStartConfig { /// /// Tcp configuration diff --git a/neo/NeoSystem.cs b/neo/NeoSystem.cs index 439b4cbe77..82dbdcaba9 100644 --- a/neo/NeoSystem.cs +++ b/neo/NeoSystem.cs @@ -28,7 +28,7 @@ public class NeoSystem : IDisposable public RpcServer RpcServer { get; private set; } private readonly Store store; - private NodeStartConfig start_message = null; + private ChannelsStartConfig start_message = null; private bool suspend = false; public NeoSystem(Store store) @@ -74,7 +74,7 @@ public void StartConsensus(Wallet wallet, Store consensus_store = null, bool ign Consensus.Tell(new ConsensusService.Start { IgnoreRecoveryLogs = ignoreRecoveryLogs }, Blockchain); } - public void StartNode(NodeStartConfig cfg) + public void StartNode(ChannelsStartConfig cfg) { start_message = cfg; diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index 65b7dfa9b3..3801847854 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -106,7 +106,7 @@ protected override void OnReceive(object message) { switch (message) { - case NodeStartConfig start: + case ChannelsStartConfig start: OnStart ( start.Tcp != null && start.Tcp.IsValid ? start.Tcp.EndPoint : null, From 72b82cf217da2ed70c96c63489f5d8cd9ddca22f Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 11 May 2019 10:52:06 +0200 Subject: [PATCH 16/42] Clean code --- neo/Network/P2P/Capabilities/ServerCapability.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index f16947282f..1f6fb62a13 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -12,11 +12,13 @@ public enum ChannelType : byte } public ChannelType Channel { get; set; } + public ushort Port { get; set; } + public override int Size => base.Size + // Type sizeof(byte) + // Channel - sizeof(ushort); //Port + sizeof(ushort); // Port /// /// Constructor @@ -50,4 +52,4 @@ public override void Serialize(BinaryWriter writer) writer.Write(Port); } } -} \ No newline at end of file +} From 2e8d5589e8b9b78f7cd62570a5bc2897263411fe Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 11 May 2019 10:53:49 +0200 Subject: [PATCH 17/42] Clean code --- neo/Network/P2P/Payloads/VersionPayload.cs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index 00829dd22f..fae5518cca 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -27,14 +27,14 @@ public class VersionPayload : ISerializable public NodeCapabilityBase[] Capabilities; public int Size => - sizeof(uint) + //Magic - sizeof(uint) + //Version - sizeof(VersionServices) + //Services - sizeof(uint) + //Timestamp - sizeof(uint) + //Nonce - UserAgent.GetVarSize() + //UserAgent - sizeof(uint) + //StartHeight - Capabilities.GetVarSize(); //Capabilities + sizeof(uint) + // Magic + sizeof(uint) + // Version + sizeof(VersionServices) + // Services + sizeof(uint) + // Timestamp + sizeof(uint) + // Nonce + UserAgent.GetVarSize() + // UserAgent + sizeof(uint) + // StartHeight + Capabilities.GetVarSize(); // Capabilities public static VersionPayload Create(uint nonce, string userAgent, uint startHeight, IEnumerable capabilities) { From be1b889b600c56efc5dfb656844839fb4feab057 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 11 May 2019 10:56:26 +0200 Subject: [PATCH 18/42] UPnP for Udp port --- neo/Network/P2P/Peer.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index 3801847854..68024e5be7 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -159,17 +159,17 @@ private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesir MaxConnectionsPerAddress = maxConnectionsPerAddress; timer = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(0, 5000, Context.Self, new Timer(), ActorRefs.NoSender); - if ((ListenerTcpPort > 0 || ListenerWsPort > 0) + if ((ListenerTcpPort > 0 || ListenerWsPort > 0 || ListenerUdpPort > 0) && localAddresses.All(p => !p.IsIPv4MappedToIPv6 || IsIntranetAddress(p)) && UPnP.Discover()) { try { localAddresses.Add(UPnP.GetExternalIP()); - if (ListenerTcpPort > 0) - UPnP.ForwardPort(ListenerTcpPort, ProtocolType.Tcp, "NEO"); - if (ListenerWsPort > 0) - UPnP.ForwardPort(ws.Port, ProtocolType.Tcp, "NEO WebSocket"); + + if (ListenerTcpPort > 0) UPnP.ForwardPort(ListenerTcpPort, ProtocolType.Tcp, "NEO Tcp"); + if (ListenerUdpPort > 0) UPnP.ForwardPort(udp.Port, ProtocolType.Udp, "NEO Udp"); + if (ListenerWsPort > 0) UPnP.ForwardPort(ws.Port, ProtocolType.Tcp, "NEO WebSocket"); } catch { } } From 9485a03897556851bfe9e5c9186e3f7ae526a188 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sat, 11 May 2019 10:58:17 +0200 Subject: [PATCH 19/42] Fx for ListennerTcpPort --- neo/Network/P2P/RemoteNode.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 86d1ac836b..6eafbd730b 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -30,6 +30,7 @@ internal class Relay { public IInventory Inventory; } public override int ListenerTcpPort => Version?.Capabilities .Where(u => u.Type == NodeCapabilities.Server) .Cast() + .Where(u => u.Channel == ServerCapability.ChannelType.Tcp) .First()?.Port ?? 0; public VersionPayload Version { get; private set; } public uint LastBlockIndex { get; private set; } From 6d80ec187c790af2c011cbe6610742b9335cf4fe Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 12 May 2019 09:22:52 +0200 Subject: [PATCH 20/42] Combine NodeCapabilities with ChannelType --- neo.UnitTests/UT_P2PMessage.cs | 6 ++-- .../P2P/Capabilities/NodeCapabilities.cs | 10 ++++-- .../P2P/Capabilities/ServerCapability.cs | 34 ++++++------------- .../P2P/Capabilities/TcpServerCapability.cs | 9 +++++ .../P2P/Capabilities/UdpServerCapability.cs | 9 +++++ .../P2P/Capabilities/WsServerCapability.cs | 9 +++++ neo/Network/P2P/RemoteNode.cs | 11 +++--- 7 files changed, 53 insertions(+), 35 deletions(-) create mode 100644 neo/Network/P2P/Capabilities/TcpServerCapability.cs create mode 100644 neo/Network/P2P/Capabilities/UdpServerCapability.cs create mode 100644 neo/Network/P2P/Capabilities/WsServerCapability.cs diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/UT_P2PMessage.cs index 6b10b6beba..7f82a9efa3 100644 --- a/neo.UnitTests/UT_P2PMessage.cs +++ b/neo.UnitTests/UT_P2PMessage.cs @@ -90,7 +90,7 @@ public void Compression() Version = 6, Capabilities = new NodeCapabilityBase[] { - new ServerCapability(ServerCapability.ChannelType.Tcp, 25) + new TcpServerCapability(25) } }; @@ -114,8 +114,8 @@ public void Compression() payloadCopy.Version.Should().Be(payload.Version); payloadCopy.Capabilities.Length.Should().Be(1); - ((ServerCapability)payloadCopy.Capabilities[0]).Channel.Should().Be(ServerCapability.ChannelType.Tcp); - ((ServerCapability)payloadCopy.Capabilities[0]).Port.Should().Be(25); + ((TcpServerCapability)payloadCopy.Capabilities[0]).Type.Should().Be(NodeCapabilities.TcpServer); + ((TcpServerCapability)payloadCopy.Capabilities[0]).Port.Should().Be(25); } } diff --git a/neo/Network/P2P/Capabilities/NodeCapabilities.cs b/neo/Network/P2P/Capabilities/NodeCapabilities.cs index 4577472c53..dcbc44977f 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilities.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilities.cs @@ -4,7 +4,13 @@ namespace Neo.Network.P2P.Capabilities { public enum NodeCapabilities : byte { - [ReflectionCache(typeof(ServerCapability))] - Server = 0x00, + [ReflectionCache(typeof(TcpServerCapability))] + TcpServer = 0x01, + + [ReflectionCache(typeof(UdpServerCapability))] + UdpServer = 0x02, + + [ReflectionCache(typeof(WsServerCapability))] + WsServer = 0x03, } } \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index 1f6fb62a13..cb21f7aea8 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -1,55 +1,41 @@ -using System.IO; +using System; +using System.IO; namespace Neo.Network.P2P.Capabilities { public class ServerCapability : NodeCapabilityBase { - public enum ChannelType : byte - { - Tcp = 0x00, - Udp = 0x01, - Websocket = 0x02 - } - - public ChannelType Channel { get; set; } - public ushort Port { get; set; } - + public override int Size => base.Size + // Type - sizeof(byte) + // Channel sizeof(ushort); // Port - /// - /// Constructor - /// - public ServerCapability() : base(NodeCapabilities.Server) { } - /// /// Constructor /// /// Channel /// Port - public ServerCapability(ChannelType type, ushort port) : base(NodeCapabilities.Server) + protected ServerCapability(NodeCapabilities type, ushort port = 0) : base(type) { - Channel = type; + if (type != NodeCapabilities.TcpServer && type != NodeCapabilities.UdpServer && type != NodeCapabilities.WsServer) + { + throw new ArgumentException(nameof(type)); + } + Port = port; } public override void Deserialize(BinaryReader reader) { base.Deserialize(reader); - - Channel = (ChannelType)reader.ReadByte(); Port = reader.ReadUInt16(); } public override void Serialize(BinaryWriter writer) { base.Serialize(writer); - - writer.Write((byte)Type); writer.Write(Port); } } -} +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/TcpServerCapability.cs b/neo/Network/P2P/Capabilities/TcpServerCapability.cs new file mode 100644 index 0000000000..bf27a3aede --- /dev/null +++ b/neo/Network/P2P/Capabilities/TcpServerCapability.cs @@ -0,0 +1,9 @@ +namespace Neo.Network.P2P.Capabilities +{ + public class TcpServerCapability : ServerCapability + { + public TcpServerCapability() : base(NodeCapabilities.TcpServer) { } + + public TcpServerCapability(ushort port) : base(NodeCapabilities.TcpServer, port) { } + } +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/UdpServerCapability.cs b/neo/Network/P2P/Capabilities/UdpServerCapability.cs new file mode 100644 index 0000000000..4014d7efb8 --- /dev/null +++ b/neo/Network/P2P/Capabilities/UdpServerCapability.cs @@ -0,0 +1,9 @@ +namespace Neo.Network.P2P.Capabilities +{ + public class UdpServerCapability : ServerCapability + { + public UdpServerCapability() : base(NodeCapabilities.UdpServer) { } + + public UdpServerCapability(ushort port) : base(NodeCapabilities.UdpServer, port) { } + } +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/WsServerCapability.cs b/neo/Network/P2P/Capabilities/WsServerCapability.cs new file mode 100644 index 0000000000..52bbf9d9c1 --- /dev/null +++ b/neo/Network/P2P/Capabilities/WsServerCapability.cs @@ -0,0 +1,9 @@ +namespace Neo.Network.P2P.Capabilities +{ + public class WsServerCapability : ServerCapability + { + public WsServerCapability() : base(NodeCapabilities.WsServer) { } + + public WsServerCapability(ushort port) : base(NodeCapabilities.WsServer, port) { } + } +} \ No newline at end of file diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 6eafbd730b..f789bd5ab7 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -28,9 +28,8 @@ internal class Relay { public IInventory Inventory; } public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); public override int ListenerTcpPort => Version?.Capabilities - .Where(u => u.Type == NodeCapabilities.Server) - .Cast() - .Where(u => u.Channel == ServerCapability.ChannelType.Tcp) + .Where(u => u.Type == NodeCapabilities.TcpServer) + .Cast() .First()?.Port ?? 0; public VersionPayload Version { get; private set; } public uint LastBlockIndex { get; private set; } @@ -44,9 +43,9 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP var capabilities = new List(); - if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Tcp, (ushort)LocalNode.Singleton.ListenerTcpPort)); - if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Udp, (ushort)LocalNode.Singleton.ListenerUdpPort)); - if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new ServerCapability(ServerCapability.ChannelType.Websocket, (ushort)LocalNode.Singleton.ListenerWsPort)); + if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new TcpServerCapability((ushort)LocalNode.Singleton.ListenerTcpPort)); + if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new UdpServerCapability((ushort)LocalNode.Singleton.ListenerUdpPort)); + if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new WsServerCapability((ushort)LocalNode.Singleton.ListenerWsPort)); SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, Blockchain.Singleton.Height, capabilities))); From 56d8d64748564bba29c566cb015cde9b9f387767 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 12 May 2019 19:02:45 +0200 Subject: [PATCH 21/42] Summarize ServerCapability and remove reflection --- neo.UnitTests/UT_P2PMessage.cs | 6 +++--- .../P2P/Capabilities/NodeCapabilities.cs | 5 ----- .../P2P/Capabilities/ServerCapability.cs | 2 +- .../P2P/Capabilities/TcpServerCapability.cs | 9 -------- .../P2P/Capabilities/UdpServerCapability.cs | 9 -------- .../P2P/Capabilities/WsServerCapability.cs | 9 -------- neo/Network/P2P/Payloads/VersionPayload.cs | 21 +++++++------------ neo/Network/P2P/RemoteNode.cs | 8 +++---- 8 files changed, 16 insertions(+), 53 deletions(-) delete mode 100644 neo/Network/P2P/Capabilities/TcpServerCapability.cs delete mode 100644 neo/Network/P2P/Capabilities/UdpServerCapability.cs delete mode 100644 neo/Network/P2P/Capabilities/WsServerCapability.cs diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/UT_P2PMessage.cs index 7f82a9efa3..074b582707 100644 --- a/neo.UnitTests/UT_P2PMessage.cs +++ b/neo.UnitTests/UT_P2PMessage.cs @@ -90,7 +90,7 @@ public void Compression() Version = 6, Capabilities = new NodeCapabilityBase[] { - new TcpServerCapability(25) + new ServerCapability(NodeCapabilities.TcpServer, 25) } }; @@ -114,8 +114,8 @@ public void Compression() payloadCopy.Version.Should().Be(payload.Version); payloadCopy.Capabilities.Length.Should().Be(1); - ((TcpServerCapability)payloadCopy.Capabilities[0]).Type.Should().Be(NodeCapabilities.TcpServer); - ((TcpServerCapability)payloadCopy.Capabilities[0]).Port.Should().Be(25); + ((ServerCapability)payloadCopy.Capabilities[0]).Type.Should().Be(NodeCapabilities.TcpServer); + ((ServerCapability)payloadCopy.Capabilities[0]).Port.Should().Be(25); } } diff --git a/neo/Network/P2P/Capabilities/NodeCapabilities.cs b/neo/Network/P2P/Capabilities/NodeCapabilities.cs index dcbc44977f..292aec7fd2 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilities.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilities.cs @@ -4,13 +4,8 @@ namespace Neo.Network.P2P.Capabilities { public enum NodeCapabilities : byte { - [ReflectionCache(typeof(TcpServerCapability))] TcpServer = 0x01, - - [ReflectionCache(typeof(UdpServerCapability))] UdpServer = 0x02, - - [ReflectionCache(typeof(WsServerCapability))] WsServer = 0x03, } } \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index cb21f7aea8..b3821fd9cf 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -16,7 +16,7 @@ public class ServerCapability : NodeCapabilityBase /// /// Channel /// Port - protected ServerCapability(NodeCapabilities type, ushort port = 0) : base(type) + public ServerCapability(NodeCapabilities type, ushort port = 0) : base(type) { if (type != NodeCapabilities.TcpServer && type != NodeCapabilities.UdpServer && type != NodeCapabilities.WsServer) { diff --git a/neo/Network/P2P/Capabilities/TcpServerCapability.cs b/neo/Network/P2P/Capabilities/TcpServerCapability.cs deleted file mode 100644 index bf27a3aede..0000000000 --- a/neo/Network/P2P/Capabilities/TcpServerCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Neo.Network.P2P.Capabilities -{ - public class TcpServerCapability : ServerCapability - { - public TcpServerCapability() : base(NodeCapabilities.TcpServer) { } - - public TcpServerCapability(ushort port) : base(NodeCapabilities.TcpServer, port) { } - } -} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/UdpServerCapability.cs b/neo/Network/P2P/Capabilities/UdpServerCapability.cs deleted file mode 100644 index 4014d7efb8..0000000000 --- a/neo/Network/P2P/Capabilities/UdpServerCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Neo.Network.P2P.Capabilities -{ - public class UdpServerCapability : ServerCapability - { - public UdpServerCapability() : base(NodeCapabilities.UdpServer) { } - - public UdpServerCapability(ushort port) : base(NodeCapabilities.UdpServer, port) { } - } -} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/WsServerCapability.cs b/neo/Network/P2P/Capabilities/WsServerCapability.cs deleted file mode 100644 index 52bbf9d9c1..0000000000 --- a/neo/Network/P2P/Capabilities/WsServerCapability.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Neo.Network.P2P.Capabilities -{ - public class WsServerCapability : ServerCapability - { - public WsServerCapability() : base(NodeCapabilities.WsServer) { } - - public WsServerCapability(ushort port) : base(NodeCapabilities.WsServer, port) { } - } -} \ No newline at end of file diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index fae5518cca..57678a0675 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -1,5 +1,4 @@ using Neo.IO; -using Neo.IO.Caching; using Neo.Network.P2P.Capabilities; using System; using System.Collections.Generic; @@ -10,11 +9,6 @@ namespace Neo.Network.P2P.Payloads { public class VersionPayload : ISerializable { - /// - /// Reflection cache for ConsensusMessageType - /// - private static readonly ReflectionCache ReflectionCache = ReflectionCache.CreateFromEnum(); - const int MaxCapabilities = 32; public uint Magic; @@ -67,17 +61,18 @@ void ISerializable.Deserialize(BinaryReader reader) for (int x = 0, max = Capabilities.Length; x < max; x++) { - var type = reader.PeekChar(); + var cap = (NodeCapabilities)reader.PeekChar(); - if (!ReflectionCache.TryGetValue((byte)type, out var objType)) + switch ((NodeCapabilities)reader.PeekChar()) { - throw new FormatException(); - } + case NodeCapabilities.TcpServer: + case NodeCapabilities.UdpServer: + case NodeCapabilities.WsServer: Capabilities[x] = new ServerCapability(cap); break; - var value = (NodeCapabilityBase)Activator.CreateInstance(objType); - value.Deserialize(reader); + default: throw new FormatException(); + } - Capabilities[x] = value; + Capabilities[x].Deserialize(reader); } } diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index f789bd5ab7..70c3e41cae 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -29,7 +29,7 @@ internal class Relay { public IInventory Inventory; } public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); public override int ListenerTcpPort => Version?.Capabilities .Where(u => u.Type == NodeCapabilities.TcpServer) - .Cast() + .Cast() .First()?.Port ?? 0; public VersionPayload Version { get; private set; } public uint LastBlockIndex { get; private set; } @@ -43,9 +43,9 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP var capabilities = new List(); - if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new TcpServerCapability((ushort)LocalNode.Singleton.ListenerTcpPort)); - if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new UdpServerCapability((ushort)LocalNode.Singleton.ListenerUdpPort)); - if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new WsServerCapability((ushort)LocalNode.Singleton.ListenerWsPort)); + if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.TcpServer, (ushort)LocalNode.Singleton.ListenerTcpPort)); + if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.UdpServer, (ushort)LocalNode.Singleton.ListenerUdpPort)); + if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.WsServer, (ushort)LocalNode.Singleton.ListenerWsPort)); SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, Blockchain.Singleton.Height, capabilities))); From f238e4699658310e8725d1653165eee18367ef1e Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 12 May 2019 19:06:59 +0200 Subject: [PATCH 22/42] Move Capabilities --- neo/Network/P2P/Payloads/VersionPayload.cs | 24 ++++++++++++---------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index 57678a0675..ab4673a05c 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -15,20 +15,20 @@ public class VersionPayload : ISerializable public uint Version; public VersionServices Services; public uint Timestamp; + public NodeCapabilityBase[] Capabilities; public uint Nonce; public string UserAgent; public uint StartHeight; - public NodeCapabilityBase[] Capabilities; public int Size => sizeof(uint) + // Magic sizeof(uint) + // Version sizeof(VersionServices) + // Services sizeof(uint) + // Timestamp + Capabilities.GetVarSize() + // Capabilities sizeof(uint) + // Nonce UserAgent.GetVarSize() + // UserAgent - sizeof(uint) + // StartHeight - Capabilities.GetVarSize(); // Capabilities + sizeof(uint); // StartHeight public static VersionPayload Create(uint nonce, string userAgent, uint startHeight, IEnumerable capabilities) { @@ -51,10 +51,7 @@ void ISerializable.Deserialize(BinaryReader reader) Version = reader.ReadUInt32(); Services = (VersionServices)reader.ReadUInt64(); Timestamp = reader.ReadUInt32(); - Nonce = reader.ReadUInt32(); - UserAgent = reader.ReadVarString(1024); - StartHeight = reader.ReadUInt32(); - + // Capabilities Capabilities = new NodeCapabilityBase[reader.ReadVarInt(MaxCapabilities)]; @@ -74,6 +71,10 @@ void ISerializable.Deserialize(BinaryReader reader) Capabilities[x].Deserialize(reader); } + + Nonce = reader.ReadUInt32(); + UserAgent = reader.ReadVarString(1024); + StartHeight = reader.ReadUInt32(); } void ISerializable.Serialize(BinaryWriter writer) @@ -82,10 +83,7 @@ void ISerializable.Serialize(BinaryWriter writer) writer.Write(Version); writer.Write((ulong)Services); writer.Write(Timestamp); - writer.Write(Nonce); - writer.WriteVarString(UserAgent); - writer.Write(StartHeight); - + // Capabilities writer.WriteVarInt(Capabilities.Length); @@ -93,6 +91,10 @@ void ISerializable.Serialize(BinaryWriter writer) { value.Serialize(writer); } + + writer.Write(Nonce); + writer.WriteVarString(UserAgent); + writer.Write(StartHeight); } } } From e9c90978ba42857f95bceaaff79b82f460d67aaa Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 12 May 2019 19:10:18 +0200 Subject: [PATCH 23/42] OnStart with ChannelsStartConfig --- neo/Network/P2P/Peer.cs | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index 68024e5be7..fdce151ae4 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -107,13 +107,7 @@ protected override void OnReceive(object message) switch (message) { case ChannelsStartConfig start: - OnStart - ( - start.Tcp != null && start.Tcp.IsValid ? start.Tcp.EndPoint : null, - start.Udp != null && start.Udp.IsValid ? start.Udp.EndPoint : null, - start.WebSocket != null && start.WebSocket.IsValid ? start.WebSocket.EndPoint : null, - start.MinDesiredConnections, start.MaxConnections, start.MaxConnectionsPerAddress - ); + OnStart(start); break; case Timer _: OnTimer(); @@ -148,15 +142,15 @@ protected override void OnReceive(object message) } } - private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesiredConnections, int maxConnections, int maxConnectionsPerAddress) + private void OnStart(ChannelsStartConfig config) { - ListenerTcpPort = tcp == null ? 0 : tcp.Port; - ListenerUdpPort = udp == null ? 0 : udp.Port; - ListenerWsPort = ws == null ? 0 : ws.Port; + ListenerTcpPort = config.Tcp == null ? 0 : config.Tcp.Port; + ListenerUdpPort = config.Udp == null ? 0 : config.Udp.Port; + ListenerWsPort = config.WebSocket == null ? 0 : config.WebSocket.Port; - MinDesiredConnections = minDesiredConnections; - MaxConnections = maxConnections; - MaxConnectionsPerAddress = maxConnectionsPerAddress; + MinDesiredConnections = config.MinDesiredConnections; + MaxConnections = config.MaxConnections; + MaxConnectionsPerAddress = config.MaxConnectionsPerAddress; timer = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(0, 5000, Context.Self, new Timer(), ActorRefs.NoSender); if ((ListenerTcpPort > 0 || ListenerWsPort > 0 || ListenerUdpPort > 0) @@ -168,23 +162,23 @@ private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesir localAddresses.Add(UPnP.GetExternalIP()); if (ListenerTcpPort > 0) UPnP.ForwardPort(ListenerTcpPort, ProtocolType.Tcp, "NEO Tcp"); - if (ListenerUdpPort > 0) UPnP.ForwardPort(udp.Port, ProtocolType.Udp, "NEO Udp"); - if (ListenerWsPort > 0) UPnP.ForwardPort(ws.Port, ProtocolType.Tcp, "NEO WebSocket"); + if (ListenerUdpPort > 0) UPnP.ForwardPort(ListenerUdpPort, ProtocolType.Udp, "NEO Udp"); + if (ListenerWsPort > 0) UPnP.ForwardPort(ListenerWsPort, ProtocolType.Tcp, "NEO WebSocket"); } catch { } } if (ListenerTcpPort > 0) { - tcp_manager.Tell(new Tcp.Bind(Self, tcp, options: new[] { new Inet.SO.ReuseAddress(true) })); + tcp_manager.Tell(new Tcp.Bind(Self, config.Tcp.EndPoint, options: new[] { new Inet.SO.ReuseAddress(true) })); } if (ListenerWsPort > 0) { var host = "*"; - if (!ws.Address.GetAddressBytes().SequenceEqual(IPAddress.Any.GetAddressBytes())) + if (!config.WebSocket.EndPoint.Address.GetAddressBytes().SequenceEqual(IPAddress.Any.GetAddressBytes())) { // Is not for all interfaces - host = ws.Address.ToString(); + host = config.WebSocket.EndPoint.Address.ToString(); } ws_host = new WebHostBuilder().UseKestrel().UseUrls($"http://{host}:{ListenerWsPort}").Configure(app => app.UseWebSockets().Run(ProcessWebSocketAsync)).Build(); @@ -192,7 +186,7 @@ private void OnStart(IPEndPoint tcp, IPEndPoint udp, IPEndPoint ws, int minDesir } if (ListenerUdpPort > 0) { - udp_manager.Tell(new Udp.Bind(Self, udp)); + udp_manager.Tell(new Udp.Bind(Self, config.Udp.EndPoint)); } } From c9447b6e2caba0495b99e76c1975e0968b5f4f26 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 12 May 2019 19:14:23 +0200 Subject: [PATCH 24/42] Remove EndPointConfig --- neo/ChannelsStartConfig.cs | 7 ++++--- neo/EndPointConfig.cs | 27 --------------------------- neo/Network/P2P/Peer.cs | 8 ++++---- 3 files changed, 8 insertions(+), 34 deletions(-) delete mode 100644 neo/EndPointConfig.cs diff --git a/neo/ChannelsStartConfig.cs b/neo/ChannelsStartConfig.cs index c66c74c59c..fabdb4c86d 100644 --- a/neo/ChannelsStartConfig.cs +++ b/neo/ChannelsStartConfig.cs @@ -1,4 +1,5 @@ using Neo.Network.P2P; +using System.Net; namespace Neo { @@ -7,17 +8,17 @@ public class ChannelsStartConfig /// /// Tcp configuration /// - public EndPointConfig Tcp { get; set; } = new EndPointConfig() { }; + public IPEndPoint Tcp { get; set; } /// /// Udp configuration /// - public EndPointConfig Udp { get; set; } = new EndPointConfig() { }; + public IPEndPoint Udp { get; set; } /// /// Web socket configuration /// - public EndPointConfig WebSocket { get; set; } = new EndPointConfig() { }; + public IPEndPoint WebSocket { get; set; } /// /// Minimum desired connections diff --git a/neo/EndPointConfig.cs b/neo/EndPointConfig.cs deleted file mode 100644 index 4c6690ac02..0000000000 --- a/neo/EndPointConfig.cs +++ /dev/null @@ -1,27 +0,0 @@ -using System.Net; - -namespace Neo -{ - public class EndPointConfig - { - /// - /// Address - /// - public string Address { get; set; } = "0.0.0.0"; - - /// - /// Port - /// - public ushort Port { get; set; } = 0; - - /// - /// Ip EndPoint - /// - public IPEndPoint EndPoint => new IPEndPoint(IPAddress.Parse(Address), Port); - - /// - /// Return true if the address and port are valid - /// - public bool IsValid => IPAddress.TryParse(Address, out var addr) && Port > 0; - } -} \ No newline at end of file diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index fdce151ae4..2d2b22ef37 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -169,16 +169,16 @@ private void OnStart(ChannelsStartConfig config) } if (ListenerTcpPort > 0) { - tcp_manager.Tell(new Tcp.Bind(Self, config.Tcp.EndPoint, options: new[] { new Inet.SO.ReuseAddress(true) })); + tcp_manager.Tell(new Tcp.Bind(Self, config.Tcp, options: new[] { new Inet.SO.ReuseAddress(true) })); } if (ListenerWsPort > 0) { var host = "*"; - if (!config.WebSocket.EndPoint.Address.GetAddressBytes().SequenceEqual(IPAddress.Any.GetAddressBytes())) + if (!config.WebSocket.Address.GetAddressBytes().SequenceEqual(IPAddress.Any.GetAddressBytes())) { // Is not for all interfaces - host = config.WebSocket.EndPoint.Address.ToString(); + host = config.WebSocket.Address.ToString(); } ws_host = new WebHostBuilder().UseKestrel().UseUrls($"http://{host}:{ListenerWsPort}").Configure(app => app.UseWebSockets().Run(ProcessWebSocketAsync)).Build(); @@ -186,7 +186,7 @@ private void OnStart(ChannelsStartConfig config) } if (ListenerUdpPort > 0) { - udp_manager.Tell(new Udp.Bind(Self, config.Udp.EndPoint)); + udp_manager.Tell(new Udp.Bind(Self, config.Udp)); } } From 1a86ae7363818bf3b4a790c4ab6152dd9e396a79 Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 12 May 2019 19:47:35 +0200 Subject: [PATCH 25/42] Move udp logic to ProtocolHandler --- neo/Network/P2P/LocalNode.cs | 49 +++----- neo/Network/P2P/Peer.cs | 5 - neo/Network/P2P/ProtocolHandler.cs | 196 +++++++++++++++++------------ neo/Network/P2P/UdpMessage.cs | 34 +++++ 4 files changed, 166 insertions(+), 118 deletions(-) create mode 100644 neo/Network/P2P/UdpMessage.cs diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index 11fb2be389..a2cdae3bcf 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -24,6 +24,7 @@ internal class SendDirectly { public IInventory Inventory; } private static readonly object lockObj = new object(); private readonly NeoSystem system; + private readonly IActorRef protocol; internal readonly ConcurrentDictionary RemoteNodes = new ConcurrentDictionary(); public int ConnectedCount => RemoteNodes.Count; @@ -54,7 +55,9 @@ public LocalNode(NeoSystem system) { if (_singleton != null) throw new InvalidOperationException(); + this.system = system; + protocol = Context.ActorOf(ProtocolHandler.Props(system)); _singleton = this; } } @@ -140,6 +143,12 @@ protected override void OnReceive(object message) base.OnReceive(message); switch (message) { + case UdpMessage udp: + SendUdp(udp.Sender, udp.Data); + break; + case Udp.Received udpmsg: + protocol.Tell(udpmsg); + break; case Message msg: BroadcastMessage(msg); break; @@ -157,47 +166,17 @@ protected override void OnReceive(object message) } } - protected override void OnUdpMessage(IPEndPoint remote, ByteString data) - { - if (Message.TryDeserialize(data, out var msg) != data.Count) return; - - switch (msg.Command) - { - case MessageCommand.Transaction: - { - if (msg.Payload.Size <= Transaction.MaxTransactionSize) - system.LocalNode.Tell(new Relay { Inventory = (Transaction)msg.Payload }); - - break; - } - case MessageCommand.Ping: - { - var payload = (PingPayload)msg.Payload; - msg = Message.Create(MessageCommand.Pong, PingPayload.Create(Blockchain.Singleton.Height, payload.Nonce)); - SendUdp(remote, ByteString.FromBytes(msg.ToArray())); - break; - } - case MessageCommand.GetAddr: - { - NetworkAddressWithTime[] networkAddresses = GetPeers(); - if (networkAddresses.Length == 0) return; - msg = Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses)); - SendUdp(remote, ByteString.FromBytes(msg.ToArray())); - break; - } - } - } - public NetworkAddressWithTime[] GetPeers() { Random rand = new Random(); - IEnumerable peers = RemoteNodes.Values + + return RemoteNodes.Values .Where(p => p.ListenerTcpPort > 0) .GroupBy(p => p.Remote.Address, (k, g) => g.First()) .OrderBy(p => rand.Next()) - .Take(AddrPayload.MaxCountToSend); - - return peers.Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Services, p.Version.Timestamp)).ToArray(); + .Take(AddrPayload.MaxCountToSend) + .Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Services, p.Version.Timestamp)) + .ToArray(); } private void OnRelay(IInventory inventory) diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index 2d2b22ef37..bebfd1cafe 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -130,9 +130,6 @@ protected override void OnReceive(object message) case Udp.Bound _: udp_listener = Sender; break; - case Udp.Received udpmsg: - OnUdpMessage((IPEndPoint)udpmsg.Sender, udpmsg.Data); - break; case Tcp.CommandFailed commandFailed: OnTcpCommandFailed(commandFailed.Cmd); break; @@ -190,8 +187,6 @@ private void OnStart(ChannelsStartConfig config) } } - protected abstract void OnUdpMessage(IPEndPoint remote, ByteString data); - protected void SendUdp(IPEndPoint remote, ByteString data) => udp_listener.Tell(Udp.Send.Create(data, remote)); private void OnTcpConnected(IPEndPoint remote, IPEndPoint local) diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index 9b2d2c4de2..48cc830409 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -1,5 +1,6 @@ using Akka.Actor; using Akka.Configuration; +using Akka.IO; using Neo.Cryptography; using Neo.IO; using Neo.IO.Actors; @@ -8,7 +9,6 @@ using Neo.Network.P2P.Payloads; using Neo.Persistence; using Neo.Plugins; -using System; using System.Collections; using System.Collections.Generic; using System.Linq; @@ -36,83 +36,123 @@ public ProtocolHandler(NeoSystem system) protected override void OnReceive(object message) { - if (!(message is Message msg)) return; - foreach (IP2PPlugin plugin in Plugin.P2PPlugins) - if (!plugin.OnP2PMessage(msg)) - return; - if (version == null) + switch (message) { - if (msg.Command != MessageCommand.Version) - throw new ProtocolViolationException(); - OnVersionMessageReceived((VersionPayload)msg.Payload); - return; - } - if (!verack) - { - if (msg.Command != MessageCommand.Verack) - throw new ProtocolViolationException(); - OnVerackMessageReceived(); - return; - } - switch (msg.Command) - { - case MessageCommand.Addr: - OnAddrMessageReceived((AddrPayload)msg.Payload); - break; - case MessageCommand.Block: - OnInventoryReceived((Block)msg.Payload); - break; - case MessageCommand.Consensus: - OnInventoryReceived((ConsensusPayload)msg.Payload); - break; - case MessageCommand.FilterAdd: - OnFilterAddMessageReceived((FilterAddPayload)msg.Payload); - break; - case MessageCommand.FilterClear: - OnFilterClearMessageReceived(); - break; - case MessageCommand.FilterLoad: - OnFilterLoadMessageReceived((FilterLoadPayload)msg.Payload); - break; - case MessageCommand.GetAddr: - OnGetAddrMessageReceived(); - break; - case MessageCommand.GetBlocks: - OnGetBlocksMessageReceived((GetBlocksPayload)msg.Payload); - break; - case MessageCommand.GetData: - OnGetDataMessageReceived((InvPayload)msg.Payload); - break; - case MessageCommand.GetHeaders: - OnGetHeadersMessageReceived((GetBlocksPayload)msg.Payload); - break; - case MessageCommand.Headers: - OnHeadersMessageReceived((HeadersPayload)msg.Payload); - break; - case MessageCommand.Inv: - OnInvMessageReceived((InvPayload)msg.Payload); - break; - case MessageCommand.Mempool: - OnMemPoolMessageReceived(); - break; - case MessageCommand.Ping: - OnPingMessageReceived((PingPayload)msg.Payload); - break; - case MessageCommand.Pong: - OnPongMessageReceived((PingPayload)msg.Payload); - break; - case MessageCommand.Transaction: - if (msg.Payload.Size <= Transaction.MaxTransactionSize) - OnInventoryReceived((Transaction)msg.Payload); - break; - case MessageCommand.Verack: - case MessageCommand.Version: - throw new ProtocolViolationException(); - case MessageCommand.Alert: - case MessageCommand.MerkleBlock: - case MessageCommand.NotFound: - case MessageCommand.Reject: - default: break; + case Message msg: + { + foreach (IP2PPlugin plugin in Plugin.P2PPlugins) + if (!plugin.OnP2PMessage(msg)) + return; + + if (version == null) + { + if (msg.Command != MessageCommand.Version) + throw new ProtocolViolationException(); + OnVersionMessageReceived((VersionPayload)msg.Payload); + return; + } + if (!verack) + { + if (msg.Command != MessageCommand.Verack) + throw new ProtocolViolationException(); + OnVerackMessageReceived(); + return; + } + switch (msg.Command) + { + case MessageCommand.Addr: + OnAddrMessageReceived((AddrPayload)msg.Payload); + break; + case MessageCommand.Block: + OnInventoryReceived((Block)msg.Payload); + break; + case MessageCommand.Consensus: + OnInventoryReceived((ConsensusPayload)msg.Payload); + break; + case MessageCommand.FilterAdd: + OnFilterAddMessageReceived((FilterAddPayload)msg.Payload); + break; + case MessageCommand.FilterClear: + OnFilterClearMessageReceived(); + break; + case MessageCommand.FilterLoad: + OnFilterLoadMessageReceived((FilterLoadPayload)msg.Payload); + break; + case MessageCommand.GetAddr: + OnGetAddrMessageReceived(); + break; + case MessageCommand.GetBlocks: + OnGetBlocksMessageReceived((GetBlocksPayload)msg.Payload); + break; + case MessageCommand.GetData: + OnGetDataMessageReceived((InvPayload)msg.Payload); + break; + case MessageCommand.GetHeaders: + OnGetHeadersMessageReceived((GetBlocksPayload)msg.Payload); + break; + case MessageCommand.Headers: + OnHeadersMessageReceived((HeadersPayload)msg.Payload); + break; + case MessageCommand.Inv: + OnInvMessageReceived((InvPayload)msg.Payload); + break; + case MessageCommand.Mempool: + OnMemPoolMessageReceived(); + break; + case MessageCommand.Ping: + OnPingMessageReceived((PingPayload)msg.Payload); + break; + case MessageCommand.Pong: + OnPongMessageReceived((PingPayload)msg.Payload); + break; + case MessageCommand.Transaction: + if (msg.Payload.Size <= Transaction.MaxTransactionSize) + OnInventoryReceived((Transaction)msg.Payload); + break; + case MessageCommand.Verack: + case MessageCommand.Version: + throw new ProtocolViolationException(); + case MessageCommand.Alert: + case MessageCommand.MerkleBlock: + case MessageCommand.NotFound: + case MessageCommand.Reject: + default: break; + } + + break; + } + case Udp.Received udp: + { + if (Message.TryDeserialize(udp.Data, out var msg) != udp.Data.Count) return; + + switch (msg.Command) + { + case MessageCommand.Transaction: + { + if (msg.Payload.Size <= Transaction.MaxTransactionSize) + system.LocalNode.Tell(new LocalNode.Relay { Inventory = (Transaction)msg.Payload }); + break; + } + case MessageCommand.Ping: + { + var payload = (PingPayload)msg.Payload; + msg = Message.Create(MessageCommand.Pong, PingPayload.Create(Blockchain.Singleton.Height, payload.Nonce)); + + system.LocalNode.Tell(new UdpMessage((IPEndPoint)udp.Sender, ByteString.FromBytes(msg.ToArray()))); + break; + } + case MessageCommand.GetAddr: + { + var networkAddresses = LocalNode.Singleton.GetPeers(); + if (networkAddresses.Length == 0) return; + msg = Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses)); + + system.LocalNode.Tell(new UdpMessage((IPEndPoint)udp.Sender, ByteString.FromBytes(msg.ToArray()))); + break; + } + } + break; + } } } @@ -296,7 +336,7 @@ public static Props Props(NeoSystem system) internal class ProtocolHandlerMailbox : PriorityMailbox { - public ProtocolHandlerMailbox(Akka.Actor.Settings settings, Config config) + public ProtocolHandlerMailbox(Settings settings, Config config) : base(settings, config) { } diff --git a/neo/Network/P2P/UdpMessage.cs b/neo/Network/P2P/UdpMessage.cs new file mode 100644 index 0000000000..0a885b5945 --- /dev/null +++ b/neo/Network/P2P/UdpMessage.cs @@ -0,0 +1,34 @@ +using Akka.IO; +using System.Net; + +namespace Neo.Network.P2P +{ + public class UdpMessage + { + /// + /// Sender + /// + public IPEndPoint Sender { get; set; } + + /// + /// Data + /// + public ByteString Data { get; set; } + + /// + /// Constructor + /// + public UdpMessage() { } + + /// + /// Constructor + /// + /// Sender + /// Data + public UdpMessage(IPEndPoint sender, ByteString data) + { + Sender = sender; + Data = data; + } + } +} \ No newline at end of file From 766f5892c6224114e5f94d39cb91b182fb21f28c Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 12 May 2019 19:49:20 +0200 Subject: [PATCH 26/42] Rename --- neo/Network/P2P/LocalNode.cs | 2 +- neo/Network/P2P/ProtocolHandler.cs | 4 ++-- neo/Network/P2P/{UdpMessage.cs => UdpResponse.cs} | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) rename neo/Network/P2P/{UdpMessage.cs => UdpResponse.cs} (82%) diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index a2cdae3bcf..fd5e067db0 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -143,7 +143,7 @@ protected override void OnReceive(object message) base.OnReceive(message); switch (message) { - case UdpMessage udp: + case UdpResponse udp: SendUdp(udp.Sender, udp.Data); break; case Udp.Received udpmsg: diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index 48cc830409..988c1b17c4 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -138,7 +138,7 @@ protected override void OnReceive(object message) var payload = (PingPayload)msg.Payload; msg = Message.Create(MessageCommand.Pong, PingPayload.Create(Blockchain.Singleton.Height, payload.Nonce)); - system.LocalNode.Tell(new UdpMessage((IPEndPoint)udp.Sender, ByteString.FromBytes(msg.ToArray()))); + system.LocalNode.Tell(new UdpResponse((IPEndPoint)udp.Sender, ByteString.FromBytes(msg.ToArray()))); break; } case MessageCommand.GetAddr: @@ -147,7 +147,7 @@ protected override void OnReceive(object message) if (networkAddresses.Length == 0) return; msg = Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses)); - system.LocalNode.Tell(new UdpMessage((IPEndPoint)udp.Sender, ByteString.FromBytes(msg.ToArray()))); + system.LocalNode.Tell(new UdpResponse((IPEndPoint)udp.Sender, ByteString.FromBytes(msg.ToArray()))); break; } } diff --git a/neo/Network/P2P/UdpMessage.cs b/neo/Network/P2P/UdpResponse.cs similarity index 82% rename from neo/Network/P2P/UdpMessage.cs rename to neo/Network/P2P/UdpResponse.cs index 0a885b5945..4d882de164 100644 --- a/neo/Network/P2P/UdpMessage.cs +++ b/neo/Network/P2P/UdpResponse.cs @@ -3,7 +3,7 @@ namespace Neo.Network.P2P { - public class UdpMessage + public class UdpResponse { /// /// Sender @@ -18,14 +18,14 @@ public class UdpMessage /// /// Constructor /// - public UdpMessage() { } + public UdpResponse() { } /// /// Constructor /// /// Sender /// Data - public UdpMessage(IPEndPoint sender, ByteString data) + public UdpResponse(IPEndPoint sender, ByteString data) { Sender = sender; Data = data; From c53f574ac87b295752ee50bf765d9c472747120b Mon Sep 17 00:00:00 2001 From: Shargon Date: Sun, 12 May 2019 23:10:47 +0200 Subject: [PATCH 27/42] Remove Services and StartHeight from VersionPayload --- neo.UnitTests/UT_P2PMessage.cs | 4 -- .../P2P/Capabilities/AcceptRelayCapability.cs | 16 +++++++ .../P2P/Capabilities/FullNodeCapability.cs | 34 +++++++++++++++ .../P2P/Capabilities/NodeCapabilities.cs | 7 ++-- .../P2P/Capabilities/NodeCapabilityBase.cs | 20 ++++++++- neo/Network/P2P/LocalNode.cs | 2 +- .../P2P/Payloads/NetworkAddressWithTime.cs | 25 +++++++---- neo/Network/P2P/Payloads/VersionPayload.cs | 40 +++--------------- neo/Network/P2P/Payloads/VersionServices.cs | 14 ------- neo/Network/P2P/RemoteNode.cs | 42 ++++++++++++------- neo/Network/P2P/TaskManager.cs | 4 +- neo/Network/P2P/TaskSession.cs | 13 ++++-- 12 files changed, 136 insertions(+), 85 deletions(-) create mode 100644 neo/Network/P2P/Capabilities/AcceptRelayCapability.cs create mode 100644 neo/Network/P2P/Capabilities/FullNodeCapability.cs delete mode 100644 neo/Network/P2P/Payloads/VersionServices.cs diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/UT_P2PMessage.cs index 074b582707..de8bd29134 100644 --- a/neo.UnitTests/UT_P2PMessage.cs +++ b/neo.UnitTests/UT_P2PMessage.cs @@ -84,8 +84,6 @@ public void Compression() UserAgent = "".PadLeft(1024, '0'), Nonce = 1, Magic = 2, - Services = VersionServices.FullNode, - StartHeight = 4, Timestamp = 5, Version = 6, Capabilities = new NodeCapabilityBase[] @@ -108,8 +106,6 @@ public void Compression() payloadCopy.UserAgent.Should().Be(payload.UserAgent); payloadCopy.Nonce.Should().Be(payload.Nonce); payloadCopy.Magic.Should().Be(payload.Magic); - payloadCopy.Services.Should().Be(payload.Services); - payloadCopy.StartHeight.Should().Be(payload.StartHeight); payloadCopy.Timestamp.Should().Be(payload.Timestamp); payloadCopy.Version.Should().Be(payload.Version); diff --git a/neo/Network/P2P/Capabilities/AcceptRelayCapability.cs b/neo/Network/P2P/Capabilities/AcceptRelayCapability.cs new file mode 100644 index 0000000000..c6f8f30c25 --- /dev/null +++ b/neo/Network/P2P/Capabilities/AcceptRelayCapability.cs @@ -0,0 +1,16 @@ +using System.IO; + +namespace Neo.Network.P2P.Capabilities +{ + public class AcceptRelayCapability : NodeCapabilityBase + { + /// + /// Constructor + /// + public AcceptRelayCapability() : base(NodeCapabilities.AcceptRelay) { } + + public override void Deserialize(BinaryReader reader) => base.Deserialize(reader); + + public override void Serialize(BinaryWriter writer) => base.Serialize(writer); + } +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/FullNodeCapability.cs b/neo/Network/P2P/Capabilities/FullNodeCapability.cs new file mode 100644 index 0000000000..1d08d0f128 --- /dev/null +++ b/neo/Network/P2P/Capabilities/FullNodeCapability.cs @@ -0,0 +1,34 @@ +using System.IO; + +namespace Neo.Network.P2P.Capabilities +{ + public class FullNodeCapability : NodeCapabilityBase + { + public uint StartHeight { get; set; } + + public override int Size => + base.Size + // Type + sizeof(uint); // Start Height + + /// + /// Constructor + /// + /// Start Height + public FullNodeCapability(uint startHeight = 0) : base(NodeCapabilities.FullNode) + { + StartHeight = startHeight; + } + + public override void Deserialize(BinaryReader reader) + { + base.Deserialize(reader); + StartHeight = reader.ReadUInt32(); + } + + public override void Serialize(BinaryWriter writer) + { + base.Serialize(writer); + writer.Write(StartHeight); + } + } +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/NodeCapabilities.cs b/neo/Network/P2P/Capabilities/NodeCapabilities.cs index 292aec7fd2..3681fa40de 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilities.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilities.cs @@ -1,11 +1,12 @@ -using Neo.IO.Caching; - -namespace Neo.Network.P2P.Capabilities +namespace Neo.Network.P2P.Capabilities { public enum NodeCapabilities : byte { TcpServer = 0x01, UdpServer = 0x02, WsServer = 0x03, + + FullNode = 0x10, + AcceptRelay = 0x11 } } \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs index bedd6fcc72..f3aede69f5 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs @@ -6,7 +6,7 @@ namespace Neo.Network.P2P.Capabilities { public abstract class NodeCapabilityBase : ISerializable { - public virtual int Size => 1; + public virtual int Size => 1; // Type /// /// Type @@ -34,5 +34,23 @@ public virtual void Serialize(BinaryWriter writer) { writer.Write((byte)Type); } + + /// + /// Create a new capability + /// + /// Type + public static NodeCapabilityBase Create(NodeCapabilities type) + { + switch (type) + { + case NodeCapabilities.TcpServer: + case NodeCapabilities.UdpServer: + case NodeCapabilities.WsServer: return new ServerCapability(type); + case NodeCapabilities.FullNode: return new FullNodeCapability(); + case NodeCapabilities.AcceptRelay: return new AcceptRelayCapability(); + + default: throw new FormatException(); + } + } } } \ No newline at end of file diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index fd5e067db0..e3ada24b6f 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -175,7 +175,7 @@ public NetworkAddressWithTime[] GetPeers() .GroupBy(p => p.Remote.Address, (k, g) => g.First()) .OrderBy(p => rand.Next()) .Take(AddrPayload.MaxCountToSend) - .Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Services, p.Version.Timestamp)) + .Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Timestamp, p.Version.Capabilities)) .ToArray(); } diff --git a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index 975541be97..1ecc3e7a25 100644 --- a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -1,5 +1,7 @@ using Neo.IO; +using Neo.Network.P2P.Capabilities; using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; @@ -9,25 +11,24 @@ namespace Neo.Network.P2P.Payloads public class NetworkAddressWithTime : ISerializable { public uint Timestamp; - public VersionServices Services; public IPEndPoint EndPoint; + public NodeCapabilityBase[] Capabilities; - public int Size => sizeof(uint) + sizeof(ulong) + 16 + sizeof(ushort); + public int Size => sizeof(uint) + 16 + sizeof(ushort) + Capabilities.GetVarSize(); - public static NetworkAddressWithTime Create(IPEndPoint endpoint, VersionServices services, uint timestamp) + public static NetworkAddressWithTime Create(IPEndPoint endpoint, uint timestamp, IEnumerable capabilities) { return new NetworkAddressWithTime { Timestamp = timestamp, - Services = services, - EndPoint = endpoint + EndPoint = endpoint, + Capabilities = capabilities.ToArray() }; } void ISerializable.Deserialize(BinaryReader reader) { Timestamp = reader.ReadUInt32(); - Services = (VersionServices)reader.ReadUInt64(); byte[] data = reader.ReadBytes(16); if (data.Length != 16) throw new FormatException(); IPAddress address = new IPAddress(data).Unmap(); @@ -35,14 +36,24 @@ void ISerializable.Deserialize(BinaryReader reader) if (data.Length != 2) throw new FormatException(); ushort port = data.Reverse().ToArray().ToUInt16(0); EndPoint = new IPEndPoint(address, port); + + // Capabilities + + Capabilities = new NodeCapabilityBase[reader.ReadVarInt(VersionPayload.MaxCapabilities)]; + + for (int x = 0, max = Capabilities.Length; x < max; x++) + { + Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.PeekChar()); + Capabilities[x].Deserialize(reader); + } } void ISerializable.Serialize(BinaryWriter writer) { writer.Write(Timestamp); - writer.Write((ulong)Services); writer.Write(EndPoint.Address.MapToIPv6().GetAddressBytes()); writer.Write(BitConverter.GetBytes((ushort)EndPoint.Port).Reverse().ToArray()); + writer.Write(Capabilities); } } } diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index ab4673a05c..03a38ef53b 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -9,38 +9,32 @@ namespace Neo.Network.P2P.Payloads { public class VersionPayload : ISerializable { - const int MaxCapabilities = 32; + public const int MaxCapabilities = 32; public uint Magic; public uint Version; - public VersionServices Services; public uint Timestamp; public NodeCapabilityBase[] Capabilities; public uint Nonce; public string UserAgent; - public uint StartHeight; public int Size => sizeof(uint) + // Magic sizeof(uint) + // Version - sizeof(VersionServices) + // Services sizeof(uint) + // Timestamp Capabilities.GetVarSize() + // Capabilities sizeof(uint) + // Nonce - UserAgent.GetVarSize() + // UserAgent - sizeof(uint); // StartHeight + UserAgent.GetVarSize(); // UserAgent - public static VersionPayload Create(uint nonce, string userAgent, uint startHeight, IEnumerable capabilities) + public static VersionPayload Create(uint nonce, string userAgent, IEnumerable capabilities) { return new VersionPayload { Magic = ProtocolSettings.Default.Magic, Version = LocalNode.ProtocolVersion, - Services = VersionServices.FullNode, Timestamp = DateTime.Now.ToTimestamp(), Nonce = nonce, UserAgent = userAgent, - StartHeight = startHeight, Capabilities = capabilities.ToArray(), }; } @@ -49,52 +43,30 @@ void ISerializable.Deserialize(BinaryReader reader) { Magic = reader.ReadUInt32(); Version = reader.ReadUInt32(); - Services = (VersionServices)reader.ReadUInt64(); Timestamp = reader.ReadUInt32(); - + // Capabilities Capabilities = new NodeCapabilityBase[reader.ReadVarInt(MaxCapabilities)]; for (int x = 0, max = Capabilities.Length; x < max; x++) { - var cap = (NodeCapabilities)reader.PeekChar(); - - switch ((NodeCapabilities)reader.PeekChar()) - { - case NodeCapabilities.TcpServer: - case NodeCapabilities.UdpServer: - case NodeCapabilities.WsServer: Capabilities[x] = new ServerCapability(cap); break; - - default: throw new FormatException(); - } - + Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.PeekChar()); Capabilities[x].Deserialize(reader); } Nonce = reader.ReadUInt32(); UserAgent = reader.ReadVarString(1024); - StartHeight = reader.ReadUInt32(); } void ISerializable.Serialize(BinaryWriter writer) { writer.Write(Magic); writer.Write(Version); - writer.Write((ulong)Services); writer.Write(Timestamp); - - // Capabilities - - writer.WriteVarInt(Capabilities.Length); - foreach (var value in Capabilities) - { - value.Serialize(writer); - } - + writer.Write(Capabilities); writer.Write(Nonce); writer.WriteVarString(UserAgent); - writer.Write(StartHeight); } } } diff --git a/neo/Network/P2P/Payloads/VersionServices.cs b/neo/Network/P2P/Payloads/VersionServices.cs deleted file mode 100644 index 4eb76d5d2b..0000000000 --- a/neo/Network/P2P/Payloads/VersionServices.cs +++ /dev/null @@ -1,14 +0,0 @@ -using System; - -namespace Neo.Network.P2P.Payloads -{ - [Flags] - public enum VersionServices : ulong - { - None = 0, - NodeNetwork = 1 << 0, - AcceptRelay = 1 << 1, - - FullNode = NodeNetwork | AcceptRelay - } -} diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 70c3e41cae..093b3e4bcb 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -25,14 +25,13 @@ internal class Relay { public IInventory Inventory; } private BloomFilter bloom_filter; private bool ack = true; private bool verack = false; + private int listenerTcpPort = 0; public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); - public override int ListenerTcpPort => Version?.Capabilities - .Where(u => u.Type == NodeCapabilities.TcpServer) - .Cast() - .First()?.Port ?? 0; + public override int ListenerTcpPort => listenerTcpPort; public VersionPayload Version { get; private set; } - public uint LastBlockIndex { get; private set; } + public bool AcceptRelay { get; private set; } = false; + public uint LastBlockIndex { get; private set; } = 0; public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndPoint local) : base(connection, remote, local) @@ -41,14 +40,17 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP this.protocol = Context.ActorOf(ProtocolHandler.Props(system)); LocalNode.Singleton.RemoteNodes.TryAdd(Self, this); - var capabilities = new List(); + var capabilities = new List + { + new FullNodeCapability(Blockchain.Singleton.Height), + new AcceptRelayCapability() + }; if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.TcpServer, (ushort)LocalNode.Singleton.ListenerTcpPort)); if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.UdpServer, (ushort)LocalNode.Singleton.ListenerUdpPort)); if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.WsServer, (ushort)LocalNode.Singleton.ListenerWsPort)); - SendMessage(Message.Create(MessageCommand.Version, - VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, Blockchain.Singleton.Height, capabilities))); + SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, capabilities))); } private void CheckMessageQueue() @@ -155,7 +157,7 @@ private void OnPingPayload(PingPayload payload) private void OnRelay(IInventory inventory) { - if (Version?.Services.HasFlag(VersionServices.AcceptRelay) != true) return; + if (!AcceptRelay) return; if (inventory.InventoryType == InventoryType.TX) { if (bloom_filter != null && !bloom_filter.Test((Transaction)inventory)) @@ -166,7 +168,7 @@ private void OnRelay(IInventory inventory) private void OnSend(IInventory inventory) { - if (Version?.Services.HasFlag(VersionServices.AcceptRelay) != true) return; + if (!AcceptRelay) return; if (inventory.InventoryType == InventoryType.TX) { if (bloom_filter != null && !bloom_filter.Test((Transaction)inventory)) @@ -189,8 +191,19 @@ private void OnVerack() private void OnVersionPayload(VersionPayload version) { - this.Version = version; - this.LastBlockIndex = Version.StartHeight; + Version = version; + AcceptRelay = version.Capabilities + .Where(u => u is AcceptRelayCapability) + .Any(); + LastBlockIndex = version.Capabilities + .Where(u => u is FullNodeCapability) + .Cast() + .FirstOrDefault()?.StartHeight ?? 0; + listenerTcpPort = version.Capabilities + .Where(u => u.Type == NodeCapabilities.TcpServer) + .Cast() + .First()?.Port ?? 0; + if (version.Nonce == LocalNode.Nonce || version.Magic != ProtocolSettings.Default.Magic) { Disconnect(true); @@ -242,10 +255,7 @@ private Message TryParseMessage() internal class RemoteNodeMailbox : PriorityMailbox { - public RemoteNodeMailbox(Akka.Actor.Settings settings, Config config) - : base(settings, config) - { - } + public RemoteNodeMailbox(Settings settings, Config config) : base(settings, config) { } protected override bool IsHighPriority(object message) { diff --git a/neo/Network/P2P/TaskManager.cs b/neo/Network/P2P/TaskManager.cs index bd9481f2ea..f7322b448e 100644 --- a/neo/Network/P2P/TaskManager.cs +++ b/neo/Network/P2P/TaskManager.cs @@ -219,13 +219,13 @@ private void RequestTasks(TaskSession session) return; } } - if ((!HasHeaderTask || globalTasks[HeaderTaskHash] < MaxConncurrentTasks) && Blockchain.Singleton.HeaderHeight < session.Version.StartHeight) + if ((!HasHeaderTask || globalTasks[HeaderTaskHash] < MaxConncurrentTasks) && Blockchain.Singleton.HeaderHeight < session.StartHeight) { session.Tasks[HeaderTaskHash] = DateTime.UtcNow; IncrementGlobalTask(HeaderTaskHash); session.RemoteNode.Tell(Message.Create(MessageCommand.GetHeaders, GetBlocksPayload.Create(Blockchain.Singleton.CurrentHeaderHash))); } - else if (Blockchain.Singleton.Height < session.Version.StartHeight) + else if (Blockchain.Singleton.Height < session.StartHeight) { UInt256 hash = Blockchain.Singleton.CurrentBlockHash; for (uint i = Blockchain.Singleton.Height + 1; i <= Blockchain.Singleton.HeaderHeight; i++) diff --git a/neo/Network/P2P/TaskSession.cs b/neo/Network/P2P/TaskSession.cs index ebfdd8f9ec..3a1f03b97d 100644 --- a/neo/Network/P2P/TaskSession.cs +++ b/neo/Network/P2P/TaskSession.cs @@ -1,7 +1,9 @@ using Akka.Actor; +using Neo.Network.P2P.Capabilities; using Neo.Network.P2P.Payloads; using System; using System.Collections.Generic; +using System.Linq; namespace Neo.Network.P2P { @@ -14,11 +16,16 @@ internal class TaskSession public bool HasTask => Tasks.Count > 0; public bool HeaderTask => Tasks.ContainsKey(UInt256.Zero); + public uint StartHeight { get; } public TaskSession(IActorRef node, VersionPayload version) { - this.RemoteNode = node; - this.Version = version; + RemoteNode = node; + Version = version; + StartHeight = version.Capabilities + .Where(u => u is FullNodeCapability) + .Cast() + .FirstOrDefault()?.StartHeight ?? 0; } } -} +} \ No newline at end of file From fee3f86f9eab845e579118325095da63e911fcfb Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 13 May 2019 11:53:58 +0200 Subject: [PATCH 28/42] Remove AcceptRelay --- .../P2P/Capabilities/AcceptRelayCapability.cs | 16 ---------------- neo/Network/P2P/Capabilities/NodeCapabilities.cs | 3 +-- .../P2P/Capabilities/NodeCapabilityBase.cs | 1 - neo/Network/P2P/RemoteNode.cs | 13 ++++++------- 4 files changed, 7 insertions(+), 26 deletions(-) delete mode 100644 neo/Network/P2P/Capabilities/AcceptRelayCapability.cs diff --git a/neo/Network/P2P/Capabilities/AcceptRelayCapability.cs b/neo/Network/P2P/Capabilities/AcceptRelayCapability.cs deleted file mode 100644 index c6f8f30c25..0000000000 --- a/neo/Network/P2P/Capabilities/AcceptRelayCapability.cs +++ /dev/null @@ -1,16 +0,0 @@ -using System.IO; - -namespace Neo.Network.P2P.Capabilities -{ - public class AcceptRelayCapability : NodeCapabilityBase - { - /// - /// Constructor - /// - public AcceptRelayCapability() : base(NodeCapabilities.AcceptRelay) { } - - public override void Deserialize(BinaryReader reader) => base.Deserialize(reader); - - public override void Serialize(BinaryWriter writer) => base.Serialize(writer); - } -} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/NodeCapabilities.cs b/neo/Network/P2P/Capabilities/NodeCapabilities.cs index 3681fa40de..9e43c1fe84 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilities.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilities.cs @@ -6,7 +6,6 @@ public enum NodeCapabilities : byte UdpServer = 0x02, WsServer = 0x03, - FullNode = 0x10, - AcceptRelay = 0x11 + FullNode = 0x10 } } \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs index f3aede69f5..c932d018a1 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs @@ -47,7 +47,6 @@ public static NodeCapabilityBase Create(NodeCapabilities type) case NodeCapabilities.UdpServer: case NodeCapabilities.WsServer: return new ServerCapability(type); case NodeCapabilities.FullNode: return new FullNodeCapability(); - case NodeCapabilities.AcceptRelay: return new AcceptRelayCapability(); default: throw new FormatException(); } diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 093b3e4bcb..74989d4147 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -30,8 +30,8 @@ internal class Relay { public IInventory Inventory; } public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); public override int ListenerTcpPort => listenerTcpPort; public VersionPayload Version { get; private set; } - public bool AcceptRelay { get; private set; } = false; public uint LastBlockIndex { get; private set; } = 0; + public bool IsFullNode { get; private set; } = false; public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndPoint local) : base(connection, remote, local) @@ -42,8 +42,7 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP var capabilities = new List { - new FullNodeCapability(Blockchain.Singleton.Height), - new AcceptRelayCapability() + new FullNodeCapability(Blockchain.Singleton.Height) }; if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.TcpServer, (ushort)LocalNode.Singleton.ListenerTcpPort)); @@ -157,7 +156,7 @@ private void OnPingPayload(PingPayload payload) private void OnRelay(IInventory inventory) { - if (!AcceptRelay) return; + if (!IsFullNode) return; if (inventory.InventoryType == InventoryType.TX) { if (bloom_filter != null && !bloom_filter.Test((Transaction)inventory)) @@ -168,7 +167,7 @@ private void OnRelay(IInventory inventory) private void OnSend(IInventory inventory) { - if (!AcceptRelay) return; + if (!IsFullNode) return; if (inventory.InventoryType == InventoryType.TX) { if (bloom_filter != null && !bloom_filter.Test((Transaction)inventory)) @@ -192,8 +191,8 @@ private void OnVerack() private void OnVersionPayload(VersionPayload version) { Version = version; - AcceptRelay = version.Capabilities - .Where(u => u is AcceptRelayCapability) + IsFullNode = version.Capabilities + .Where(u => u is FullNodeCapability) .Any(); LastBlockIndex = version.Capabilities .Where(u => u is FullNodeCapability) From 311cd31e57e95d183dc249411533cf5eadc72590 Mon Sep 17 00:00:00 2001 From: Shargon Date: Mon, 13 May 2019 11:58:31 +0200 Subject: [PATCH 29/42] Clean code --- neo/Network/P2P/LocalNode.cs | 13 +++++-------- neo/Network/P2P/Peer.cs | 5 +++-- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index e3ada24b6f..5442416605 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -32,13 +32,13 @@ internal class SendDirectly { public IInventory Inventory; } public static readonly uint Nonce; public static string UserAgent { get; set; } - private static LocalNode _singleton; + private static LocalNode singleton; public static LocalNode Singleton { get { - while (_singleton == null) Thread.Sleep(10); - return _singleton; + while (singleton == null) Thread.Sleep(10); + return singleton; } } @@ -53,12 +53,12 @@ public LocalNode(NeoSystem system) { lock (lockObj) { - if (_singleton != null) + if (singleton != null) throw new InvalidOperationException(); this.system = system; protocol = Context.ActorOf(ProtocolHandler.Props(system)); - _singleton = this; + singleton = this; } } @@ -143,9 +143,6 @@ protected override void OnReceive(object message) base.OnReceive(message); switch (message) { - case UdpResponse udp: - SendUdp(udp.Sender, udp.Data); - break; case Udp.Received udpmsg: protocol.Tell(udpmsg); break; diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index bebfd1cafe..fa2359ce42 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -130,6 +130,9 @@ protected override void OnReceive(object message) case Udp.Bound _: udp_listener = Sender; break; + case UdpResponse udp: + udp_listener.Tell(Udp.Send.Create(udp.Data, udp.Sender)); + break; case Tcp.CommandFailed commandFailed: OnTcpCommandFailed(commandFailed.Cmd); break; @@ -187,8 +190,6 @@ private void OnStart(ChannelsStartConfig config) } } - protected void SendUdp(IPEndPoint remote, ByteString data) => udp_listener.Tell(Udp.Send.Create(data, remote)); - private void OnTcpConnected(IPEndPoint remote, IPEndPoint local) { ImmutableInterlocked.Update(ref ConnectingPeers, p => p.Remove(remote)); From b55d75ef0732f9e59f9e424bb630729484f6e422 Mon Sep 17 00:00:00 2001 From: Shargon Date: Tue, 14 May 2019 08:28:51 +0200 Subject: [PATCH 30/42] Parse message in LocalNode --- neo/Network/P2P/LocalNode.cs | 9 +++++--- neo/Network/P2P/ProtocolHandler.cs | 20 ++++++++---------- neo/Network/P2P/UdpRequest.cs | 33 ++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 14 deletions(-) create mode 100644 neo/Network/P2P/UdpRequest.cs diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index 5442416605..8ea202c656 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -143,9 +143,12 @@ protected override void OnReceive(object message) base.OnReceive(message); switch (message) { - case Udp.Received udpmsg: - protocol.Tell(udpmsg); - break; + case Udp.Received udp: + { + if (Message.TryDeserialize(udp.Data, out var msg) != udp.Data.Count) return; + protocol.Tell(new UdpRequest((IPEndPoint)udp.Sender, msg)); + break; + } case Message msg: BroadcastMessage(msg); break; diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index 988c1b17c4..060845a71b 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -121,33 +121,31 @@ protected override void OnReceive(object message) break; } - case Udp.Received udp: + case UdpRequest udp: { - if (Message.TryDeserialize(udp.Data, out var msg) != udp.Data.Count) return; - - switch (msg.Command) + switch (udp.Message.Command) { case MessageCommand.Transaction: { - if (msg.Payload.Size <= Transaction.MaxTransactionSize) - system.LocalNode.Tell(new LocalNode.Relay { Inventory = (Transaction)msg.Payload }); + if (udp.Message.Payload.Size <= Transaction.MaxTransactionSize) + system.LocalNode.Tell(new LocalNode.Relay { Inventory = (Transaction)udp.Message.Payload }); break; } case MessageCommand.Ping: { - var payload = (PingPayload)msg.Payload; - msg = Message.Create(MessageCommand.Pong, PingPayload.Create(Blockchain.Singleton.Height, payload.Nonce)); + var payload = (PingPayload)udp.Message.Payload; + var response = Message.Create(MessageCommand.Pong, PingPayload.Create(Blockchain.Singleton.Height, payload.Nonce)); - system.LocalNode.Tell(new UdpResponse((IPEndPoint)udp.Sender, ByteString.FromBytes(msg.ToArray()))); + system.LocalNode.Tell(new UdpResponse(udp.Sender, ByteString.FromBytes(response.ToArray()))); break; } case MessageCommand.GetAddr: { var networkAddresses = LocalNode.Singleton.GetPeers(); if (networkAddresses.Length == 0) return; - msg = Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses)); + var response = Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses)); - system.LocalNode.Tell(new UdpResponse((IPEndPoint)udp.Sender, ByteString.FromBytes(msg.ToArray()))); + system.LocalNode.Tell(new UdpResponse(udp.Sender, ByteString.FromBytes(response.ToArray()))); break; } } diff --git a/neo/Network/P2P/UdpRequest.cs b/neo/Network/P2P/UdpRequest.cs new file mode 100644 index 0000000000..4db063df65 --- /dev/null +++ b/neo/Network/P2P/UdpRequest.cs @@ -0,0 +1,33 @@ +using System.Net; + +namespace Neo.Network.P2P +{ + public class UdpRequest + { + /// + /// Sender + /// + public IPEndPoint Sender { get; set; } + + /// + /// Message + /// + public Message Message { get; set; } + + /// + /// Constructor + /// + public UdpRequest() { } + + /// + /// Constructor + /// + /// Sender + /// Message + public UdpRequest(IPEndPoint sender, Message message) + { + Sender = sender; + Message = message; + } + } +} \ No newline at end of file From 64f6c4e0e64c05c3fd2a00299f87d07a3409ce68 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 16 May 2019 10:21:56 +0200 Subject: [PATCH 31/42] Prevent PeekChar --- neo/Network/P2P/Capabilities/NodeCapabilityBase.cs | 11 ++++++++--- neo/Network/P2P/Payloads/NetworkAddressWithTime.cs | 2 +- neo/Network/P2P/Payloads/VersionPayload.cs | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs index c932d018a1..de0e0c7d5a 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs @@ -22,14 +22,19 @@ protected NodeCapabilityBase(NodeCapabilities type) Type = type; } - public virtual void Deserialize(BinaryReader reader) + public virtual void Deserialize(BinaryReader reader) { } + + public virtual void DeserializeWithType(BinaryReader reader) { if (reader.ReadByte() != (byte)Type) { throw new FormatException(); } + + Deserialize(reader); } + public virtual void Serialize(BinaryWriter writer) { writer.Write((byte)Type); @@ -45,8 +50,8 @@ public static NodeCapabilityBase Create(NodeCapabilities type) { case NodeCapabilities.TcpServer: case NodeCapabilities.UdpServer: - case NodeCapabilities.WsServer: return new ServerCapability(type); - case NodeCapabilities.FullNode: return new FullNodeCapability(); + case NodeCapabilities.WsServer: return new ServerCapability(type); + case NodeCapabilities.FullNode: return new FullNodeCapability(); default: throw new FormatException(); } diff --git a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index 1ecc3e7a25..bdadf43528 100644 --- a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -43,7 +43,7 @@ void ISerializable.Deserialize(BinaryReader reader) for (int x = 0, max = Capabilities.Length; x < max; x++) { - Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.PeekChar()); + Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.ReadByte()); Capabilities[x].Deserialize(reader); } } diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index 03a38ef53b..2ecaef49a8 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -51,7 +51,7 @@ void ISerializable.Deserialize(BinaryReader reader) for (int x = 0, max = Capabilities.Length; x < max; x++) { - Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.PeekChar()); + Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.ReadByte()); Capabilities[x].Deserialize(reader); } From 10694fe0728aa20df876d56b262e253e48df6eea Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 16 May 2019 16:39:41 +0200 Subject: [PATCH 32/42] Fix Serialize --- neo/Network/P2P/Capabilities/FullNodeCapability.cs | 4 ++-- neo/Network/P2P/Capabilities/NodeCapabilityBase.cs | 8 ++++---- neo/Network/P2P/Capabilities/ServerCapability.cs | 4 ++-- neo/Network/P2P/Payloads/NetworkAddressWithTime.cs | 2 +- neo/Network/P2P/Payloads/VersionPayload.cs | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/neo/Network/P2P/Capabilities/FullNodeCapability.cs b/neo/Network/P2P/Capabilities/FullNodeCapability.cs index 1d08d0f128..f0ee7cee1d 100644 --- a/neo/Network/P2P/Capabilities/FullNodeCapability.cs +++ b/neo/Network/P2P/Capabilities/FullNodeCapability.cs @@ -19,9 +19,9 @@ public FullNodeCapability(uint startHeight = 0) : base(NodeCapabilities.FullNode StartHeight = startHeight; } - public override void Deserialize(BinaryReader reader) + public override void DeserializeWithoutType(BinaryReader reader) { - base.Deserialize(reader); + base.DeserializeWithoutType(reader); StartHeight = reader.ReadUInt32(); } diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs index de0e0c7d5a..8e7d1e295b 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs @@ -22,18 +22,18 @@ protected NodeCapabilityBase(NodeCapabilities type) Type = type; } - public virtual void Deserialize(BinaryReader reader) { } - - public virtual void DeserializeWithType(BinaryReader reader) + public void Deserialize(BinaryReader reader) { if (reader.ReadByte() != (byte)Type) { throw new FormatException(); } - Deserialize(reader); + DeserializeWithoutType(reader); } + public virtual void DeserializeWithoutType(BinaryReader reader) { } + public virtual void Serialize(BinaryWriter writer) { diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index b3821fd9cf..353cc0c695 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -26,9 +26,9 @@ public ServerCapability(NodeCapabilities type, ushort port = 0) : base(type) Port = port; } - public override void Deserialize(BinaryReader reader) + public override void DeserializeWithoutType(BinaryReader reader) { - base.Deserialize(reader); + base.DeserializeWithoutType(reader); Port = reader.ReadUInt16(); } diff --git a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index bdadf43528..974173b71a 100644 --- a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -44,7 +44,7 @@ void ISerializable.Deserialize(BinaryReader reader) for (int x = 0, max = Capabilities.Length; x < max; x++) { Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.ReadByte()); - Capabilities[x].Deserialize(reader); + Capabilities[x].DeserializeWithoutType(reader); } } diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index 2ecaef49a8..52918663d7 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -52,7 +52,7 @@ void ISerializable.Deserialize(BinaryReader reader) for (int x = 0, max = Capabilities.Length; x < max; x++) { Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.ReadByte()); - Capabilities[x].Deserialize(reader); + Capabilities[x].DeserializeWithoutType(reader); } Nonce = reader.ReadUInt32(); From d8eaf7de60585976fb027e82c9cf06d716b2cc72 Mon Sep 17 00:00:00 2001 From: Shargon Date: Thu, 16 May 2019 16:44:17 +0200 Subject: [PATCH 33/42] Clean code --- neo/Network/P2P/Capabilities/NodeCapabilityBase.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs index 8e7d1e295b..0b61ebe361 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs @@ -34,7 +34,6 @@ public void Deserialize(BinaryReader reader) public virtual void DeserializeWithoutType(BinaryReader reader) { } - public virtual void Serialize(BinaryWriter writer) { writer.Write((byte)Type); From 485693effbdd9079261c4a1a7782de689b5fe555 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Fri, 17 May 2019 15:47:24 +0800 Subject: [PATCH 34/42] Move `ChannelsStartConfig` into `Neo.Network.P2P` --- neo/{ => Network/P2P}/ChannelsStartConfig.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) rename neo/{ => Network/P2P}/ChannelsStartConfig.cs (93%) diff --git a/neo/ChannelsStartConfig.cs b/neo/Network/P2P/ChannelsStartConfig.cs similarity index 93% rename from neo/ChannelsStartConfig.cs rename to neo/Network/P2P/ChannelsStartConfig.cs index fabdb4c86d..0ddeeedc2f 100644 --- a/neo/ChannelsStartConfig.cs +++ b/neo/Network/P2P/ChannelsStartConfig.cs @@ -1,7 +1,6 @@ -using Neo.Network.P2P; -using System.Net; +using System.Net; -namespace Neo +namespace Neo.Network.P2P { public class ChannelsStartConfig { @@ -35,4 +34,4 @@ public class ChannelsStartConfig /// public int MaxConnectionsPerAddress { get; set; } = 3; } -} \ No newline at end of file +} From 68cb16ca7b8ad11233b97e17b04a626995d881ff Mon Sep 17 00:00:00 2001 From: erikzhang Date: Fri, 17 May 2019 16:21:39 +0800 Subject: [PATCH 35/42] Optimize capabilities --- .../P2P/Capabilities/FullNodeCapability.cs | 10 ++-- .../P2P/Capabilities/NodeCapabilityBase.cs | 51 +++++++++++-------- .../P2P/Capabilities/ServerCapability.cs | 10 ++-- .../P2P/Payloads/NetworkAddressWithTime.cs | 5 +- neo/Network/P2P/Payloads/VersionPayload.cs | 5 +- 5 files changed, 39 insertions(+), 42 deletions(-) diff --git a/neo/Network/P2P/Capabilities/FullNodeCapability.cs b/neo/Network/P2P/Capabilities/FullNodeCapability.cs index f0ee7cee1d..6fc032d424 100644 --- a/neo/Network/P2P/Capabilities/FullNodeCapability.cs +++ b/neo/Network/P2P/Capabilities/FullNodeCapability.cs @@ -4,7 +4,7 @@ namespace Neo.Network.P2P.Capabilities { public class FullNodeCapability : NodeCapabilityBase { - public uint StartHeight { get; set; } + public uint StartHeight; public override int Size => base.Size + // Type @@ -19,16 +19,14 @@ public FullNodeCapability(uint startHeight = 0) : base(NodeCapabilities.FullNode StartHeight = startHeight; } - public override void DeserializeWithoutType(BinaryReader reader) + protected override void DeserializeWithoutType(BinaryReader reader) { - base.DeserializeWithoutType(reader); StartHeight = reader.ReadUInt32(); } - public override void Serialize(BinaryWriter writer) + protected override void SerializeWithoutType(BinaryWriter writer) { - base.Serialize(writer); writer.Write(StartHeight); } } -} \ No newline at end of file +} diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs index 0b61ebe361..44a79f56fd 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs @@ -6,12 +6,12 @@ namespace Neo.Network.P2P.Capabilities { public abstract class NodeCapabilityBase : ISerializable { - public virtual int Size => 1; // Type - /// /// Type /// - public NodeCapabilities Type { get; } + public readonly NodeCapabilities Type; + + public virtual int Size => sizeof(NodeCapabilities); // Type /// /// Constructor @@ -19,10 +19,10 @@ public abstract class NodeCapabilityBase : ISerializable /// Type protected NodeCapabilityBase(NodeCapabilities type) { - Type = type; + this.Type = type; } - public void Deserialize(BinaryReader reader) + void ISerializable.Deserialize(BinaryReader reader) { if (reader.ReadByte() != (byte)Type) { @@ -32,28 +32,35 @@ public void Deserialize(BinaryReader reader) DeserializeWithoutType(reader); } - public virtual void DeserializeWithoutType(BinaryReader reader) { } - - public virtual void Serialize(BinaryWriter writer) - { - writer.Write((byte)Type); - } - - /// - /// Create a new capability - /// - /// Type - public static NodeCapabilityBase Create(NodeCapabilities type) + public static NodeCapabilityBase DeserializeFrom(BinaryReader reader) { + NodeCapabilityBase result; + NodeCapabilities type = (NodeCapabilities)reader.ReadByte(); switch (type) { case NodeCapabilities.TcpServer: case NodeCapabilities.UdpServer: - case NodeCapabilities.WsServer: return new ServerCapability(type); - case NodeCapabilities.FullNode: return new FullNodeCapability(); - - default: throw new FormatException(); + case NodeCapabilities.WsServer: + result = new ServerCapability(type); + break; + case NodeCapabilities.FullNode: + result = new FullNodeCapability(); + break; + default: + throw new FormatException(); } + result.DeserializeWithoutType(reader); + return result; + } + + protected abstract void DeserializeWithoutType(BinaryReader reader); + + void ISerializable.Serialize(BinaryWriter writer) + { + writer.Write((byte)Type); + SerializeWithoutType(writer); } + + protected abstract void SerializeWithoutType(BinaryWriter writer); } -} \ No newline at end of file +} diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index 353cc0c695..9b0005b5ae 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -5,7 +5,7 @@ namespace Neo.Network.P2P.Capabilities { public class ServerCapability : NodeCapabilityBase { - public ushort Port { get; set; } + public ushort Port; public override int Size => base.Size + // Type @@ -26,16 +26,14 @@ public ServerCapability(NodeCapabilities type, ushort port = 0) : base(type) Port = port; } - public override void DeserializeWithoutType(BinaryReader reader) + protected override void DeserializeWithoutType(BinaryReader reader) { - base.DeserializeWithoutType(reader); Port = reader.ReadUInt16(); } - public override void Serialize(BinaryWriter writer) + protected override void SerializeWithoutType(BinaryWriter writer) { - base.Serialize(writer); writer.Write(Port); } } -} \ No newline at end of file +} diff --git a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index 974173b71a..98d9537776 100644 --- a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -42,10 +42,7 @@ void ISerializable.Deserialize(BinaryReader reader) Capabilities = new NodeCapabilityBase[reader.ReadVarInt(VersionPayload.MaxCapabilities)]; for (int x = 0, max = Capabilities.Length; x < max; x++) - { - Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.ReadByte()); - Capabilities[x].DeserializeWithoutType(reader); - } + Capabilities[x] = NodeCapabilityBase.DeserializeFrom(reader); } void ISerializable.Serialize(BinaryWriter writer) diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index 52918663d7..c71fde9e1b 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -50,10 +50,7 @@ void ISerializable.Deserialize(BinaryReader reader) Capabilities = new NodeCapabilityBase[reader.ReadVarInt(MaxCapabilities)]; for (int x = 0, max = Capabilities.Length; x < max; x++) - { - Capabilities[x] = NodeCapabilityBase.Create((NodeCapabilities)reader.ReadByte()); - Capabilities[x].DeserializeWithoutType(reader); - } + Capabilities[x] = NodeCapabilityBase.DeserializeFrom(reader); Nonce = reader.ReadUInt32(); UserAgent = reader.ReadVarString(1024); From 499fb927b528b27830b5bd2454c8b0a31eb58b1a Mon Sep 17 00:00:00 2001 From: erikzhang Date: Fri, 17 May 2019 16:31:14 +0800 Subject: [PATCH 36/42] Rename --- neo.UnitTests/UT_P2PMessage.cs | 6 ++-- .../P2P/Capabilities/FullNodeCapability.cs | 4 +-- ...odeCapabilityBase.cs => NodeCapability.cs} | 30 +++++++++---------- ...eCapabilities.cs => NodeCapabilityType.cs} | 4 +-- .../P2P/Capabilities/ServerCapability.cs | 6 ++-- .../P2P/Payloads/NetworkAddressWithTime.cs | 8 ++--- neo/Network/P2P/Payloads/VersionPayload.cs | 8 ++--- neo/Network/P2P/RemoteNode.cs | 10 +++---- 8 files changed, 38 insertions(+), 38 deletions(-) rename neo/Network/P2P/Capabilities/{NodeCapabilityBase.cs => NodeCapability.cs} (56%) rename neo/Network/P2P/Capabilities/{NodeCapabilities.cs => NodeCapabilityType.cs} (78%) diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/UT_P2PMessage.cs index de8bd29134..d2c7c2f849 100644 --- a/neo.UnitTests/UT_P2PMessage.cs +++ b/neo.UnitTests/UT_P2PMessage.cs @@ -86,9 +86,9 @@ public void Compression() Magic = 2, Timestamp = 5, Version = 6, - Capabilities = new NodeCapabilityBase[] + Capabilities = new NodeCapability[] { - new ServerCapability(NodeCapabilities.TcpServer, 25) + new ServerCapability(NodeCapabilityType.TcpServer, 25) } }; @@ -110,7 +110,7 @@ public void Compression() payloadCopy.Version.Should().Be(payload.Version); payloadCopy.Capabilities.Length.Should().Be(1); - ((ServerCapability)payloadCopy.Capabilities[0]).Type.Should().Be(NodeCapabilities.TcpServer); + ((ServerCapability)payloadCopy.Capabilities[0]).Type.Should().Be(NodeCapabilityType.TcpServer); ((ServerCapability)payloadCopy.Capabilities[0]).Port.Should().Be(25); } diff --git a/neo/Network/P2P/Capabilities/FullNodeCapability.cs b/neo/Network/P2P/Capabilities/FullNodeCapability.cs index 6fc032d424..7c2ae75845 100644 --- a/neo/Network/P2P/Capabilities/FullNodeCapability.cs +++ b/neo/Network/P2P/Capabilities/FullNodeCapability.cs @@ -2,7 +2,7 @@ namespace Neo.Network.P2P.Capabilities { - public class FullNodeCapability : NodeCapabilityBase + public class FullNodeCapability : NodeCapability { public uint StartHeight; @@ -14,7 +14,7 @@ public class FullNodeCapability : NodeCapabilityBase /// Constructor /// /// Start Height - public FullNodeCapability(uint startHeight = 0) : base(NodeCapabilities.FullNode) + public FullNodeCapability(uint startHeight = 0) : base(NodeCapabilityType.FullNode) { StartHeight = startHeight; } diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs b/neo/Network/P2P/Capabilities/NodeCapability.cs similarity index 56% rename from neo/Network/P2P/Capabilities/NodeCapabilityBase.cs rename to neo/Network/P2P/Capabilities/NodeCapability.cs index 44a79f56fd..c7530c93a8 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityBase.cs +++ b/neo/Network/P2P/Capabilities/NodeCapability.cs @@ -4,20 +4,20 @@ namespace Neo.Network.P2P.Capabilities { - public abstract class NodeCapabilityBase : ISerializable + public abstract class NodeCapability : ISerializable { /// /// Type /// - public readonly NodeCapabilities Type; + public readonly NodeCapabilityType Type; - public virtual int Size => sizeof(NodeCapabilities); // Type + public virtual int Size => sizeof(NodeCapabilityType); // Type /// /// Constructor /// /// Type - protected NodeCapabilityBase(NodeCapabilities type) + protected NodeCapability(NodeCapabilityType type) { this.Type = type; } @@ -32,25 +32,25 @@ void ISerializable.Deserialize(BinaryReader reader) DeserializeWithoutType(reader); } - public static NodeCapabilityBase DeserializeFrom(BinaryReader reader) + public static NodeCapability DeserializeFrom(BinaryReader reader) { - NodeCapabilityBase result; - NodeCapabilities type = (NodeCapabilities)reader.ReadByte(); + NodeCapability capability; + NodeCapabilityType type = (NodeCapabilityType)reader.ReadByte(); switch (type) { - case NodeCapabilities.TcpServer: - case NodeCapabilities.UdpServer: - case NodeCapabilities.WsServer: - result = new ServerCapability(type); + case NodeCapabilityType.TcpServer: + case NodeCapabilityType.UdpServer: + case NodeCapabilityType.WsServer: + capability = new ServerCapability(type); break; - case NodeCapabilities.FullNode: - result = new FullNodeCapability(); + case NodeCapabilityType.FullNode: + capability = new FullNodeCapability(); break; default: throw new FormatException(); } - result.DeserializeWithoutType(reader); - return result; + capability.DeserializeWithoutType(reader); + return capability; } protected abstract void DeserializeWithoutType(BinaryReader reader); diff --git a/neo/Network/P2P/Capabilities/NodeCapabilities.cs b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs similarity index 78% rename from neo/Network/P2P/Capabilities/NodeCapabilities.cs rename to neo/Network/P2P/Capabilities/NodeCapabilityType.cs index 9e43c1fe84..34d4ec24b3 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilities.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs @@ -1,6 +1,6 @@ namespace Neo.Network.P2P.Capabilities { - public enum NodeCapabilities : byte + public enum NodeCapabilityType : byte { TcpServer = 0x01, UdpServer = 0x02, @@ -8,4 +8,4 @@ public enum NodeCapabilities : byte FullNode = 0x10 } -} \ No newline at end of file +} diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index 9b0005b5ae..d79531a1ba 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -3,7 +3,7 @@ namespace Neo.Network.P2P.Capabilities { - public class ServerCapability : NodeCapabilityBase + public class ServerCapability : NodeCapability { public ushort Port; @@ -16,9 +16,9 @@ public class ServerCapability : NodeCapabilityBase /// /// Channel /// Port - public ServerCapability(NodeCapabilities type, ushort port = 0) : base(type) + public ServerCapability(NodeCapabilityType type, ushort port = 0) : base(type) { - if (type != NodeCapabilities.TcpServer && type != NodeCapabilities.UdpServer && type != NodeCapabilities.WsServer) + if (type != NodeCapabilityType.TcpServer && type != NodeCapabilityType.UdpServer && type != NodeCapabilityType.WsServer) { throw new ArgumentException(nameof(type)); } diff --git a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index 98d9537776..5e159b152c 100644 --- a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -12,11 +12,11 @@ public class NetworkAddressWithTime : ISerializable { public uint Timestamp; public IPEndPoint EndPoint; - public NodeCapabilityBase[] Capabilities; + public NodeCapability[] Capabilities; public int Size => sizeof(uint) + 16 + sizeof(ushort) + Capabilities.GetVarSize(); - public static NetworkAddressWithTime Create(IPEndPoint endpoint, uint timestamp, IEnumerable capabilities) + public static NetworkAddressWithTime Create(IPEndPoint endpoint, uint timestamp, IEnumerable capabilities) { return new NetworkAddressWithTime { @@ -39,10 +39,10 @@ void ISerializable.Deserialize(BinaryReader reader) // Capabilities - Capabilities = new NodeCapabilityBase[reader.ReadVarInt(VersionPayload.MaxCapabilities)]; + Capabilities = new NodeCapability[reader.ReadVarInt(VersionPayload.MaxCapabilities)]; for (int x = 0, max = Capabilities.Length; x < max; x++) - Capabilities[x] = NodeCapabilityBase.DeserializeFrom(reader); + Capabilities[x] = NodeCapability.DeserializeFrom(reader); } void ISerializable.Serialize(BinaryWriter writer) diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index c71fde9e1b..925e242cc9 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -14,7 +14,7 @@ public class VersionPayload : ISerializable public uint Magic; public uint Version; public uint Timestamp; - public NodeCapabilityBase[] Capabilities; + public NodeCapability[] Capabilities; public uint Nonce; public string UserAgent; @@ -26,7 +26,7 @@ public class VersionPayload : ISerializable sizeof(uint) + // Nonce UserAgent.GetVarSize(); // UserAgent - public static VersionPayload Create(uint nonce, string userAgent, IEnumerable capabilities) + public static VersionPayload Create(uint nonce, string userAgent, IEnumerable capabilities) { return new VersionPayload { @@ -47,10 +47,10 @@ void ISerializable.Deserialize(BinaryReader reader) // Capabilities - Capabilities = new NodeCapabilityBase[reader.ReadVarInt(MaxCapabilities)]; + Capabilities = new NodeCapability[reader.ReadVarInt(MaxCapabilities)]; for (int x = 0, max = Capabilities.Length; x < max; x++) - Capabilities[x] = NodeCapabilityBase.DeserializeFrom(reader); + Capabilities[x] = NodeCapability.DeserializeFrom(reader); Nonce = reader.ReadUInt32(); UserAgent = reader.ReadVarString(1024); diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 74989d4147..f8329d89c1 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -40,14 +40,14 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP this.protocol = Context.ActorOf(ProtocolHandler.Props(system)); LocalNode.Singleton.RemoteNodes.TryAdd(Self, this); - var capabilities = new List + var capabilities = new List { new FullNodeCapability(Blockchain.Singleton.Height) }; - if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.TcpServer, (ushort)LocalNode.Singleton.ListenerTcpPort)); - if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.UdpServer, (ushort)LocalNode.Singleton.ListenerUdpPort)); - if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new ServerCapability(NodeCapabilities.WsServer, (ushort)LocalNode.Singleton.ListenerWsPort)); + if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilityType.TcpServer, (ushort)LocalNode.Singleton.ListenerTcpPort)); + if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilityType.UdpServer, (ushort)LocalNode.Singleton.ListenerUdpPort)); + if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new ServerCapability(NodeCapabilityType.WsServer, (ushort)LocalNode.Singleton.ListenerWsPort)); SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, capabilities))); } @@ -199,7 +199,7 @@ private void OnVersionPayload(VersionPayload version) .Cast() .FirstOrDefault()?.StartHeight ?? 0; listenerTcpPort = version.Capabilities - .Where(u => u.Type == NodeCapabilities.TcpServer) + .Where(u => u.Type == NodeCapabilityType.TcpServer) .Cast() .First()?.Port ?? 0; From cefc6ae8ca18c8ed6018732a9a0eac51b0c290f5 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 17 May 2019 10:42:28 +0200 Subject: [PATCH 37/42] Update NodeCapabilityType.cs --- neo/Network/P2P/Capabilities/NodeCapabilityType.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityType.cs b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs index 34d4ec24b3..d0ff8c339a 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityType.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs @@ -2,9 +2,13 @@ { public enum NodeCapabilityType : byte { + #region Servers + TcpServer = 0x01, UdpServer = 0x02, WsServer = 0x03, + + #endregion FullNode = 0x10 } From e0fb9b8f5dedb083544d5c8f0e48255e4dae545c Mon Sep 17 00:00:00 2001 From: erikzhang Date: Fri, 17 May 2019 16:57:12 +0800 Subject: [PATCH 38/42] Optimize `RemoteNode` --- neo/Network/P2P/Connection.cs | 1 - neo/Network/P2P/RemoteNode.cs | 17 ++++------------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/neo/Network/P2P/Connection.cs b/neo/Network/P2P/Connection.cs index 10405c94ea..a6ae95f8f5 100644 --- a/neo/Network/P2P/Connection.cs +++ b/neo/Network/P2P/Connection.cs @@ -14,7 +14,6 @@ public abstract class Connection : UntypedActor public IPEndPoint Remote { get; } public IPEndPoint Local { get; } - public abstract int ListenerTcpPort { get; } private ICancelable timer; private readonly IActorRef tcp; diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index f8329d89c1..d051edda05 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -25,10 +25,9 @@ internal class Relay { public IInventory Inventory; } private BloomFilter bloom_filter; private bool ack = true; private bool verack = false; - private int listenerTcpPort = 0; public IPEndPoint Listener => new IPEndPoint(Remote.Address, ListenerTcpPort); - public override int ListenerTcpPort => listenerTcpPort; + public int ListenerTcpPort => Version.Capabilities.OfType().FirstOrDefault(p => p.Type == NodeCapabilityType.TcpServer)?.Port ?? 0; public VersionPayload Version { get; private set; } public uint LastBlockIndex { get; private set; } = 0; public bool IsFullNode { get; private set; } = false; @@ -191,17 +190,9 @@ private void OnVerack() private void OnVersionPayload(VersionPayload version) { Version = version; - IsFullNode = version.Capabilities - .Where(u => u is FullNodeCapability) - .Any(); - LastBlockIndex = version.Capabilities - .Where(u => u is FullNodeCapability) - .Cast() - .FirstOrDefault()?.StartHeight ?? 0; - listenerTcpPort = version.Capabilities - .Where(u => u.Type == NodeCapabilityType.TcpServer) - .Cast() - .First()?.Port ?? 0; + FullNodeCapability capability = (FullNodeCapability)version.Capabilities.FirstOrDefault(p => p.Type == NodeCapabilityType.FullNode); + IsFullNode = capability != null; + if (IsFullNode) LastBlockIndex = capability.StartHeight; if (version.Nonce == LocalNode.Nonce || version.Magic != ProtocolSettings.Default.Magic) { From 373cf31f7d5b3c48856385858918fc5c4074cc91 Mon Sep 17 00:00:00 2001 From: Shargon Date: Fri, 17 May 2019 14:35:21 +0200 Subject: [PATCH 39/42] Remove udp --- .../P2P/Capabilities/NodeCapability.cs | 1 - .../P2P/Capabilities/NodeCapabilityType.cs | 5 ++- .../P2P/Capabilities/ServerCapability.cs | 4 +-- neo/Network/P2P/ChannelsStartConfig.cs | 5 --- neo/Network/P2P/LocalNode.cs | 8 ----- neo/Network/P2P/Peer.cs | 18 +--------- neo/Network/P2P/ProtocolHandler.cs | 31 ----------------- neo/Network/P2P/RemoteNode.cs | 1 - neo/Network/P2P/UdpRequest.cs | 33 ------------------ neo/Network/P2P/UdpResponse.cs | 34 ------------------- neo/Network/RPC/RpcServer.cs | 1 - 11 files changed, 5 insertions(+), 136 deletions(-) delete mode 100644 neo/Network/P2P/UdpRequest.cs delete mode 100644 neo/Network/P2P/UdpResponse.cs diff --git a/neo/Network/P2P/Capabilities/NodeCapability.cs b/neo/Network/P2P/Capabilities/NodeCapability.cs index c7530c93a8..1160dad912 100644 --- a/neo/Network/P2P/Capabilities/NodeCapability.cs +++ b/neo/Network/P2P/Capabilities/NodeCapability.cs @@ -39,7 +39,6 @@ public static NodeCapability DeserializeFrom(BinaryReader reader) switch (type) { case NodeCapabilityType.TcpServer: - case NodeCapabilityType.UdpServer: case NodeCapabilityType.WsServer: capability = new ServerCapability(type); break; diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityType.cs b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs index d0ff8c339a..9aea3e4f3a 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityType.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs @@ -5,11 +5,10 @@ public enum NodeCapabilityType : byte #region Servers TcpServer = 0x01, - UdpServer = 0x02, - WsServer = 0x03, + WsServer = 0x02, #endregion FullNode = 0x10 } -} +} \ No newline at end of file diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index d79531a1ba..377b446c40 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -18,7 +18,7 @@ public class ServerCapability : NodeCapability /// Port public ServerCapability(NodeCapabilityType type, ushort port = 0) : base(type) { - if (type != NodeCapabilityType.TcpServer && type != NodeCapabilityType.UdpServer && type != NodeCapabilityType.WsServer) + if (type != NodeCapabilityType.TcpServer && type != NodeCapabilityType.WsServer) { throw new ArgumentException(nameof(type)); } @@ -36,4 +36,4 @@ protected override void SerializeWithoutType(BinaryWriter writer) writer.Write(Port); } } -} +} \ No newline at end of file diff --git a/neo/Network/P2P/ChannelsStartConfig.cs b/neo/Network/P2P/ChannelsStartConfig.cs index 0ddeeedc2f..809237b302 100644 --- a/neo/Network/P2P/ChannelsStartConfig.cs +++ b/neo/Network/P2P/ChannelsStartConfig.cs @@ -9,11 +9,6 @@ public class ChannelsStartConfig /// public IPEndPoint Tcp { get; set; } - /// - /// Udp configuration - /// - public IPEndPoint Udp { get; set; } - /// /// Web socket configuration /// diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index 8ea202c656..80d0427e87 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -24,7 +24,6 @@ internal class SendDirectly { public IInventory Inventory; } private static readonly object lockObj = new object(); private readonly NeoSystem system; - private readonly IActorRef protocol; internal readonly ConcurrentDictionary RemoteNodes = new ConcurrentDictionary(); public int ConnectedCount => RemoteNodes.Count; @@ -57,7 +56,6 @@ public LocalNode(NeoSystem system) throw new InvalidOperationException(); this.system = system; - protocol = Context.ActorOf(ProtocolHandler.Props(system)); singleton = this; } } @@ -143,12 +141,6 @@ protected override void OnReceive(object message) base.OnReceive(message); switch (message) { - case Udp.Received udp: - { - if (Message.TryDeserialize(udp.Data, out var msg) != udp.Data.Count) return; - protocol.Tell(new UdpRequest((IPEndPoint)udp.Sender, msg)); - break; - } case Message msg: BroadcastMessage(msg); break; diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index fa2359ce42..c7e7c9ecf7 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -28,10 +28,8 @@ private class WsConnected { public WebSocket Socket; public IPEndPoint Remote; p public const int DefaultMaxConnections = DefaultMinDesiredConnections * 4; private static readonly IActorRef tcp_manager = Context.System.Tcp(); - private static readonly IActorRef udp_manager = Context.System.Udp(); private IActorRef tcp_listener; - private IActorRef udp_listener; private IWebHost ws_host; private ICancelable timer; protected ActorSelection Connections => Context.ActorSelection("connection_*"); @@ -44,7 +42,6 @@ private class WsConnected { public WebSocket Socket; public IPEndPoint Remote; p protected HashSet TrustedIpAddresses { get; } = new HashSet(); public int ListenerTcpPort { get; private set; } - public int ListenerUdpPort { get; private set; } public int ListenerWsPort { get; private set; } public int MaxConnectionsPerAddress { get; private set; } = 3; public int MinDesiredConnections { get; private set; } = DefaultMinDesiredConnections; @@ -127,12 +124,6 @@ protected override void OnReceive(object message) case Tcp.Bound _: tcp_listener = Sender; break; - case Udp.Bound _: - udp_listener = Sender; - break; - case UdpResponse udp: - udp_listener.Tell(Udp.Send.Create(udp.Data, udp.Sender)); - break; case Tcp.CommandFailed commandFailed: OnTcpCommandFailed(commandFailed.Cmd); break; @@ -145,7 +136,6 @@ protected override void OnReceive(object message) private void OnStart(ChannelsStartConfig config) { ListenerTcpPort = config.Tcp == null ? 0 : config.Tcp.Port; - ListenerUdpPort = config.Udp == null ? 0 : config.Udp.Port; ListenerWsPort = config.WebSocket == null ? 0 : config.WebSocket.Port; MinDesiredConnections = config.MinDesiredConnections; @@ -153,7 +143,7 @@ private void OnStart(ChannelsStartConfig config) MaxConnectionsPerAddress = config.MaxConnectionsPerAddress; timer = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(0, 5000, Context.Self, new Timer(), ActorRefs.NoSender); - if ((ListenerTcpPort > 0 || ListenerWsPort > 0 || ListenerUdpPort > 0) + if ((ListenerTcpPort > 0 || ListenerWsPort > 0) && localAddresses.All(p => !p.IsIPv4MappedToIPv6 || IsIntranetAddress(p)) && UPnP.Discover()) { @@ -162,7 +152,6 @@ private void OnStart(ChannelsStartConfig config) localAddresses.Add(UPnP.GetExternalIP()); if (ListenerTcpPort > 0) UPnP.ForwardPort(ListenerTcpPort, ProtocolType.Tcp, "NEO Tcp"); - if (ListenerUdpPort > 0) UPnP.ForwardPort(ListenerUdpPort, ProtocolType.Udp, "NEO Udp"); if (ListenerWsPort > 0) UPnP.ForwardPort(ListenerWsPort, ProtocolType.Tcp, "NEO WebSocket"); } catch { } @@ -184,10 +173,6 @@ private void OnStart(ChannelsStartConfig config) ws_host = new WebHostBuilder().UseKestrel().UseUrls($"http://{host}:{ListenerWsPort}").Configure(app => app.UseWebSockets().Run(ProcessWebSocketAsync)).Build(); ws_host.Start(); } - if (ListenerUdpPort > 0) - { - udp_manager.Tell(new Udp.Bind(Self, config.Udp)); - } } private void OnTcpConnected(IPEndPoint remote, IPEndPoint local) @@ -269,7 +254,6 @@ protected override void PostStop() timer.CancelIfNotNull(); ws_host?.Dispose(); tcp_listener?.Tell(Tcp.Unbind.Instance); - udp_listener?.Tell(Udp.Unbind.Instance); base.PostStop(); } diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index 060845a71b..1d91c65aff 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -1,6 +1,5 @@ using Akka.Actor; using Akka.Configuration; -using Akka.IO; using Neo.Cryptography; using Neo.IO; using Neo.IO.Actors; @@ -119,36 +118,6 @@ protected override void OnReceive(object message) default: break; } - break; - } - case UdpRequest udp: - { - switch (udp.Message.Command) - { - case MessageCommand.Transaction: - { - if (udp.Message.Payload.Size <= Transaction.MaxTransactionSize) - system.LocalNode.Tell(new LocalNode.Relay { Inventory = (Transaction)udp.Message.Payload }); - break; - } - case MessageCommand.Ping: - { - var payload = (PingPayload)udp.Message.Payload; - var response = Message.Create(MessageCommand.Pong, PingPayload.Create(Blockchain.Singleton.Height, payload.Nonce)); - - system.LocalNode.Tell(new UdpResponse(udp.Sender, ByteString.FromBytes(response.ToArray()))); - break; - } - case MessageCommand.GetAddr: - { - var networkAddresses = LocalNode.Singleton.GetPeers(); - if (networkAddresses.Length == 0) return; - var response = Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses)); - - system.LocalNode.Tell(new UdpResponse(udp.Sender, ByteString.FromBytes(response.ToArray()))); - break; - } - } break; } } diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index d051edda05..16c5756485 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -45,7 +45,6 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP }; if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilityType.TcpServer, (ushort)LocalNode.Singleton.ListenerTcpPort)); - if (LocalNode.Singleton.ListenerUdpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilityType.UdpServer, (ushort)LocalNode.Singleton.ListenerUdpPort)); if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new ServerCapability(NodeCapabilityType.WsServer, (ushort)LocalNode.Singleton.ListenerWsPort)); SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, capabilities))); diff --git a/neo/Network/P2P/UdpRequest.cs b/neo/Network/P2P/UdpRequest.cs deleted file mode 100644 index 4db063df65..0000000000 --- a/neo/Network/P2P/UdpRequest.cs +++ /dev/null @@ -1,33 +0,0 @@ -using System.Net; - -namespace Neo.Network.P2P -{ - public class UdpRequest - { - /// - /// Sender - /// - public IPEndPoint Sender { get; set; } - - /// - /// Message - /// - public Message Message { get; set; } - - /// - /// Constructor - /// - public UdpRequest() { } - - /// - /// Constructor - /// - /// Sender - /// Message - public UdpRequest(IPEndPoint sender, Message message) - { - Sender = sender; - Message = message; - } - } -} \ No newline at end of file diff --git a/neo/Network/P2P/UdpResponse.cs b/neo/Network/P2P/UdpResponse.cs deleted file mode 100644 index 4d882de164..0000000000 --- a/neo/Network/P2P/UdpResponse.cs +++ /dev/null @@ -1,34 +0,0 @@ -using Akka.IO; -using System.Net; - -namespace Neo.Network.P2P -{ - public class UdpResponse - { - /// - /// Sender - /// - public IPEndPoint Sender { get; set; } - - /// - /// Data - /// - public ByteString Data { get; set; } - - /// - /// Constructor - /// - public UdpResponse() { } - - /// - /// Constructor - /// - /// Sender - /// Data - public UdpResponse(IPEndPoint sender, ByteString data) - { - Sender = sender; - Data = data; - } - } -} \ No newline at end of file diff --git a/neo/Network/RPC/RpcServer.cs b/neo/Network/RPC/RpcServer.cs index 6854aa7004..9e56a77864 100644 --- a/neo/Network/RPC/RpcServer.cs +++ b/neo/Network/RPC/RpcServer.cs @@ -567,7 +567,6 @@ private JObject GetVersion() { JObject json = new JObject(); json["tcpPort"] = LocalNode.Singleton.ListenerTcpPort; - json["udpPort"] = LocalNode.Singleton.ListenerUdpPort; json["wsPort"] = LocalNode.Singleton.ListenerWsPort; json["nonce"] = LocalNode.Nonce; json["useragent"] = LocalNode.UserAgent; From 6f97f556fb9eae09c66bf628a5e5c525b902b37d Mon Sep 17 00:00:00 2001 From: erikzhang Date: Fri, 17 May 2019 23:12:16 +0800 Subject: [PATCH 40/42] format --- neo.UnitTests/UT_P2PMessage.cs | 1 - neo/NeoSystem.cs | 4 +- .../P2P/Capabilities/NodeCapabilityType.cs | 8 +- .../P2P/Capabilities/ServerCapability.cs | 2 +- neo/Network/P2P/LocalNode.cs | 17 +- .../P2P/Payloads/NetworkAddressWithTime.cs | 5 +- neo/Network/P2P/Payloads/VersionPayload.cs | 21 +-- neo/Network/P2P/Peer.cs | 5 +- neo/Network/P2P/ProtocolHandler.cs | 169 +++++++++--------- neo/Network/P2P/RemoteNode.cs | 2 +- neo/Network/P2P/TaskSession.cs | 13 +- neo/Network/RPC/RpcServer.cs | 2 +- 12 files changed, 111 insertions(+), 138 deletions(-) diff --git a/neo.UnitTests/UT_P2PMessage.cs b/neo.UnitTests/UT_P2PMessage.cs index d2c7c2f849..e8fe25d83b 100644 --- a/neo.UnitTests/UT_P2PMessage.cs +++ b/neo.UnitTests/UT_P2PMessage.cs @@ -5,7 +5,6 @@ using Neo.Network.P2P; using Neo.Network.P2P.Capabilities; using Neo.Network.P2P.Payloads; -using System.Collections.Generic; namespace Neo.UnitTests { diff --git a/neo/NeoSystem.cs b/neo/NeoSystem.cs index f3f07cdc6d..4197bb9847 100644 --- a/neo/NeoSystem.cs +++ b/neo/NeoSystem.cs @@ -73,9 +73,9 @@ public void StartConsensus(Wallet wallet, Store consensus_store = null, bool ign Consensus.Tell(new ConsensusService.Start { IgnoreRecoveryLogs = ignoreRecoveryLogs }, Blockchain); } - public void StartNode(ChannelsStartConfig cfg) + public void StartNode(ChannelsStartConfig config) { - start_message = cfg; + start_message = config; if (!suspend) { diff --git a/neo/Network/P2P/Capabilities/NodeCapabilityType.cs b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs index 9aea3e4f3a..e8eb71850c 100644 --- a/neo/Network/P2P/Capabilities/NodeCapabilityType.cs +++ b/neo/Network/P2P/Capabilities/NodeCapabilityType.cs @@ -2,13 +2,11 @@ { public enum NodeCapabilityType : byte { - #region Servers - + //Servers TcpServer = 0x01, WsServer = 0x02, - - #endregion + //Others FullNode = 0x10 } -} \ No newline at end of file +} diff --git a/neo/Network/P2P/Capabilities/ServerCapability.cs b/neo/Network/P2P/Capabilities/ServerCapability.cs index 377b446c40..a27573d438 100644 --- a/neo/Network/P2P/Capabilities/ServerCapability.cs +++ b/neo/Network/P2P/Capabilities/ServerCapability.cs @@ -36,4 +36,4 @@ protected override void SerializeWithoutType(BinaryWriter writer) writer.Write(Port); } } -} \ No newline at end of file +} diff --git a/neo/Network/P2P/LocalNode.cs b/neo/Network/P2P/LocalNode.cs index 80d0427e87..6f30ed50cb 100644 --- a/neo/Network/P2P/LocalNode.cs +++ b/neo/Network/P2P/LocalNode.cs @@ -1,5 +1,4 @@ using Akka.Actor; -using Akka.IO; using Neo.IO; using Neo.Ledger; using Neo.Network.P2P.Payloads; @@ -54,7 +53,6 @@ public LocalNode(NeoSystem system) { if (singleton != null) throw new InvalidOperationException(); - this.system = system; singleton = this; } @@ -77,7 +75,7 @@ private static IPEndPoint GetIPEndpointFromHostPort(string hostNameOrAddress, in IPHostEntry entry; try { - entry = System.Net.Dns.GetHostEntry(hostNameOrAddress); + entry = Dns.GetHostEntry(hostNameOrAddress); } catch (SocketException) { @@ -158,19 +156,6 @@ protected override void OnReceive(object message) } } - public NetworkAddressWithTime[] GetPeers() - { - Random rand = new Random(); - - return RemoteNodes.Values - .Where(p => p.ListenerTcpPort > 0) - .GroupBy(p => p.Remote.Address, (k, g) => g.First()) - .OrderBy(p => rand.Next()) - .Take(AddrPayload.MaxCountToSend) - .Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Timestamp, p.Version.Capabilities)) - .ToArray(); - } - private void OnRelay(IInventory inventory) { if (inventory is Transaction transaction) diff --git a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index 5e159b152c..f30b77ec06 100644 --- a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -1,7 +1,6 @@ using Neo.IO; using Neo.Network.P2P.Capabilities; using System; -using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; @@ -16,13 +15,13 @@ public class NetworkAddressWithTime : ISerializable public int Size => sizeof(uint) + 16 + sizeof(ushort) + Capabilities.GetVarSize(); - public static NetworkAddressWithTime Create(IPEndPoint endpoint, uint timestamp, IEnumerable capabilities) + public static NetworkAddressWithTime Create(IPEndPoint endpoint, uint timestamp, params NodeCapability[] capabilities) { return new NetworkAddressWithTime { Timestamp = timestamp, EndPoint = endpoint, - Capabilities = capabilities.ToArray() + Capabilities = capabilities }; } diff --git a/neo/Network/P2P/Payloads/VersionPayload.cs b/neo/Network/P2P/Payloads/VersionPayload.cs index 925e242cc9..124f4923cd 100644 --- a/neo/Network/P2P/Payloads/VersionPayload.cs +++ b/neo/Network/P2P/Payloads/VersionPayload.cs @@ -1,9 +1,7 @@ using Neo.IO; using Neo.Network.P2P.Capabilities; using System; -using System.Collections.Generic; using System.IO; -using System.Linq; namespace Neo.Network.P2P.Payloads { @@ -14,19 +12,19 @@ public class VersionPayload : ISerializable public uint Magic; public uint Version; public uint Timestamp; - public NodeCapability[] Capabilities; public uint Nonce; public string UserAgent; + public NodeCapability[] Capabilities; public int Size => sizeof(uint) + // Magic sizeof(uint) + // Version sizeof(uint) + // Timestamp - Capabilities.GetVarSize() + // Capabilities sizeof(uint) + // Nonce - UserAgent.GetVarSize(); // UserAgent + UserAgent.GetVarSize() + // UserAgent + Capabilities.GetVarSize(); // Capabilities - public static VersionPayload Create(uint nonce, string userAgent, IEnumerable capabilities) + public static VersionPayload Create(uint nonce, string userAgent, params NodeCapability[] capabilities) { return new VersionPayload { @@ -35,7 +33,7 @@ public static VersionPayload Create(uint nonce, string userAgent, IEnumerable peers = LocalNode.Singleton.RemoteNodes.Values + .Where(p => p.ListenerTcpPort > 0) + .GroupBy(p => p.Remote.Address, (k, g) => g.First()) + .OrderBy(p => rand.Next()) + .Take(AddrPayload.MaxCountToSend); + NetworkAddressWithTime[] networkAddresses = peers.Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Timestamp, p.Version.Capabilities)).ToArray(); if (networkAddresses.Length == 0) return; Context.Parent.Tell(Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses))); } diff --git a/neo/Network/P2P/RemoteNode.cs b/neo/Network/P2P/RemoteNode.cs index 16c5756485..cafa1ebf20 100644 --- a/neo/Network/P2P/RemoteNode.cs +++ b/neo/Network/P2P/RemoteNode.cs @@ -47,7 +47,7 @@ public RemoteNode(NeoSystem system, object connection, IPEndPoint remote, IPEndP if (LocalNode.Singleton.ListenerTcpPort > 0) capabilities.Add(new ServerCapability(NodeCapabilityType.TcpServer, (ushort)LocalNode.Singleton.ListenerTcpPort)); if (LocalNode.Singleton.ListenerWsPort > 0) capabilities.Add(new ServerCapability(NodeCapabilityType.WsServer, (ushort)LocalNode.Singleton.ListenerWsPort)); - SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, capabilities))); + SendMessage(Message.Create(MessageCommand.Version, VersionPayload.Create(LocalNode.Nonce, LocalNode.UserAgent, capabilities.ToArray()))); } private void CheckMessageQueue() diff --git a/neo/Network/P2P/TaskSession.cs b/neo/Network/P2P/TaskSession.cs index 3a1f03b97d..6d732150f9 100644 --- a/neo/Network/P2P/TaskSession.cs +++ b/neo/Network/P2P/TaskSession.cs @@ -20,12 +20,11 @@ internal class TaskSession public TaskSession(IActorRef node, VersionPayload version) { - RemoteNode = node; - Version = version; - StartHeight = version.Capabilities - .Where(u => u is FullNodeCapability) - .Cast() - .FirstOrDefault()?.StartHeight ?? 0; + this.RemoteNode = node; + this.Version = version; + this.StartHeight = version.Capabilities + .OfType() + .FirstOrDefault()?.StartHeight ?? 0; } } -} \ No newline at end of file +} diff --git a/neo/Network/RPC/RpcServer.cs b/neo/Network/RPC/RpcServer.cs index 9e56a77864..6b5e7f549d 100644 --- a/neo/Network/RPC/RpcServer.cs +++ b/neo/Network/RPC/RpcServer.cs @@ -488,7 +488,7 @@ private JObject GetPeers() { JObject peerJson = new JObject(); peerJson["address"] = p.Remote.Address.ToString(); - peerJson["tcpPort"] = p.ListenerTcpPort; + peerJson["port"] = p.ListenerTcpPort; return peerJson; })); return json; From 2e214cc8e7891ac390715557e606d3332b15f1c6 Mon Sep 17 00:00:00 2001 From: erikzhang Date: Fri, 17 May 2019 23:23:32 +0800 Subject: [PATCH 41/42] Remove port from `NetworkAddressWithTime` --- .../P2P/Payloads/NetworkAddressWithTime.cs | 22 ++++++++----------- neo/Network/P2P/ProtocolHandler.cs | 4 ++-- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs index f30b77ec06..b311314b94 100644 --- a/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs +++ b/neo/Network/P2P/Payloads/NetworkAddressWithTime.cs @@ -10,17 +10,18 @@ namespace Neo.Network.P2P.Payloads public class NetworkAddressWithTime : ISerializable { public uint Timestamp; - public IPEndPoint EndPoint; + public IPAddress Address; public NodeCapability[] Capabilities; - public int Size => sizeof(uint) + 16 + sizeof(ushort) + Capabilities.GetVarSize(); + public IPEndPoint EndPoint => new IPEndPoint(Address, Capabilities.Where(p => p.Type == NodeCapabilityType.TcpServer).Select(p => (ServerCapability)p).FirstOrDefault()?.Port ?? 0); + public int Size => sizeof(uint) + 16 + Capabilities.GetVarSize(); - public static NetworkAddressWithTime Create(IPEndPoint endpoint, uint timestamp, params NodeCapability[] capabilities) + public static NetworkAddressWithTime Create(IPAddress address, uint timestamp, params NodeCapability[] capabilities) { return new NetworkAddressWithTime { Timestamp = timestamp, - EndPoint = endpoint, + Address = address, Capabilities = capabilities }; } @@ -28,18 +29,14 @@ public static NetworkAddressWithTime Create(IPEndPoint endpoint, uint timestamp, void ISerializable.Deserialize(BinaryReader reader) { Timestamp = reader.ReadUInt32(); + + // Address byte[] data = reader.ReadBytes(16); if (data.Length != 16) throw new FormatException(); - IPAddress address = new IPAddress(data).Unmap(); - data = reader.ReadBytes(2); - if (data.Length != 2) throw new FormatException(); - ushort port = data.Reverse().ToArray().ToUInt16(0); - EndPoint = new IPEndPoint(address, port); + Address = new IPAddress(data).Unmap(); // Capabilities - Capabilities = new NodeCapability[reader.ReadVarInt(VersionPayload.MaxCapabilities)]; - for (int x = 0, max = Capabilities.Length; x < max; x++) Capabilities[x] = NodeCapability.DeserializeFrom(reader); } @@ -47,8 +44,7 @@ void ISerializable.Deserialize(BinaryReader reader) void ISerializable.Serialize(BinaryWriter writer) { writer.Write(Timestamp); - writer.Write(EndPoint.Address.MapToIPv6().GetAddressBytes()); - writer.Write(BitConverter.GetBytes((ushort)EndPoint.Port).Reverse().ToArray()); + writer.Write(Address.MapToIPv6().GetAddressBytes()); writer.Write(Capabilities); } } diff --git a/neo/Network/P2P/ProtocolHandler.cs b/neo/Network/P2P/ProtocolHandler.cs index 356ec880b1..a42518afac 100644 --- a/neo/Network/P2P/ProtocolHandler.cs +++ b/neo/Network/P2P/ProtocolHandler.cs @@ -120,7 +120,7 @@ private void OnAddrMessageReceived(AddrPayload payload) { system.LocalNode.Tell(new Peer.Peers { - EndPoints = payload.AddressList.Select(p => p.EndPoint) + EndPoints = payload.AddressList.Select(p => p.EndPoint).Where(p => p.Port > 0) }); } @@ -150,7 +150,7 @@ private void OnGetAddrMessageReceived() .GroupBy(p => p.Remote.Address, (k, g) => g.First()) .OrderBy(p => rand.Next()) .Take(AddrPayload.MaxCountToSend); - NetworkAddressWithTime[] networkAddresses = peers.Select(p => NetworkAddressWithTime.Create(p.Listener, p.Version.Timestamp, p.Version.Capabilities)).ToArray(); + NetworkAddressWithTime[] networkAddresses = peers.Select(p => NetworkAddressWithTime.Create(p.Listener.Address, p.Version.Timestamp, p.Version.Capabilities)).ToArray(); if (networkAddresses.Length == 0) return; Context.Parent.Tell(Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses))); } From cd75d0d6710aa13ce2646596c0b5bdd5d21ab1eb Mon Sep 17 00:00:00 2001 From: erikzhang Date: Sat, 18 May 2019 01:19:03 +0800 Subject: [PATCH 42/42] rename --- neo/NeoSystem.cs | 4 ++-- .../P2P/{ChannelsStartConfig.cs => ChannelsConfig.cs} | 2 +- neo/Network/P2P/Peer.cs | 6 +++--- 3 files changed, 6 insertions(+), 6 deletions(-) rename neo/Network/P2P/{ChannelsStartConfig.cs => ChannelsConfig.cs} (95%) diff --git a/neo/NeoSystem.cs b/neo/NeoSystem.cs index 4197bb9847..f53d6efa76 100644 --- a/neo/NeoSystem.cs +++ b/neo/NeoSystem.cs @@ -27,7 +27,7 @@ public class NeoSystem : IDisposable public RpcServer RpcServer { get; private set; } private readonly Store store; - private ChannelsStartConfig start_message = null; + private ChannelsConfig start_message = null; private bool suspend = false; public NeoSystem(Store store) @@ -73,7 +73,7 @@ public void StartConsensus(Wallet wallet, Store consensus_store = null, bool ign Consensus.Tell(new ConsensusService.Start { IgnoreRecoveryLogs = ignoreRecoveryLogs }, Blockchain); } - public void StartNode(ChannelsStartConfig config) + public void StartNode(ChannelsConfig config) { start_message = config; diff --git a/neo/Network/P2P/ChannelsStartConfig.cs b/neo/Network/P2P/ChannelsConfig.cs similarity index 95% rename from neo/Network/P2P/ChannelsStartConfig.cs rename to neo/Network/P2P/ChannelsConfig.cs index 809237b302..fe09c54996 100644 --- a/neo/Network/P2P/ChannelsStartConfig.cs +++ b/neo/Network/P2P/ChannelsConfig.cs @@ -2,7 +2,7 @@ namespace Neo.Network.P2P { - public class ChannelsStartConfig + public class ChannelsConfig { /// /// Tcp configuration diff --git a/neo/Network/P2P/Peer.cs b/neo/Network/P2P/Peer.cs index 09cbd9c12c..eb21095685 100644 --- a/neo/Network/P2P/Peer.cs +++ b/neo/Network/P2P/Peer.cs @@ -102,8 +102,8 @@ protected override void OnReceive(object message) { switch (message) { - case ChannelsStartConfig start: - OnStart(start); + case ChannelsConfig config: + OnStart(config); break; case Timer _: OnTimer(); @@ -132,7 +132,7 @@ protected override void OnReceive(object message) } } - private void OnStart(ChannelsStartConfig config) + private void OnStart(ChannelsConfig config) { ListenerTcpPort = config.Tcp?.Port ?? 0; ListenerWsPort = config.WebSocket?.Port ?? 0;