diff --git a/Lidgren.Network/NetMessageType.cs b/Lidgren.Network/NetMessageType.cs
index a14e99c..8dd53de 100644
--- a/Lidgren.Network/NetMessageType.cs
+++ b/Lidgren.Network/NetMessageType.cs
@@ -169,7 +169,9 @@ namespace Lidgren.Network
DiscoveryResponse = 137,
NatPunchMessage = 138, // send between peers
NatIntroduction = 139, // send to master server
+ NatIntroductionConfirmRequest = 142,
+ NatIntroductionConfirmed = 143,
ExpandMTURequest = 140,
ExpandMTUSuccess = 141,
}
-}
\ No newline at end of file
+}
diff --git a/Lidgren.Network/NetNatIntroduction.cs b/Lidgren.Network/NetNatIntroduction.cs
index d134e14..1df7e42 100644
--- a/Lidgren.Network/NetNatIntroduction.cs
+++ b/Lidgren.Network/NetNatIntroduction.cs
@@ -9,8 +9,10 @@ using NetEndPoint = System.Net.IPEndPoint;
namespace Lidgren.Network
{
- public partial class NetPeer
- {
+ public partial class NetPeer {
+ private const byte HostByte = 1;
+ private const byte ClientByte = 0;
+
///
/// Send NetIntroduction to hostExternal and clientExternal; introducing client to host
///
@@ -92,16 +94,61 @@ namespace Lidgren.Network
{
NetIncomingMessage tmp = SetupReadHelperMessage(ptr, 1000); // never mind length
- byte fromHostByte = tmp.ReadByte();
- if (fromHostByte == 0)
+ var isFromClient = tmp.ReadByte() == ClientByte;
+ string token = tmp.ReadString();
+ if (isFromClient)
{
- // it's from client
- LogDebug("NAT punch received from " + senderEndPoint + " we're host, so we ignore this");
- return; // don't alert hosts about nat punch successes; only clients
+ LogDebug("NAT punch received from " + senderEndPoint + " we're host, so we send a NatIntroductionConfirmed message - token is " + token);
+
+ var confirmResponse = CreateMessage(1);
+ confirmResponse.m_messageType = NetMessageType.NatIntroductionConfirmed;
+ confirmResponse.Write(HostByte);
+ confirmResponse.Write(token);
+ Interlocked.Increment(ref confirmResponse.m_recyclingCount);
+ m_unsentUnconnectedMessages.Enqueue(new NetTuple(senderEndPoint, confirmResponse));
}
+ else
+ {
+ LogDebug("NAT punch received from " + senderEndPoint + " we're client, so we send a NatIntroductionConfirmRequest - token is " + token);
+
+ var confirmRequest = CreateMessage(1);
+ confirmRequest.m_messageType = NetMessageType.NatIntroductionConfirmRequest;
+ confirmRequest.Write(ClientByte);
+ confirmRequest.Write(token);
+ Interlocked.Increment(ref confirmRequest.m_recyclingCount);
+ m_unsentUnconnectedMessages.Enqueue(new NetTuple(senderEndPoint, confirmRequest));
+ }
+ }
+
+ private void HandleNatPunchConfirmRequest(int ptr, NetEndPoint senderEndPoint)
+ {
+ NetIncomingMessage tmp = SetupReadHelperMessage(ptr, 1000); // never mind length
+ var isFromClient = tmp.ReadByte() == ClientByte;
string token = tmp.ReadString();
- LogDebug("NAT punch received from " + senderEndPoint + " we're client, so we've succeeded - token is " + token);
+ LogDebug("Received NAT punch confirmation from " + senderEndPoint + " sending NatIntroductionConfirmed - token is " + token);
+
+ var confirmResponse = CreateMessage(1);
+ confirmResponse.m_messageType = NetMessageType.NatIntroductionConfirmed;
+ confirmResponse.Write(isFromClient ? HostByte : ClientByte);
+ confirmResponse.Write(token);
+ Interlocked.Increment(ref confirmResponse.m_recyclingCount);
+ m_unsentUnconnectedMessages.Enqueue(new NetTuple(senderEndPoint, confirmResponse));
+ }
+
+ private void HandleNatPunchConfirmed(int ptr, NetEndPoint senderEndPoint)
+ {
+ NetIncomingMessage tmp = SetupReadHelperMessage(ptr, 1000); // never mind length
+ var isFromClient = tmp.ReadByte() == ClientByte;
+ if (isFromClient)
+ {
+ LogDebug("NAT punch confirmation received from " + senderEndPoint + " we're host, so we ignore this");
+ return;
+ }
+
+ string token = tmp.ReadString();
+
+ LogDebug("NAT punch confirmation received from " + senderEndPoint + " we're client so we go ahead and succeed the introduction");
//
// Release punch success to client; enabling him to Connect() to msg.Sender if token is ok
@@ -110,14 +157,6 @@ namespace Lidgren.Network
punchSuccess.m_senderEndPoint = senderEndPoint;
punchSuccess.Write(token);
ReleaseMessage(punchSuccess);
-
- // send a return punch just for good measure
- var punch = CreateMessage(1);
- punch.m_messageType = NetMessageType.NatPunchMessage;
- punch.Write((byte)0);
- punch.Write(token);
- Interlocked.Increment(ref punch.m_recyclingCount);
- m_unsentUnconnectedMessages.Enqueue(new NetTuple(senderEndPoint, punch));
- }
+ }
}
}
diff --git a/Lidgren.Network/NetPeer.Internal.cs b/Lidgren.Network/NetPeer.Internal.cs
index d6b0e01..303059e 100644
--- a/Lidgren.Network/NetPeer.Internal.cs
+++ b/Lidgren.Network/NetPeer.Internal.cs
@@ -120,7 +120,7 @@ namespace Lidgren.Network
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
if (reBind)
- m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1);
+ m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1);
m_socket.ReceiveBufferSize = m_configuration.ReceiveBufferSize;
m_socket.SendBufferSize = m_configuration.SendBufferSize;
@@ -244,7 +244,7 @@ namespace Lidgren.Network
Heartbeat();
NetUtility.Sleep(10);
-
+
lock (m_initializeLock)
{
try
@@ -412,7 +412,7 @@ namespace Lidgren.Network
switch (sx.SocketErrorCode)
{
case SocketError.ConnectionReset:
- // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
+ // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable"
// we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?!
// So, what to do?
LogWarning("ConnectionReset");
@@ -629,6 +629,14 @@ namespace Lidgren.Network
if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
HandleNatPunch(ptr, senderEndPoint);
return;
+ case NetMessageType.NatIntroductionConfirmRequest:
+ if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
+ HandleNatPunchConfirmRequest(ptr, senderEndPoint);
+ return;
+ case NetMessageType.NatIntroductionConfirmed:
+ if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
+ HandleNatPunchConfirmed(ptr, senderEndPoint);
+ return;
case NetMessageType.ConnectResponse:
lock (m_handshakes)