1
0
mirror of https://github.com/lidgren/lidgren-network-gen3.git synced 2026-05-17 23:56:30 +09:00

Added improved NAT punch.

Clients that request an introduction now first request a confirmation from
the server to make sure unconnected messages can be sent in both
directions before attempting to make a connection. Similarly the server
automatically sends a confirmation to the client to reduce the possiblity
that either one of the endpoints has issues with sending messages to the
other.
This commit is contained in:
Frank Versnel
2016-02-15 16:36:12 +01:00
parent c8e2b011e0
commit 27b3d8e386
3 changed files with 70 additions and 21 deletions

View File

@@ -169,6 +169,8 @@ namespace Lidgren.Network
DiscoveryResponse = 137, DiscoveryResponse = 137,
NatPunchMessage = 138, // send between peers NatPunchMessage = 138, // send between peers
NatIntroduction = 139, // send to master server NatIntroduction = 139, // send to master server
NatIntroductionConfirmRequest = 142,
NatIntroductionConfirmed = 143,
ExpandMTURequest = 140, ExpandMTURequest = 140,
ExpandMTUSuccess = 141, ExpandMTUSuccess = 141,
} }

View File

@@ -9,8 +9,10 @@ using NetEndPoint = System.Net.IPEndPoint;
namespace Lidgren.Network namespace Lidgren.Network
{ {
public partial class NetPeer public partial class NetPeer {
{ private const byte HostByte = 1;
private const byte ClientByte = 0;
/// <summary> /// <summary>
/// Send NetIntroduction to hostExternal and clientExternal; introducing client to host /// Send NetIntroduction to hostExternal and clientExternal; introducing client to host
/// </summary> /// </summary>
@@ -92,16 +94,61 @@ namespace Lidgren.Network
{ {
NetIncomingMessage tmp = SetupReadHelperMessage(ptr, 1000); // never mind length NetIncomingMessage tmp = SetupReadHelperMessage(ptr, 1000); // never mind length
byte fromHostByte = tmp.ReadByte(); var isFromClient = tmp.ReadByte() == ClientByte;
if (fromHostByte == 0) string token = tmp.ReadString();
if (isFromClient)
{ {
// it's from client LogDebug("NAT punch received from " + senderEndPoint + " we're host, so we send a NatIntroductionConfirmed message - token is " + token);
LogDebug("NAT punch received from " + senderEndPoint + " we're host, so we ignore this");
return; // don't alert hosts about nat punch successes; only clients 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<NetEndPoint, NetOutgoingMessage>(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<NetEndPoint, NetOutgoingMessage>(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(); 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<NetEndPoint, NetOutgoingMessage>(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 // 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.m_senderEndPoint = senderEndPoint;
punchSuccess.Write(token); punchSuccess.Write(token);
ReleaseMessage(punchSuccess); 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<NetEndPoint, NetOutgoingMessage>(senderEndPoint, punch));
} }
} }
} }

View File

@@ -629,6 +629,14 @@ namespace Lidgren.Network
if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess)) if (m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.NatIntroductionSuccess))
HandleNatPunch(ptr, senderEndPoint); HandleNatPunch(ptr, senderEndPoint);
return; 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: case NetMessageType.ConnectResponse:
lock (m_handshakes) lock (m_handshakes)