Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Udp support #728

Closed
wants to merge 62 commits into from
Closed
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
f884a17
Udp support
shargon May 10, 2019
b8b814e
Fix unbind
shargon May 10, 2019
f7a4958
typo
shargon May 10, 2019
c5de11a
Merge branch 'master' into udp-server
vncoelho May 10, 2019
0170488
Unify GetPeers
shargon May 10, 2019
d59271a
Merge remote-tracking branch 'shargon/udp-server' into udp-server
shargon May 10, 2019
1192b3f
Clean Peer
shargon May 10, 2019
e284c37
Fix clean
shargon May 10, 2019
fe42fcd
Refactor VersionPayload
shargon May 10, 2019
5904954
Merge branch 'master' into udp-server
shargon May 10, 2019
b466f9d
Fix
shargon May 10, 2019
a1972c4
Merge remote-tracking branch 'shargon/udp-server' into udp-server
shargon May 10, 2019
3a54118
Unit test
shargon May 10, 2019
54a3087
Clean code
shargon May 10, 2019
2c4fc41
Clean line
shargon May 10, 2019
ee2c9f0
Fix ut
shargon May 10, 2019
77a0b1c
Simplify VersionPayload capabilities
shargon May 10, 2019
2215a55
Refactor VersionPayload capabilities
shargon May 11, 2019
ace3153
rename NodeConfig to ChannelsStartConfig
shargon May 11, 2019
72b82cf
Clean code
shargon May 11, 2019
2e8d558
Clean code
shargon May 11, 2019
be1b889
UPnP for Udp port
shargon May 11, 2019
765d6cf
Merge remote-tracking branch 'shargon/udp-server' into udp-server
shargon May 11, 2019
9485a03
Fx for ListennerTcpPort
shargon May 11, 2019
6d80ec1
Combine NodeCapabilities with ChannelType
shargon May 12, 2019
d0c1d7a
Merge branch 'master' into udp-server
erikzhang May 12, 2019
56d8d64
Summarize ServerCapability and remove reflection
shargon May 12, 2019
f238e46
Move Capabilities
shargon May 12, 2019
e9c9097
OnStart with ChannelsStartConfig
shargon May 12, 2019
c9447b6
Remove EndPointConfig
shargon May 12, 2019
1a86ae7
Move udp logic to ProtocolHandler
shargon May 12, 2019
766f589
Rename
shargon May 12, 2019
fd12eaf
Merge branch 'master' into udp-server
shargon May 12, 2019
c53f574
Remove Services and StartHeight from VersionPayload
shargon May 12, 2019
bb76f79
Merge remote-tracking branch 'shargon/udp-server' into udp-server
shargon May 12, 2019
f8ebcc0
Merge branch 'master' into udp-server
shargon May 13, 2019
fee3f86
Remove AcceptRelay
shargon May 13, 2019
311cd31
Clean code
shargon May 13, 2019
b55d75e
Parse message in LocalNode
shargon May 14, 2019
c8fc819
Merge branch 'master' into udp-server
shargon May 14, 2019
279babe
Merge branch 'master' into udp-server
shargon May 14, 2019
35489a8
Merge branch 'master' into udp-server
shargon May 16, 2019
32db242
Merge branch 'master' into udp-server
shargon May 16, 2019
64f6c4e
Prevent PeekChar
shargon May 16, 2019
10694fe
Fix Serialize
shargon May 16, 2019
957d52e
Merge branch 'master' into udp-server
shargon May 16, 2019
d8eaf7d
Clean code
shargon May 16, 2019
6762a8e
Merge remote-tracking branch 'shargon/udp-server' into udp-server
shargon May 16, 2019
485693e
Move `ChannelsStartConfig` into `Neo.Network.P2P`
erikzhang May 17, 2019
c425700
Merge branch 'master' into udp-server
shargon May 17, 2019
68cb16c
Optimize capabilities
erikzhang May 17, 2019
499fb92
Rename
erikzhang May 17, 2019
cefc6ae
Update NodeCapabilityType.cs
shargon May 17, 2019
e0fb9b8
Optimize `RemoteNode`
erikzhang May 17, 2019
53ad245
Merge branch 'master' into udp-server
shargon May 19, 2019
f8b1074
Clean code
shargon May 19, 2019
1ffc01c
Clean code
shargon May 19, 2019
e3dba12
Clean code
shargon May 19, 2019
0ac4a63
Clean code
shargon May 19, 2019
2e36378
Merge branch 'master' into udp-server
vncoelho May 24, 2019
6a277a8
Merge branch 'master' into udp-server
shargon May 27, 2019
cfbd114
Merge branch 'master' into udp-server
shargon Jun 15, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 15 additions & 3 deletions neo.UnitTests/UT_P2PMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down Expand Up @@ -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<NodeCapabilities, INodeCapability>()
};

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();

