Skip to content

Commit 17acdd9

Browse files
committed
hole punch improvements and fixes (fix #374, fix #366)
1 parent 89bdd30 commit 17acdd9

File tree

10 files changed

+152
-104
lines changed

10 files changed

+152
-104
lines changed

LibSample/HolePunchServerTest.cs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ void INatPunchListener.OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndP
7676
}
7777
}
7878

79-
void INatPunchListener.OnNatIntroductionSuccess(IPEndPoint targetEndPoint, string token)
79+
void INatPunchListener.OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token)
8080
{
8181
//Ignore we are server
8282
}
@@ -85,21 +85,21 @@ public void Run()
8585
{
8686
Console.WriteLine("=== HolePunch Test ===");
8787

88-
EventBasedNetListener netListener = new EventBasedNetListener();
88+
EventBasedNetListener clientListener = new EventBasedNetListener();
8989
EventBasedNatPunchListener natPunchListener1 = new EventBasedNatPunchListener();
9090
EventBasedNatPunchListener natPunchListener2 = new EventBasedNatPunchListener();
9191

92-
netListener.PeerConnectedEvent += peer =>
92+
clientListener.PeerConnectedEvent += peer =>
9393
{
94-
Console.WriteLine("PeerConnected: " + peer.EndPoint.ToString());
94+
Console.WriteLine("PeerConnected: " + peer.EndPoint);
9595
};
9696

97-
netListener.ConnectionRequestEvent += request =>
97+
clientListener.ConnectionRequestEvent += request =>
9898
{
9999
request.AcceptIfKey(ConnectionKey);
100100
};
101101

102-
netListener.PeerDisconnectedEvent += (peer, disconnectInfo) =>
102+
clientListener.PeerDisconnectedEvent += (peer, disconnectInfo) =>
103103
{
104104
Console.WriteLine("PeerDisconnected: " + disconnectInfo.Reason);
105105
if (disconnectInfo.AdditionalData.AvailableBytes > 0)
@@ -108,35 +108,35 @@ public void Run()
108108
}
109109
};
110110

111-
natPunchListener1.NatIntroductionSuccess += (point, token) =>
111+
natPunchListener1.NatIntroductionSuccess += (point, addrType, token) =>
112112
{
113113
var peer = _c1.Connect(point, ConnectionKey);
114-
Console.WriteLine("Success C1. Connecting to C2: {0}, connection created: {1}", point, peer != null);
114+
Console.WriteLine($"NatIntroductionSuccess C1. Connecting to C2: {point}, type: {addrType}, connection created: {peer != null}");
115115
};
116116

117-
natPunchListener2.NatIntroductionSuccess += (point, token) =>
117+
natPunchListener2.NatIntroductionSuccess += (point, addrType, token) =>
118118
{
119119
var peer = _c2.Connect(point, ConnectionKey);
120-
Console.WriteLine("Success C2. Connecting to C1: {0}, connection created: {1}", point, peer != null);
120+
Console.WriteLine($"NatIntroductionSuccess C2. Connecting to C1: {point}, type: {addrType}, connection created: {peer != null}");
121121
};
122122

123-
_c1 = new NetManager(netListener)
123+
_c1 = new NetManager(clientListener)
124124
{
125125
IPv6Enabled = false,
126126
NatPunchEnabled = true
127127
};
128128
_c1.NatPunchModule.Init(natPunchListener1);
129129
_c1.Start();
130130

131-
_c2 = new NetManager(netListener)
131+
_c2 = new NetManager(clientListener)
132132
{
133133
IPv6Enabled = false,
134134
NatPunchEnabled = true
135135
};
136136
_c2.NatPunchModule.Init(natPunchListener2);
137137
_c2.Start();
138138

139-
_puncher = new NetManager(netListener)
139+
_puncher = new NetManager(clientListener)
140140
{
141141
IPv6Enabled = false,
142142
NatPunchEnabled = true

LiteNetLib.Tests/CommunicationTest.cs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,26 @@ public void ConnectionByIpV4()
5959
Assert.AreEqual(1, client.ConnectedPeersCount);
6060
}
6161

