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

Adding disconnection reason and its use for ensuring better p2p performance #1154

Closed
wants to merge 166 commits into from
Closed
Show file tree
Hide file tree
Changes from 148 commits
Commits
Show all changes
166 commits
Select commit Hold shift + click to select a range
93060a2
Merge pull request #1 from neo-project/master
Tommo-L Jun 4, 2019
f4371d3
Merge pull request #3 from neo-project/master
Tommo-L Jun 20, 2019
5784ac5
Merge pull request #5 from neo-project/master
Tommo-L Jun 28, 2019
d8ab5e2
Merge pull request #6 from neo-project/master
Tommo-L Jul 8, 2019
9a1f07a
Merge pull request #7 from neo-project/master
Tommo-L Jul 16, 2019
ee20bc9
add internal to DB and WriteBatch
eryeer Jul 16, 2019
4d873e2
Merge branch 'master' into master
eryeer Jul 17, 2019
81dd495
Merge branch 'master' into master
lock9 Jul 18, 2019
5518fbd
Merge branch 'master' into master
eryeer Jul 22, 2019
60a1845
Merge pull request #8 from neo-project/master
Tommo-L Sep 23, 2019
97c2f34
Merge pull request #9 from neo-project/master
Tommo-L Sep 26, 2019
639c739
Merge remote-tracking branch 'upstream/master'
Sep 27, 2019
6376be1
Merge remote-tracking branch 'upstream/master'
Oct 9, 2019
3ef8f92
add disconnect message
Oct 10, 2019
85f6103
rename DisconnectionPayload to DisconnectPayload
Oct 10, 2019
bfef982
remove OnDisconnect handler from RemoteNode to LocalNode as tcp.close…
Oct 11, 2019
90e47f4
format
Oct 11, 2019
1ace691
add websocket disconnect
Oct 11, 2019
f5c21e4
format
Oct 11, 2019
b49534f
format
Oct 11, 2019
f1468d5
format
Oct 11, 2019
b5ed267
format
Oct 11, 2019
cbc1c2a
fix UT_LocalNode
Oct 11, 2019
2588118
rename MaxConnectionPerAddressReached
Oct 12, 2019
383e043
fix trusted ip addresses
Oct 12, 2019
da0abb5
format remove whitespace
Oct 12, 2019
575c37c
change tcp.close => tcp.abort
Oct 12, 2019
df39f5e
format
Oct 12, 2019
b76b04d
reset db.cs writebatch.cs
Oct 12, 2019
8e2b0fa
typo received
Oct 12, 2019
8eda67d
remove UntrustedIpAddresses
Oct 14, 2019
4600839
optimize ConnectedPeers filter
Oct 14, 2019
59e4f0d
Merge branch 'master' into fix_p2p_disconnect
shargon Oct 16, 2019
082d785
remove Message field in DisconnectPayload
Oct 17, 2019
aa2ea6d
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Oct 17, 2019
e46d02e
add emtpyactor
Oct 17, 2019
1e1aedf
remove async
Oct 17, 2019
0561c32
fix typo
Oct 17, 2019
226481a
remove DisconnectWithAddresses method
Oct 17, 2019
0100068
remove DisconnectWithAddresses method
Oct 17, 2019
07d98fb
Merge branch 'master' into fix_p2p_disconnect
vncoelho Oct 18, 2019
a34254b
Merge remote-tracking branch 'upstream/master'
Oct 18, 2019
1dff642
Merge branch 'master' into fix_p2p_disconnect
shargon Oct 18, 2019
2d96b3f
add localnode remote address
Oct 21, 2019
5b29aaf
refactor IsDuplicateConnection
Oct 21, 2019
b481a03
remove remotenode after received disconnect msg
Oct 22, 2019
a9bf799
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Oct 22, 2019
c9b52d6
fix LocalNode#GetRandomConnectedPeers
Oct 22, 2019
d3bd21b
fix LocalNode#GetRandomConnectedPeers
Oct 22, 2019
aee96f8
Merge remote-tracking branch 'upstream/master'
Oct 22, 2019
b514efe
Merge branch 'master' into fix_p2p_disconnect
shargon Oct 23, 2019
ee3509f
fix localnode ut
Oct 23, 2019
7afa712
Merge branch 'master' into fix_p2p_disconnect
vncoelho Oct 23, 2019
6636ce8
Merge remote-tracking branch 'upstream/master'
Oct 25, 2019
8e46b44
Merge branch 'master' into fix_p2p_disconnect
vncoelho Oct 31, 2019
ecbbdc9
Merge remote-tracking branch 'upstream/master' into fix_p2p_disconnect
Nov 1, 2019
ccb3f67
refactor connection
Nov 1, 2019
7b1a363
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Nov 1, 2019
b0a4165
Merge remote-tracking branch 'upstream/master'
Nov 4, 2019
298c7da
Merge remote-tracking branch 'upstream/master'
Nov 8, 2019
4dd37bb
Merge remote-tracking branch 'upstream/master'
hope2028 Nov 11, 2019
cf6037f
merge and fix conflicts
hope2028 Nov 11, 2019
d11bab2
fix conflicts
hope2028 Nov 11, 2019
138eeb9
Merge branch 'master' into fix_p2p_disconnect
Nov 13, 2019
bb9bb74
fix ut bug
Nov 13, 2019
ee21124
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Nov 13, 2019
a156012
Merge remote-tracking branch 'upstream/master'
Nov 13, 2019
827c7bd
refactor LocalNode.CheckDuplicateConnection
Nov 15, 2019
f1ab573
rename DuplicateConnection to DuplicateNone and refactor ConnectedPeers
Nov 15, 2019
59432fc
Merge remote-tracking branch 'upstream/master'
Nov 15, 2019
1b701b8
add limit to the LocalAddresses
Nov 15, 2019
f0f922d
change the limit to MaxConnections
Nov 15, 2019
967de15
remove assign null
Nov 15, 2019
6b7db44
Merge branch 'master' into fix_p2p_disconnect
shargon Nov 15, 2019
ae78293
Merge remote-tracking branch 'upstream/master'
Nov 18, 2019
6adc3da
refactor LocalNode, RemoteNode
Nov 21, 2019
a208484
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Nov 21, 2019
e5022b7
Merge branch 'master' into fix_p2p_disconnect
Nov 21, 2019
64e01fb
reset test ip
Nov 21, 2019
76b60bc
fix ut
Nov 21, 2019
66eb08a
format
Nov 21, 2019
34d5534
Update MessageCommand.cs
erikzhang Nov 21, 2019
49c4267
Split classes
erikzhang Nov 21, 2019
cb75a76
Update DisconnectPayload.cs
erikzhang Nov 21, 2019
9d14691
Update LocalNode.cs
erikzhang Nov 21, 2019
86efb94
send disconnect msg attach with 10 addrs
Nov 21, 2019
3ab636c
replace 10 by MinDesiredConnections
Nov 21, 2019
817ba9b
fix Test_Peer_Max_Per_Address_Connection_Reached and add more assertion
Nov 21, 2019
6b06c23
reset MinDesiredConnections to const 10
Nov 21, 2019
eb23c1d
Process `DisconnectPayload` in `ProtocolHandler`
erikzhang Nov 21, 2019
39f6559
remove useless ut in UT_LocalNode
Nov 21, 2019
a370743
replace ActorRefs.NoSender by ActorRefs.Nobody
Nov 22, 2019
8805ce6
Merge branch 'master' into fix_p2p_disconnect
shargon Nov 22, 2019
50a8b60
merge and format
Nov 26, 2019
5a6bf5e
Merge remote-tracking branch 'upstream/master'
Nov 26, 2019
c4b06e0
up UT_localnode
Nov 26, 2019
d67357d
Merge branch 'master' into fix_p2p_disconnect
Nov 26, 2019
a4aba34
fix ProtocolHandler.OnDisconnectMessageReceived
Nov 26, 2019
bc6c977
merge and fix conflicts
Nov 27, 2019
a492163
revert rand
Nov 28, 2019
cd4d6b9
Merge branch 'master' into fix_p2p_disconnect
Nov 28, 2019
f7a1fe2
add log
Nov 28, 2019
f566864
add comments
Nov 28, 2019
ab487a6
Merge branch 'master' into fix_p2p_disconnect
erikzhang Nov 29, 2019
28b7349
replace Context.Stop(Parent) by Context.watch
Dec 2, 2019
7ebe9cc
merge and fix conflicts
Dec 2, 2019
7821961
Fix whitespace formatting
Dec 2, 2019
47e0935
Merge branch 'master' into fix_p2p_disconnect
lock9 Dec 2, 2019
fe0319a
optimize code in DisconnectPayload.cs
Dec 3, 2019
3e4aee4
refactor LocalNode & Peer.cs
Dec 3, 2019
9957793
Merge branch 'master' into fix_p2p_disconnect
Dec 3, 2019
fc68609
Merge branch 'master' into fix_p2p_disconnect
Dec 4, 2019
5c3f26c
Merge branch 'master' of https://github.com/Tommo-L/neo into fix_p2p_…
Dec 5, 2019
29becc0
Merge branch 'master' of https://github.com/neo-project/neo
Dec 5, 2019
3261c50
Merge branch 'master' into fix_p2p_disconnect
Dec 9, 2019
568bea7
Merge remote-tracking branch 'upstream/master'
Dec 9, 2019
3605a85
Merge branch 'master' into fix_p2p_disconnect
vncoelho Dec 10, 2019
76a25cd
Merge remote-tracking branch 'upstream/master'
Dec 11, 2019
de89b48
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Dec 12, 2019
b465fac
reset
Dec 12, 2019
7557099
merge and fix conflicts
Dec 12, 2019
f1cfc84
merge and refactor LocalNode
Dec 16, 2019
46d8894
Merge branch 'master' into fix_p2p_disconnect
Dec 16, 2019
f3e9a9b
format
Dec 16, 2019
7e8bf18
Merge remote-tracking branch 'upstream/master'
Dec 16, 2019
4b0b0dc
Merge remote-tracking branch 'upstream/master'
Dec 23, 2019
c35f038
Merge branch 'master' into fix_p2p_disconnect
Dec 23, 2019
1744b5f
Merge remote-tracking branch 'upstream/master'
Dec 26, 2019
2642400
Merge remote-tracking branch 'upstream/master'
Dec 29, 2019
620ec27
Merge remote-tracking branch 'upstream/master'
Dec 30, 2019
1a476cf
Merge branch 'master' into fix_p2p_disconnect
vncoelho Jan 6, 2020
eacfef5
add more comments
Jan 7, 2020
e85698d
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Jan 7, 2020
29ed287
Merge remote-tracking branch 'upstream/master'
Jan 7, 2020
34dedbc
Merge branch 'master' into fix_p2p_disconnect
Jan 7, 2020
bc1135e
remove useless line
Jan 7, 2020
a8cc787
Merge branch 'master' into fix_p2p_disconnect
shargon Mar 9, 2020
9409fe2
Merge branch 'master' into fix_p2p_disconnect
Mar 15, 2020
3ab6a92
optimize
Mar 15, 2020
65d4128
add commments to trigger github action
Mar 15, 2020
0fb51cb
Merge branch 'master' into fix_p2p_disconnect
erikzhang Mar 24, 2020
8e9ddb3
Remove empty line
erikzhang Mar 24, 2020
ff7c040
remove add localaddress when the same nonce
Mar 25, 2020
829c41c
Merge branch 'master' into fix_p2p_disconnect
Mar 25, 2020
4af40c1
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Mar 25, 2020
c1710e1
private
erikzhang Mar 25, 2020
2a6aa64
add OnTcpConnected virutal modifier
Mar 25, 2020
1aace70
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Mar 25, 2020
05b1cfd
add Disconnect method
Mar 26, 2020
a3e2818
refactor Disconnect to TcpDisconnect and WsDisconnect
Mar 26, 2020
bd3bf6c
add virtual TcpDisconnect, WsDisconnect with reason argument
Mar 26, 2020
fa5ce65
add comments to trigger github action, skip UT_ProtocolSettings fail
Mar 26, 2020
07934f6
private
erikzhang Mar 27, 2020
55e654f
reset remove peers from ConnectingPeers
Mar 27, 2020
19a145c
Merge branch 'fix_p2p_disconnect' of https://github.com/Tommo-L/neo i…
Mar 27, 2020
04ea624
foramt
Mar 27, 2020
fb29add
Merge branch 'master' into fix_p2p_disconnect
vncoelho Mar 27, 2020
e93907f
fix conflicts
Apr 14, 2020
b56613b
format
Apr 14, 2020
615fcda
format
Apr 14, 2020
e07724b
Merge branch 'master' into fix_p2p_disconnect
vncoelho Apr 28, 2020
5b637c6
Merge branch 'master' into fix_p2p_disconnect
shargon Apr 30, 2020
857c2f6
Merge branch 'master' into fix_p2p_disconnect
May 13, 2020
3beb4b8
Merge branch 'master' into fix_p2p_disconnect
vncoelho May 19, 2020
0f714dd
Merge branch 'master' into fix_p2p_disconnect
Jun 5, 2020
626bc8c
remove CheckDuplicateNonce
Jun 5, 2020
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
115 changes: 114 additions & 1 deletion src/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 All @@ -8,6 +9,7 @@
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
Expand All @@ -22,6 +24,7 @@ internal class SendDirectly { public IInventory Inventory; }