Expand All @@ -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'));

}
}
}
27 changes: 27 additions & 0 deletions neo/EndPointConfig.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using System.Net;

namespace Neo
{
public class EndPointConfig
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
{
/// <summary>
/// Address
/// </summary>
public string Address { get; set; } = "0.0.0.0";

/// <summary>
/// Port
/// </summary>
public ushort Port { get; set; } = 0;

/// <summary>
/// Ip EndPoint
/// </summary>
public IPEndPoint EndPoint => new IPEndPoint(IPAddress.Parse(Address), Port);

/// <summary>
/// Return true if the address and port are valid
/// </summary>
public bool IsValid => IPAddress.TryParse(Address, out var addr) && Port > 0;
}
}
15 changes: 4 additions & 11 deletions neo/NeoSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
private bool suspend = false;

public NeoSystem(Store store)
Expand Down Expand Up @@ -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)
{
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
start_message = new Peer.Start
{
Port = port,
WsPort = wsPort,
MinDesiredConnections = minDesiredConnections,
MaxConnections = maxConnections,
MaxConnectionsPerAddress = maxConnectionsPerAddress
};
start_message = cfg;

if (!suspend)
{
LocalNode.Tell(start_message);
Expand Down
6 changes: 6 additions & 0 deletions neo/Network/P2P/Capabilities/INodeCapability.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
using Neo.IO;

namespace Neo.Network.P2P.Capabilities
{
public interface INodeCapability : ISerializable { }
}
19 changes: 19 additions & 0 deletions neo/Network/P2P/Capabilities/NodeCapabilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Neo.IO.Caching;

namespace Neo.Network.P2P.Capabilities
{
public enum NodeCapabilities : byte
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was a nice catch.

The FullNode flag means that FullNodeCapabilities are enabled?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before we only exposed services, now we can add extra information in each service, for "full node" the height, for "tcpServer" the port... etc

{
[ReflectionCache(typeof(UInt16Capability))]
TcpPort = 0x00,

[ReflectionCache(typeof(UInt16Capability))]
UdpPort = 0x01,

[ReflectionCache(typeof(UInt16Capability))]
WebsocketPort = 0x02,

[ReflectionCache(typeof(StringCapability))]
RpcServerAddress = 0x03
}
}
38 changes: 38 additions & 0 deletions neo/Network/P2P/Capabilities/StringCapability.cs
Original file line number Diff line number Diff line change
@@ -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();

/// <summary>
/// Constructor
/// </summary>
public StringCapability() { }

/// <summary>
/// Constructor
/// </summary>
/// <param name="value">Value</param>
public StringCapability(string value)
{
Value = value
}

public void Deserialize(BinaryReader reader)
{
Value = reader.ReadVarString(MaxStringCapability);
}

public void Serialize(BinaryWriter writer)
{
writer.WriteVarString(Value);
}
}
}
35 changes: 35 additions & 0 deletions neo/Network/P2P/Capabilities/UInt16Capability.cs
Original file line number Diff line number Diff line change
@@ -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);

/// <summary>
/// Constructor
/// </summary>
public UInt16Capability() { }

/// <summary>
/// Constructor
/// </summary>
/// <param name="value">Value</param>
public UInt16Capability(ushort value)
{
Value = value;
}

public void Deserialize(BinaryReader reader)
{
Value = reader.ReadUInt16();
}

public void Serialize(BinaryWriter writer)
{
writer.Write(Value);
}
}
}
2 changes: 1 addition & 1 deletion neo/Network/P2P/Connection.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
erikzhang marked this conversation as resolved.
Show resolved Hide resolved

private ICancelable timer;
private readonly IActorRef tcp;
Expand Down
56 changes: 50 additions & 6 deletions neo/Network/P2P/LocalNode.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Akka.Actor;
using Akka.IO;
using Neo.IO;
using Neo.Ledger;
using Neo.Network.P2P.Payloads;
Expand Down Expand Up @@ -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;
}
}

Expand All @@ -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;
}
}

Expand All @@ -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)
{
Expand Down Expand Up @@ -156,6 +157,49 @@ protected override void OnReceive(object message)
}
}

protected override void OnUdpMessage(IPEndPoint remote, ByteString data)
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
{
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<RemoteNode> peers = 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();
}

private void OnRelay(IInventory inventory)
{
if (inventory is Transaction transaction)
Expand Down
Loading