62+
[Test, Timeout(TestTimeout)]
63+
public void P2PConnect()
64+
{
65+
var client1 = ManagerStack.Client(1);
66+
var client2 = ManagerStack.Client(2);
67+
68+
client1.Connect("127.0.0.1", client2.LocalPort, DefaultAppKey);
69+
client2.Connect("127.0.0.1", client1.LocalPort, DefaultAppKey);
70+
71+
while (client1.ConnectedPeersCount != 1 || client2.ConnectedPeersCount != 1)
72+
{
73+
Thread.Sleep(15);
74+
client1.PollEvents();
75+
client2.PollEvents();
76+
}
77+
78+
Assert.AreEqual(1, client1.ConnectedPeersCount);
79+
Assert.AreEqual(1, client2.ConnectedPeersCount);
80+
}
81+
6282
[Test, Timeout(TestTimeout)]
6383
public void ConnectionByIpV4Unsynced()
6484
{

LiteNetLib/ConnectionRequest.cs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,6 @@
44

55
namespace LiteNetLib
66
{
7-
public enum ConnectionRequestType
8-
{
9-
Incoming,
10-
PeerToPeer
11-
}
12-
137
internal enum ConnectionRequestResult
148
{
159
None,
@@ -24,7 +18,6 @@ public class ConnectionRequest
2418
private int _used;
2519

2620
public readonly NetDataReader Data;
27-
public ConnectionRequestType Type { get; private set; }
2821

2922
internal ConnectionRequestResult Result { get; private set; }
3023
internal long ConnectionTime;
@@ -48,14 +41,12 @@ internal void UpdateRequest(NetConnectRequestPacket connRequest)
4841
internal ConnectionRequest(
4942
long connectionId,
5043
byte connectionNumber,
51-
ConnectionRequestType type,
5244
NetDataReader netDataReader,
5345
IPEndPoint endPoint,
5446
NetManager listener)
5547
{
5648
ConnectionTime = connectionId;
5749
ConnectionNumber = connectionNumber;
58-
Type = type;
5950
RemoteEndPoint = endPoint;
6051
Data = netDataReader;
6152
_listener = listener;

LiteNetLib/INetEventListener.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ public enum DisconnectReason
2626
ConnectionRejected,
2727
InvalidProtocol,
2828
UnknownHost,
29-
Reconnect
29+
Reconnect,
30+
PeerToPeerConnection
3031
}
3132

3233
/// <summary>

LiteNetLib/NatPunchModule.cs

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,22 @@
55

66
namespace LiteNetLib
77
{
8+
public enum NatAddressType
9+
{
10+
Internal,
11+
External
12+
}
13+
814
public interface INatPunchListener
915
{
1016
void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token);
11-
void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, string token);
17+
void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token);
1218
}
1319

1420
public class EventBasedNatPunchListener : INatPunchListener
1521
{
1622
public delegate void OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndPoint remoteEndPoint, string token);
17-
public delegate void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, string token);
23+
public delegate void OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token);
1824

1925
public event OnNatIntroductionRequest NatIntroductionRequest;
2026
public event OnNatIntroductionSuccess NatIntroductionSuccess;
@@ -25,10 +31,10 @@ void INatPunchListener.OnNatIntroductionRequest(IPEndPoint localEndPoint, IPEndP
2531
NatIntroductionRequest(localEndPoint, remoteEndPoint, token);
2632
}
2733

28-
void INatPunchListener.OnNatIntroductionSuccess(IPEndPoint targetEndPoint, string token)
34+
void INatPunchListener.OnNatIntroductionSuccess(IPEndPoint targetEndPoint, NatAddressType type, string token)
2935
{
3036
if (NatIntroductionSuccess != null)
31-
NatIntroductionSuccess(targetEndPoint, token);
37+
NatIntroductionSuccess(targetEndPoint, type, token);
3238
}
3339
}
3440

@@ -47,6 +53,7 @@ struct RequestEventData
4753
struct SuccessEventData
4854
{
4955
public IPEndPoint TargetEndPoint;
56+
public NatAddressType Type;
5057
public string Token;
5158
}
5259