public const uint ProtocolVersion = 0;
private const int MaxCountFromSeedList = 5;
private const int PeersToReturnOnDisconnect = 10;
private readonly IPEndPoint[] SeedList = new IPEndPoint[ProtocolSettings.Default.SeedList.Length];

private static readonly object lockObj = new object();
Expand Down Expand Up @@ -104,7 +107,7 @@ private static IPEndPoint GetIPEndpointFromHostPort(string hostNameOrAddress, in
IPHostEntry entry;
try
{
entry = Dns.GetHostEntry(hostNameOrAddress);
entry = System.Net.Dns.GetHostEntry(hostNameOrAddress);
}
catch (SocketException)
{
Expand All @@ -129,6 +132,37 @@ internal static IPEndPoint GetIpEndPoint(string hostAndPort)
return null;
}

/// <summary>
/// Check duplicated duplicated Nonce. Usually it occurs when a new remote connection is established, which checks its counterpart's Nonce value. <br/>
/// If Nonce is the same we check if the Remote can be added to the known LocalAddresses.<br/>
/// If it is equal to the Nonce of other RemoteNode, we just return true, else we'll return false and update the Listener address of the connected remote node.
/// </summary>
/// <param name="remoteActor">Remote node actor</param>
/// <param name="remoteNode">Remote node</param>
public bool CheckDuplicateNonce(IActorRef remoteActor, RemoteNode remoteNode)
Tommo-L marked this conversation as resolved.
Show resolved Hide resolved
{
var version = remoteNode.Version;
var remote = remoteNode.Remote;

if (remote is null) return false;
if (version.Nonce == Nonce) return true;

foreach (var pair in RemoteNodes)
Copy link
Contributor

Choose a reason for hiding this comment

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

This foreach loop could be avoided by adjusting the data structures.
The Peer has the ConnectedAddresses map, if we need to be able to map from addresses to remote nodes maybe that relationship should be modeled.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Here we are filtering duplicate connections through two attributes: nonce, Address.

{
var otherNode = pair.Value;
if (otherNode != remoteNode && otherNode.Remote.Address.Equals(remote.Address) && otherNode.Version?.Nonce == version.Nonce)
{// filter duplicate connections
return true;
}
}
if (remote.Port != remoteNode.ListenerTcpPort && remoteNode.ListenerTcpPort != 0)
{
ConnectedPeers.TryUpdate(remoteActor, remoteNode.Listener, remote);
}

return false;
}

public IEnumerable<RemoteNode> GetRemoteNodes()
{
return RemoteNodes.Values;
Expand Down Expand Up @@ -162,6 +196,21 @@ protected override void NeedMorePeers(int count)
}
}

