You've already forked lidgren-network-gen3
mirror of
https://github.com/lidgren/lidgren-network-gen3.git
synced 2026-05-17 07:36:32 +09:00
IPv6: Space Wizard Edition.
This PR fixes the IPv6 support *properly*. The two previous PRs, #123 and #126, both made a mess out of it: PR #123 implemented IPv6 by breaking non-dualstack IPv4 support. PR #126 fixed IPv4 support by breaking non-dualstack IPv6 support. This change fixes the mess entirely. IPv4, IPv6 and IPv6-dual-stack are now all independently supported and work as expected. Namely IPv4 can't receive IPv6, IPv6 can only receive IPv4 if NetPeerConfiguration.DualStack is set. You can still have an IPv6-only socket. I'll leave some review comments on the PR for less-immediately obvious changes.
This commit is contained in:
@@ -132,14 +132,19 @@ namespace Lidgren.Network
|
|||||||
m_socket.SendBufferSize = m_configuration.SendBufferSize;
|
m_socket.SendBufferSize = m_configuration.SendBufferSize;
|
||||||
m_socket.Blocking = false;
|
m_socket.Blocking = false;
|
||||||
|
|
||||||
if(m_configuration.DualStack && m_configuration.LocalAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
if (m_configuration.DualStack)
|
||||||
m_socket.DualMode = true;
|
{
|
||||||
|
if (m_configuration.LocalAddress.AddressFamily != AddressFamily.InterNetworkV6)
|
||||||
|
{
|
||||||
|
LogWarning("Configuration specifies Dual Stack but does not use IPv6 local address; Dual stack will not work.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_socket.DualMode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var localAddress = m_configuration.DualStack
|
var ep = (EndPoint)new NetEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port);
|
||||||
? m_configuration.LocalAddress.MapToIPv6()
|
|
||||||
: m_configuration.LocalAddress;
|
|
||||||
|
|
||||||
var ep = (EndPoint)new NetEndPoint(localAddress, reBind ? m_listenPort : m_configuration.Port);
|
|
||||||
m_socket.Bind(ep);
|
m_socket.Bind(ep);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Net.Sockets;
|
||||||
#if !__NOIPENDPOINT__
|
#if !__NOIPENDPOINT__
|
||||||
using NetEndPoint = System.Net.IPEndPoint;
|
using NetEndPoint = System.Net.IPEndPoint;
|
||||||
#endif
|
#endif
|
||||||
@@ -32,8 +32,8 @@ namespace Lidgren.Network
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Signalling event which can be waited on to determine when a message is queued for reading.
|
/// Signalling event which can be waited on to determine when a message is queued for reading.
|
||||||
/// Note that there is no guarantee that after the event is signaled the blocked thread will
|
/// Note that there is no guarantee that after the event is signaled the blocked thread will
|
||||||
/// find the message in the queue. Other user created threads could be preempted and dequeue
|
/// find the message in the queue. Other user created threads could be preempted and dequeue
|
||||||
/// the message before the waiting thread wakes up.
|
/// the message before the waiting thread wakes up.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public AutoResetEvent MessageReceivedEvent
|
public AutoResetEvent MessageReceivedEvent
|
||||||
@@ -121,10 +121,16 @@ namespace Lidgren.Network
|
|||||||
m_connections = new List<NetConnection>();
|
m_connections = new List<NetConnection>();
|
||||||
m_connectionLookup = new Dictionary<NetEndPoint, NetConnection>();
|
m_connectionLookup = new Dictionary<NetEndPoint, NetConnection>();
|
||||||
m_handshakes = new Dictionary<NetEndPoint, NetConnection>();
|
m_handshakes = new Dictionary<NetEndPoint, NetConnection>();
|
||||||
var address = config.DualStack ? IPAddress.IPv6Any : IPAddress.Any;
|
if (m_configuration.LocalAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
m_senderRemote = (EndPoint)new NetEndPoint(address, 0);
|
{
|
||||||
|
m_senderRemote = (EndPoint)new IPEndPoint(IPAddress.IPv6Any, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_senderRemote = (EndPoint)new IPEndPoint(IPAddress.Any, 0);
|
||||||
|
}
|
||||||
m_status = NetPeerStatus.NotRunning;
|
m_status = NetPeerStatus.NotRunning;
|
||||||
m_receivedFragmentGroups = new Dictionary<NetConnection, Dictionary<int, ReceivedFragmentGroup>>();
|
m_receivedFragmentGroups = new Dictionary<NetConnection, Dictionary<int, ReceivedFragmentGroup>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -149,7 +155,7 @@ namespace Lidgren.Network
|
|||||||
}
|
}
|
||||||
|
|
||||||
InitializeNetwork();
|
InitializeNetwork();
|
||||||
|
|
||||||
// start network thread
|
// start network thread
|
||||||
m_networkThread = new Thread(new ThreadStart(NetworkLoop));
|
m_networkThread = new Thread(new ThreadStart(NetworkLoop));
|
||||||
m_networkThread.Name = m_configuration.NetworkThreadName;
|
m_networkThread.Name = m_configuration.NetworkThreadName;
|
||||||
@@ -184,7 +190,7 @@ namespace Lidgren.Network
|
|||||||
public NetIncomingMessage WaitMessage(int maxMillis)
|
public NetIncomingMessage WaitMessage(int maxMillis)
|
||||||
{
|
{
|
||||||
NetIncomingMessage msg = ReadMessage();
|
NetIncomingMessage msg = ReadMessage();
|
||||||
|
|
||||||
while (msg == null)
|
while (msg == null)
|
||||||
{
|
{
|
||||||
// This could return true...
|
// This could return true...
|
||||||
@@ -192,11 +198,11 @@ namespace Lidgren.Network
|
|||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ... while this will still returns null. That's why we need to cycle.
|
// ... while this will still returns null. That's why we need to cycle.
|
||||||
msg = ReadMessage();
|
msg = ReadMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
return msg;
|
return msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,7 +222,7 @@ namespace Lidgren.Network
|
|||||||
}
|
}
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads a pending message from any connection, if any.
|
/// Reads a pending message from any connection, if any.
|
||||||
/// Returns true if message was read, otherwise false.
|
/// Returns true if message was read, otherwise false.
|
||||||
|
|||||||
@@ -35,12 +35,12 @@ namespace Lidgren.Network
|
|||||||
// -4 bytes to be on the safe side and align to 8-byte boundary
|
// -4 bytes to be on the safe side and align to 8-byte boundary
|
||||||
// Total 1408 bytes
|
// Total 1408 bytes
|
||||||
// Note that lidgren headers (5 bytes) are not included here; since it's part of the "mtu payload"
|
// Note that lidgren headers (5 bytes) are not included here; since it's part of the "mtu payload"
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default MTU value in bytes
|
/// Default MTU value in bytes
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public const int kDefaultMTU = 1408;
|
public const int kDefaultMTU = 1408;
|
||||||
|
|
||||||
private const string c_isLockedMessage = "You may not modify the NetPeerConfiguration after it has been used to initialize a NetPeer";
|
private const string c_isLockedMessage = "You may not modify the NetPeerConfiguration after it has been used to initialize a NetPeer";
|
||||||
|
|
||||||
private bool m_isLocked;
|
private bool m_isLocked;
|
||||||
@@ -344,23 +344,21 @@ namespace Lidgren.Network
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether the library should use IPv6 dual stack mode
|
/// Gets or sets a value indicating whether the library should use IPv6 dual stack mode.
|
||||||
|
/// If you enable this you should make sure that the <see cref="LocalAddress"/> is an IPv6 address.
|
||||||
|
/// Cannot be changed once NetPeer is initialized.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DualStack
|
public bool DualStack
|
||||||
{
|
{
|
||||||
get { return m_dualStack; }
|
get { return m_dualStack; }
|
||||||
set
|
set
|
||||||
{
|
{
|
||||||
if (m_isLocked)
|
if (m_isLocked)
|
||||||
throw new NetException(c_isLockedMessage);
|
throw new NetException(c_isLockedMessage);
|
||||||
m_dualStack = value;
|
m_dualStack = value;
|
||||||
if (m_dualStack && m_localAddress.Equals(IPAddress.Any))
|
}
|
||||||
m_localAddress = IPAddress.IPv6Any;
|
|
||||||
if (!m_dualStack && m_localAddress.Equals(IPAddress.IPv6Any))
|
|
||||||
m_localAddress = IPAddress.Any;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the local broadcast address to use when broadcasting
|
/// Gets or sets the local broadcast address to use when broadcasting
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ namespace Lidgren.Network
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname
|
/// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static NetAddress Resolve(string ipOrHost)
|
public static NetAddress Resolve(string ipOrHost)
|
||||||
@@ -240,7 +240,7 @@ namespace Lidgren.Network
|
|||||||
}
|
}
|
||||||
return new string(c);
|
return new string(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Returns true if the endpoint supplied is on the same subnet as this host
|
/// Returns true if the endpoint supplied is on the same subnet as this host
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -471,23 +471,23 @@ namespace Lidgren.Network
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="src">Source.</param>
|
/// <param name="src">Source.</param>
|
||||||
/// <param name="dst">Destination.</param>
|
/// <param name="dst">Destination.</param>
|
||||||
internal static void CopyEndpoint(IPEndPoint src, IPEndPoint dst)
|
internal static void CopyEndpoint(IPEndPoint src, IPEndPoint dst)
|
||||||
{
|
{
|
||||||
dst.Port = src.Port;
|
dst.Port = src.Port;
|
||||||
if (src.AddressFamily == AddressFamily.InterNetwork)
|
if (src.AddressFamily == AddressFamily.InterNetwork)
|
||||||
dst.Address = src.Address.MapToIPv6();
|
dst.Address = src.Address.MapToIPv6();
|
||||||
else
|
else
|
||||||
dst.Address = src.Address;
|
dst.Address = src.Address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Maps the IPEndPoint object to an IPv6 address. Has allocation
|
/// Maps the IPEndPoint object to an IPv6 address. Has allocation
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static IPEndPoint MapToIPv6(IPEndPoint endPoint)
|
internal static IPEndPoint MapToIPv6(IPEndPoint endPoint)
|
||||||
{
|
{
|
||||||
if (endPoint.AddressFamily == AddressFamily.InterNetwork)
|
if (endPoint.AddressFamily == AddressFamily.InterNetwork)
|
||||||
return new IPEndPoint(endPoint.Address.MapToIPv6(), endPoint.Port);
|
return new IPEndPoint(endPoint.Address.MapToIPv6(), endPoint.Port);
|
||||||
return endPoint;
|
return endPoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user