@@ -66,6 +73,7 @@ class NatIntroduceResponsePacket
6673
class NatPunchPacket
6774
{
6875
public string Token { get; set; }
76+
public bool IsExternal { get; set; }
6977
}
7078

7179
private readonly NetSocket _socket;
@@ -87,8 +95,11 @@ internal NatPunchModule(NetSocket socket)
8795

8896
internal void ProcessMessage(IPEndPoint senderEndPoint, NetPacket packet)
8997
{
90-
_cacheReader.SetSource(packet.RawData, NetConstants.HeaderSize, packet.Size);
91-
_netPacketProcessor.ReadAllPackets(_cacheReader, senderEndPoint);
98+
lock (_cacheReader)
99+
{
100+
_cacheReader.SetSource(packet.RawData, NetConstants.HeaderSize, packet.Size);
101+
_netPacketProcessor.ReadAllPackets(_cacheReader, senderEndPoint);
102+
}
92103
}
93104

94105
public void Init(INatPunchListener listener)
@@ -137,7 +148,10 @@ public void PollEvents()
137148
while (_successEvents.Count > 0)
138149
{
139150
var evt = _successEvents.Dequeue();
140-
_natPunchListener.OnNatIntroductionSuccess(evt.TargetEndPoint, evt.Token);
151+
_natPunchListener.OnNatIntroductionSuccess(
152+
evt.TargetEndPoint,
153+
evt.Type,
154+
evt.Token);
141155
}
142156
}
143157
lock (_requestEvents)
@@ -204,6 +218,7 @@ private void OnNatIntroductionResponse(NatIntroduceResponsePacket req)
204218

205219
// send external punch
206220
_socket.Ttl = NetConstants.SocketTTL;
221+
punchPacket.IsExternal = true;
207222
Send(punchPacket, req.External);
208223
NetDebug.Write(NetLogLevel.Trace, "[NAT] external punch sent to " + req.External);
209224
}
@@ -219,7 +234,11 @@ private void OnNatPunch(NatPunchPacket req, IPEndPoint senderEndPoint)
219234
lock (_successEvents)
220235
{
221236
_successEvents.Enqueue(new SuccessEventData
222-
{ TargetEndPoint = senderEndPoint, Token = req.Token });
237+
{
238+
TargetEndPoint = senderEndPoint,
239+
Type = req.IsExternal ? NatAddressType.External : NatAddressType.Internal,
240+
Token = req.Token
241+
});
223242
}
224243
}
225244
}

LiteNetLib/NetManager.cs

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -828,27 +828,19 @@ private void ProcessConnectRequest(
828828
RemovePeer(netPeer);
829829
//go to new connection
830830
break;
831-
case ConnectRequestResult.P2PConnection:
832-
lock (_requestsDict)
833-
{
834-
req = new ConnectionRequest(
835-
netPeer.ConnectTime,
836-
connectionNumber,
837-
ConnectionRequestType.PeerToPeer,
838-
connRequest.Data,
839-
remoteEndPoint,
840-
this);
841-
_requestsDict.Add(remoteEndPoint, req);
842-
}
843-
CreateEvent(NetEvent.EType.ConnectionRequest, connectionRequest: req);
844-
return;
831+
case ConnectRequestResult.P2PLose:
832+
DisconnectPeerForce(netPeer, DisconnectReason.PeerToPeerConnection, 0, null);
833+
RemovePeer(netPeer);
834+
//go to new connection
835+
break;
845836
default:
846837
//no operations needed
847838
return;
848839
}
849840
//ConnectRequestResult.NewConnection
850841
//Set next connection number
851-
connectionNumber = (byte)((netPeer.ConnectionNum + 1) % NetConstants.MaxConnectionNumber);
842+
if(processResult != ConnectRequestResult.P2PLose)
843+
connectionNumber = (byte)((netPeer.ConnectionNum + 1) % NetConstants.MaxConnectionNumber);
852844
//To reconnect peer
853845
}
854846
else
@@ -866,7 +858,6 @@ private void ProcessConnectRequest(
866858
req = new ConnectionRequest(
867859
connRequest.ConnectionTime,
868860
connectionNumber,
869-
ConnectionRequestType.Incoming,
870861
connRequest.Data,
871862
remoteEndPoint,
872863
this);
@@ -904,20 +895,39 @@ private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEnd
904895
return;
905896
}
906897