/// <summary>
/// Get a maximum number of count random peer currently connected with the node.
/// </summary>
/// <param name="count"></param>
/// <returns></returns>
public NetworkAddressWithTime[] GetRandomConnectedPeers(int count)
Tommo-L marked this conversation as resolved.
Show resolved Hide resolved
{
Random rand = new Random();
IEnumerable<RemoteNode> peers = RemoteNodes.Values
.Where(p => p.ListenerTcpPort > 0)
.OrderBy(p => rand.Next())
.Take(count);
return peers.Select(p => NetworkAddressWithTime.Create(p.Listener.Address, p.Version.Timestamp, p.Version.Capabilities)).ToArray();
}

protected override void OnReceive(object message)
{
base.OnReceive(message);
Expand Down Expand Up @@ -214,6 +263,70 @@ private void OnRelayDirectly(IInventory inventory)

private void OnSendDirectly(IInventory inventory) => SendToRemoteNodes(inventory);

protected override void OnTcpConnected(IPEndPoint remote, IPEndPoint local)
{
// Pre-check includes MaxConnections, MaxConnectionsPerAddress. If the check fails, it'll seed the error message.
Tcp.Message errorMsg = null;
if (MaxConnections != -1 && ConnectedPeers.Count >= MaxConnections && !TrustedIpAddresses.Contains(remote.Address))
{
Message reason = CreateDisconnectMessage(DisconnectReason.MaxConnectionReached);
errorMsg = Tcp.Write.Create(ByteString.FromBytes(reason.ToArray()));
}
ConnectedAddresses.TryGetValue(remote.Address, out int count);
if (count >= MaxConnectionsPerAddress)
{
Message reason = CreateDisconnectMessage(DisconnectReason.MaxConnectionPerAddressReached);
errorMsg = Tcp.Write.Create(ByteString.FromBytes(reason.ToArray()));
}
if (errorMsg != null)
{
Sender.Tell(new Tcp.Register(ActorRefs.Nobody));
Sender.Ask(errorMsg).ContinueWith(t => Sender.Tell(Tcp.Abort.Instance));
return;
}

base.OnTcpConnected(remote, local);
}

protected override void OnWsConnected(WebSocket ws, IPEndPoint remote, IPEndPoint local)
{
// Pre-check includes MaxConnectionsPerAddress. If the check fails, it'll send the error message.
ConnectedAddresses.TryGetValue(remote.Address, out int count);
if (count >= MaxConnectionsPerAddress)
{
var disconnectMessage = CreateDisconnectMessage(DisconnectReason.MaxConnectionPerAddressReached);
var errorMsg = new ArraySegment<byte>(disconnectMessage.ToArray());
ws.SendAsync(errorMsg, WebSocketMessageType.Binary, true, CancellationToken.None).PipeTo(Self,
failure: ex => new Tcp.ErrorClosed(ex.Message));
ws.CloseAsync(WebSocketCloseStatus.NormalClosure, "close ws", CancellationToken.None);
return;
}

base.OnWsConnected(ws, remote, local);
}

/// <summary>
/// Create disconnect message with reason
/// </summary>
/// <param name="reason">Disconnect reason</param>
private Message CreateDisconnectMessage(DisconnectReason reason)
Tommo-L marked this conversation as resolved.
Show resolved Hide resolved
{
byte[] data;
switch (reason)
{
case DisconnectReason.MaxConnectionReached:
case DisconnectReason.MaxConnectionPerAddressReached:
data = GetRandomConnectedPeers(PeersToReturnOnDisconnect).ToByteArray();
break;
default:
data = new byte[0];
break;
}
var payload = DisconnectPayload.Create(reason, data);
var message = Message.Create(MessageCommand.Disconnect, payload);
return message;
}

public static Props Props(NeoSystem system)
{
return Akka.Actor.Props.Create(() => new LocalNode(system));
Expand Down
2 changes: 2 additions & 0 deletions src/neo/Network/P2P/MessageCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ public enum MessageCommand : byte
Ping = 0x18,
[ReflectionCache(typeof(PingPayload))]
Pong = 0x19,
[ReflectionCache(typeof(DisconnectPayload))]
Disconnect = 0x1f,

//synchronization
[ReflectionCache(typeof(GetBlocksPayload))]
Expand Down
37 changes: 37 additions & 0 deletions src/neo/Network/P2P/Payloads/DisconnectPayload.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
using Neo.IO;
using System;
using System.IO;

namespace Neo.Network.P2P.Payloads
{
public class DisconnectPayload : ISerializable
{
public const int MaxDataSize = 1024;

public DisconnectReason Reason;
public byte[] Data;

public int Size => sizeof(DisconnectReason) + Data.GetVarSize();

public static DisconnectPayload Create(DisconnectReason reason, byte[] data = null)
{
return new DisconnectPayload
{
Reason = reason,
Data = data ?? Array.Empty<byte>()
};
}

public void Deserialize(BinaryReader reader)
{
Reason = (DisconnectReason)reader.ReadByte();
Data = reader.ReadVarBytes(MaxDataSize);
}

public void Serialize(BinaryWriter writer)
{
writer.Write((byte)Reason);
writer.WriteVarBytes(Data);
}
}
}
14 changes: 14 additions & 0 deletions src/neo/Network/P2P/Payloads/DisconnectReason.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
namespace Neo.Network.P2P.Payloads
{
public enum DisconnectReason : byte
{
MaxConnectionReached = 0x01,
MaxConnectionPerAddressReached = 0x02,
DuplicateNonce = 0x03,

MagicNumberIncompatible = 0x10,
FormatException = 0x11,

InternalError = 0x20,
}
}
43 changes: 13 additions & 30 deletions src/neo/Network/P2P/Peer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Neo.IO;
using Neo.Network.P2P.Payloads;
using System;
using System.Buffers.Binary;
using System.Collections.Concurrent;
Expand All @@ -14,6 +15,7 @@
using System.Net.NetworkInformation;
using System.Net.Sockets;
using System.Net.WebSockets;
using System.Threading;
using System.Threading.Tasks;

namespace Neo.Network.P2P
Expand All @@ -35,7 +37,7 @@ private class WsConnected { public WebSocket Socket; public IPEndPoint Remote; p
protected ActorSelection Connections => Context.ActorSelection("connection_*");

private static readonly HashSet<IPAddress> localAddresses = new HashSet<IPAddress>();
private readonly Dictionary<IPAddress, int> ConnectedAddresses = new Dictionary<IPAddress, int>();
protected readonly Dictionary<IPAddress, int> ConnectedAddresses = new Dictionary<IPAddress, int>();
/// <summary>
/// A dictionary that stores the connected nodes.
/// </summary>
Expand Down Expand Up @@ -92,6 +94,7 @@ protected void AddPeers(IEnumerable<IPEndPoint> peers)
protected void ConnectToPeer(IPEndPoint endPoint, bool isTrusted = false)
{
endPoint = endPoint.Unmap();

// If the address is the same, the ListenerTcpPort should be different, otherwise, return
if (endPoint.Port == ListenerTcpPort && localAddresses.Contains(endPoint.Address)) return;

Expand Down Expand Up @@ -205,28 +208,15 @@ private void OnStart(ChannelsConfig config)
/// </summary>
/// <param name="remote">The remote endpoint of TCP connection.</param>
/// <param name="local">The local endpoint of TCP connection.</param>
private void OnTcpConnected(IPEndPoint remote, IPEndPoint local)
protected virtual void OnTcpConnected(IPEndPoint remote, IPEndPoint local)
{
ImmutableInterlocked.Update(ref ConnectingPeers, p => p.Remove(remote));
erikzhang marked this conversation as resolved.
Show resolved Hide resolved
if (MaxConnections != -1 && ConnectedPeers.Count >= MaxConnections && !TrustedIpAddresses.Contains(remote.Address))
{
Sender.Tell(Tcp.Abort.Instance);
return;
}
erikzhang marked this conversation as resolved.
Show resolved Hide resolved

ConnectedAddresses.TryGetValue(remote.Address, out int count);
if (count >= MaxConnectionsPerAddress)
{
Sender.Tell(Tcp.Abort.Instance);
}
else
{
ConnectedAddresses[remote.Address] = count + 1;
IActorRef connection = Context.ActorOf(ProtocolProps(Sender, remote, local), $"connection_{Guid.NewGuid()}");
Context.Watch(connection);
Sender.Tell(new Tcp.Register(connection));
ConnectedPeers.TryAdd(connection, remote);
}
ConnectedAddresses[remote.Address] = count + 1;
IActorRef connection = Context.ActorOf(ProtocolProps(Sender, remote, local), $"connection_{Guid.NewGuid()}");
Context.Watch(connection);
Sender.Tell(new Tcp.Register(connection));
ConnectedPeers.TryAdd(connection, remote);
}

/// <summary>
Expand Down Expand Up @@ -273,18 +263,11 @@ private void OnTimer()
}
}

private void OnWsConnected(WebSocket ws, IPEndPoint remote, IPEndPoint local)
protected virtual void OnWsConnected(WebSocket ws, IPEndPoint remote, IPEndPoint local)
{
ConnectedAddresses.TryGetValue(remote.Address, out int count);
if (count >= MaxConnectionsPerAddress)
{
ws.Abort();
}
else
{
ConnectedAddresses[remote.Address] = count + 1;
Context.ActorOf(ProtocolProps(ws, remote, local), $"connection_{Guid.NewGuid()}");
}
ConnectedAddresses[remote.Address] = count + 1;
Context.ActorOf(ProtocolProps(ws, remote, local), $"connection_{Guid.NewGuid()}");
}

protected override void PostStop()
Expand Down
39 changes: 32 additions & 7 deletions src/neo/Network/P2P/ProtocolHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,12 @@ private void OnMessage(Message msg)
foreach (IP2PPlugin plugin in Plugin.P2PPlugins)
if (!plugin.OnP2PMessage(msg))
return;

if (msg.Command == MessageCommand.Disconnect)
{
OnDisconnectMessageReceived((DisconnectPayload)msg.Payload);
return;
}
if (version == null)
{
if (msg.Command != MessageCommand.Version)
Expand Down Expand Up @@ -181,13 +187,7 @@ private void OnFilterLoadMessageReceived(FilterLoadPayload payload)
/// </summary>
private void OnGetAddrMessageReceived()
{
Random rand = new Random();
IEnumerable<RemoteNode> 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.Address, p.Version.Timestamp, p.Version.Capabilities)).ToArray();
NetworkAddressWithTime[] networkAddresses = LocalNode.Singleton.GetRandomConnectedPeers(AddrPayload.MaxCountToSend);
if (networkAddresses.Length == 0) return;
Context.Parent.Tell(Message.Create(MessageCommand.Addr, AddrPayload.Create(networkAddresses)));
}
Expand Down Expand Up @@ -371,6 +371,31 @@ private void OnVersionMessageReceived(VersionPayload payload)
Context.Parent.Tell(payload);
}

/// <summary>
/// Processe received disconnect messages and close the connection
/// </summary>
/// <param name="payload">Disconnect message</param>
private void OnDisconnectMessageReceived(DisconnectPayload payload)
Tommo-L marked this conversation as resolved.
Show resolved Hide resolved
{
switch (payload.Reason)
{
case DisconnectReason.MaxConnectionReached:
case DisconnectReason.MaxConnectionPerAddressReached:
try
{
var addressList = payload.Data
.AsSerializableArray<NetworkAddressWithTime>(AddrPayload.MaxCountToSend)
.Select(p => p.EndPoint)
.Where(p => p.Port > 0);
system.LocalNode.Tell(new Peer.Peers { EndPoints = addressList });
}
catch { }
break;
default: break;
}
Context.Stop(Self);
}

private void OnTimer()
{
RefreshPendingKnownHashes();
Expand Down
Loading