907-
//special case connect request
908-
if (packet.Property == PacketProperty.ConnectRequest &&
909-
NetConnectRequestPacket.GetProtocolId(packet) != NetConstants.ProtocolId)
898+
switch (packet.Property)
910899
{
911-
SendRawAndRecycle(NetPacketPool.GetWithProperty(PacketProperty.InvalidProtocol), remoteEndPoint);
912-
return;
900+
//special case connect request
901+
case PacketProperty.ConnectRequest:
902+
if (NetConnectRequestPacket.GetProtocolId(packet) != NetConstants.ProtocolId)
903+
{
904+
SendRawAndRecycle(NetPacketPool.GetWithProperty(PacketProperty.InvalidProtocol), remoteEndPoint);
905+
return;
906+
}
907+
break;
908+
//unconnected messages
909+
case PacketProperty.Broadcast:
910+
if (!BroadcastReceiveEnabled)
911+
return;
912+
CreateEvent(NetEvent.EType.Broadcast, remoteEndPoint: remoteEndPoint, readerSource: packet);
913+
return;
914+
case PacketProperty.UnconnectedMessage:
915+
if (!UnconnectedMessagesEnabled)
916+
return;
917+
CreateEvent(NetEvent.EType.ReceiveUnconnected, remoteEndPoint: remoteEndPoint, readerSource: packet);
918+
return;
919+
case PacketProperty.NatMessage:
920+
if (NatPunchEnabled)
921+
NatPunchModule.ProcessMessage(remoteEndPoint, packet);
922+
return;
913923
}
914924

925+
//Check normal packets
915926
NetPeer netPeer;
916927
_peersLock.EnterReadLock();
917928
bool peerFound = _peersDict.TryGetValue(remoteEndPoint, out netPeer);
918929
_peersLock.ExitReadLock();
919-
920-
//Check normal packets
930+
921931
switch (packet.Property)
922932
{
923933
case PacketProperty.ConnectRequest:
@@ -953,22 +963,6 @@ private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEnd
953963
SendRawAndRecycle(packet, remoteEndPoint);
954964
}
955965
break;
956-
case PacketProperty.Broadcast:
957-
if (!BroadcastReceiveEnabled)
958-
break;
959-
CreateEvent(NetEvent.EType.Broadcast, remoteEndPoint: remoteEndPoint, readerSource: packet);
960-
break;
961-
962-
case PacketProperty.UnconnectedMessage:
963-
if (!UnconnectedMessagesEnabled)
964-
break;
965-
CreateEvent(NetEvent.EType.ReceiveUnconnected, remoteEndPoint: remoteEndPoint, readerSource: packet);
966-
break;
967-
968-
case PacketProperty.NatMessage:
969-
if (NatPunchEnabled)
970-
NatPunchModule.ProcessMessage(remoteEndPoint, packet);
971-
break;
972966
case PacketProperty.InvalidProtocol:
973967
if (peerFound && netPeer.ConnectionState == ConnectionState.Outgoing)
974968
DisconnectPeerForce(netPeer, DisconnectReason.InvalidProtocol, 0, null);
@@ -996,10 +990,11 @@ private void DataReceived(byte[] reusableBuffer, int count, IPEndPoint remoteEnd
996990
//Send shutdown
997991
SendRawAndRecycle(NetPacketPool.GetWithProperty(PacketProperty.ShutdownOk), remoteEndPoint);
998992
break;
999-
1000993
case PacketProperty.ConnectAccept:
994+
if (!peerFound)
995+
return;
1001996
var connAccept = NetConnectAcceptPacket.FromData(packet);
1002-
if (connAccept != null && peerFound && netPeer.ProcessConnectAccept(connAccept))
997+
if (connAccept != null && netPeer.ProcessConnectAccept(connAccept))
1003998
CreateEvent(NetEvent.EType.Connect, netPeer);
1004999
break;
10051000
default:

0 commit comments

Comments
 (0)