b1525 - Added IPv6 support
This commit is contained in:
parent
256e2370a3
commit
fdd4c7bac7
8 changed files with 275 additions and 197 deletions
|
@ -70,7 +70,8 @@ namespace SRMultiplayer
|
||||||
!assembly.GetName().Name.Contains("Logger") && !assembly.GetName().Name.Contains("Mono.") && !assembly.GetName().Name.Contains("Harmony") &&
|
!assembly.GetName().Name.Contains("Logger") && !assembly.GetName().Name.Contains("Mono.") && !assembly.GetName().Name.Contains("Harmony") &&
|
||||||
!assembly.GetName().Name.Equals("SRML") && !assembly.GetName().Name.Equals("SRML.Editor") && !assembly.GetName().Name.Equals("Newtonsoft.Json") &&
|
!assembly.GetName().Name.Equals("SRML") && !assembly.GetName().Name.Equals("SRML.Editor") && !assembly.GetName().Name.Equals("Newtonsoft.Json") &&
|
||||||
!assembly.GetName().Name.Equals("INIFileParser") && !assembly.GetName().Name.Equals("SRMultiplayer") && !assembly.GetName().Name.Contains("Microsoft.") &&
|
!assembly.GetName().Name.Equals("INIFileParser") && !assembly.GetName().Name.Equals("SRMultiplayer") && !assembly.GetName().Name.Contains("Microsoft.") &&
|
||||||
!assembly.GetName().Name.Equals("SRMP") && !assembly.GetName().Name.Equals("XGamingRuntime") && !Globals.UserData.IgnoredMods.Contains(assembly.GetName().Name))
|
!assembly.GetName().Name.Equals("SRMP") && !assembly.GetName().Name.Equals("XGamingRuntime") && !assembly.GetName().Name.Contains("MonoMod.Utils.")
|
||||||
|
&& !Globals.UserData.IgnoredMods.Contains(assembly.GetName().Name))
|
||||||
{
|
{
|
||||||
mods.Add(assembly.GetName().Name);
|
mods.Add(assembly.GetName().Name);
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,7 +123,7 @@ namespace Lidgren.Network
|
||||||
mutex.WaitOne();
|
mutex.WaitOne();
|
||||||
|
|
||||||
if (m_socket == null)
|
if (m_socket == null)
|
||||||
m_socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
|
m_socket = new Socket(m_configuration.LocalAddress.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
|
||||||
|
|
||||||
if (reBind)
|
if (reBind)
|
||||||
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1);
|
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, (int)1);
|
||||||
|
@ -132,7 +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;
|
||||||
|
|
||||||
var ep = (EndPoint)new NetEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port);
|
if (m_configuration.DualStack)
|
||||||
|
{
|
||||||
|
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 ep = (EndPoint)new NetEndPoint(m_configuration.LocalAddress, reBind ? m_listenPort : m_configuration.Port);
|
||||||
m_socket.Bind(ep);
|
m_socket.Bind(ep);
|
||||||
|
|
||||||
try
|
try
|
||||||
|
@ -412,172 +424,175 @@ namespace Lidgren.Network
|
||||||
// update now
|
// update now
|
||||||
now = NetTime.Now;
|
now = NetTime.Now;
|
||||||
|
|
||||||
do
|
try
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
ReceiveSocketData(now);
|
||||||
|
} while (m_socket.Available > 0);
|
||||||
|
}
|
||||||
|
catch (SocketException sx)
|
||||||
|
{
|
||||||
|
switch (sx.SocketErrorCode)
|
||||||
|
{
|
||||||
|
case SocketError.ConnectionReset:
|
||||||
|
// 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");
|
||||||
|
return;
|
||||||
|
|
||||||
|
case SocketError.NotConnected:
|
||||||
|
// socket is unbound; try to rebind it (happens on mobile when process goes to sleep)
|
||||||
|
BindSocket(true);
|
||||||
|
return;
|
||||||
|
|
||||||
|
default:
|
||||||
|
LogWarning("Socket exception: " + sx.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ReceiveSocketData(double now)
|
||||||
|
{
|
||||||
|
int bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote);
|
||||||
|
|
||||||
|
if (bytesReceived < NetConstants.HeaderByteSize)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//LogVerbose("Received " + bytesReceived + " bytes");
|
||||||
|
|
||||||
|
var ipsender = (NetEndPoint)m_senderRemote;
|
||||||
|
|
||||||
|
if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32)
|
||||||
{
|
{
|
||||||
int bytesReceived = 0;
|
// is this an UPnP response?
|
||||||
try
|
string resp = System.Text.Encoding.UTF8.GetString(m_receiveBuffer, 0, bytesReceived);
|
||||||
|
if (resp.Contains("upnp:rootdevice") || resp.Contains("UPnP/1.0"))
|
||||||
{
|
{
|
||||||
bytesReceived = m_socket.ReceiveFrom(m_receiveBuffer, 0, m_receiveBuffer.Length, SocketFlags.None, ref m_senderRemote);
|
|
||||||
}
|
|
||||||
catch (SocketException sx)
|
|
||||||
{
|
|
||||||
switch (sx.SocketErrorCode)
|
|
||||||
{
|
|
||||||
case SocketError.ConnectionReset:
|
|
||||||
// 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");
|
|
||||||
return;
|
|
||||||
|
|
||||||
case SocketError.NotConnected:
|
|
||||||
// socket is unbound; try to rebind it (happens on mobile when process goes to sleep)
|
|
||||||
BindSocket(true);
|
|
||||||
return;
|
|
||||||
|
|
||||||
default:
|
|
||||||
LogWarning("Socket exception: " + sx.ToString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bytesReceived < NetConstants.HeaderByteSize)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//LogVerbose("Received " + bytesReceived + " bytes");
|
|
||||||
|
|
||||||
var ipsender = (NetEndPoint)m_senderRemote;
|
|
||||||
|
|
||||||
if (m_upnp != null && now < m_upnp.m_discoveryResponseDeadline && bytesReceived > 32)
|
|
||||||
{
|
|
||||||
// is this an UPnP response?
|
|
||||||
string resp = System.Text.Encoding.UTF8.GetString(m_receiveBuffer, 0, bytesReceived);
|
|
||||||
if (resp.Contains("upnp:rootdevice") || resp.Contains("UPnP/1.0"))
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
|
|
||||||
resp = resp.Substring(0, resp.IndexOf("\r")).Trim();
|
|
||||||
m_upnp.ExtractServiceUrl(resp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
LogDebug("Failed to parse UPnP response: " + ex.ToString());
|
|
||||||
|
|
||||||
// don't try to parse this packet further
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NetConnection sender = null;
|
|
||||||
m_connectionLookup.TryGetValue(ipsender, out sender);
|
|
||||||
|
|
||||||
//
|
|
||||||
// parse packet into messages
|
|
||||||
//
|
|
||||||
int numMessages = 0;
|
|
||||||
int numFragments = 0;
|
|
||||||
int ptr = 0;
|
|
||||||
while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize)
|
|
||||||
{
|
|
||||||
// decode header
|
|
||||||
// 8 bits - NetMessageType
|
|
||||||
// 1 bit - Fragment?
|
|
||||||
// 15 bits - Sequence number
|
|
||||||
// 16 bits - Payload length in bits
|
|
||||||
|
|
||||||
numMessages++;
|
|
||||||
|
|
||||||
NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++];
|
|
||||||
|
|
||||||
byte low = m_receiveBuffer[ptr++];
|
|
||||||
byte high = m_receiveBuffer[ptr++];
|
|
||||||
|
|
||||||
bool isFragment = ((low & 1) == 1);
|
|
||||||
ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7));
|
|
||||||
|
|
||||||
if (isFragment)
|
|
||||||
numFragments++;
|
|
||||||
|
|
||||||
ushort payloadBitLength = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8));
|
|
||||||
int payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength);
|
|
||||||
|
|
||||||
if (bytesReceived - ptr < payloadByteLength)
|
|
||||||
{
|
|
||||||
LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tp >= NetMessageType.Unused1 && tp <= NetMessageType.Unused29)
|
|
||||||
{
|
|
||||||
ThrowOrLog("Unexpected NetMessageType: " + tp);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (tp >= NetMessageType.LibraryError)
|
resp = resp.Substring(resp.ToLower().IndexOf("location:") + 9);
|
||||||
{
|
resp = resp.Substring(0, resp.IndexOf("\r")).Trim();
|
||||||
if (sender != null)
|
m_upnp.ExtractServiceUrl(resp);
|
||||||
sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength);
|
return;
|
||||||
else
|
|
||||||
ReceivedUnconnectedLibraryMessage(now, ipsender, tp, ptr, payloadByteLength);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData))
|
|
||||||
return; // dropping unconnected message since it's not enabled
|
|
||||||
|
|
||||||
NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength);
|
|
||||||
msg.m_isFragment = isFragment;
|
|
||||||
msg.m_receiveTime = now;
|
|
||||||
msg.m_sequenceNumber = sequenceNumber;
|
|
||||||
msg.m_receivedMessageType = tp;
|
|
||||||
msg.m_senderConnection = sender;
|
|
||||||
msg.m_senderEndPoint = ipsender;
|
|
||||||
msg.m_bitLength = payloadBitLength;
|
|
||||||
|
|
||||||
Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength);
|
|
||||||
if (sender != null)
|
|
||||||
{
|
|
||||||
if (tp == NetMessageType.Unconnected)
|
|
||||||
{
|
|
||||||
// We're connected; but we can still send unconnected messages to this peer
|
|
||||||
msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
|
|
||||||
ReleaseMessage(msg);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// connected application (non-library) message
|
|
||||||
sender.ReceivedMessage(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// at this point we know the message type is enabled
|
|
||||||
// unconnected application (non-library) message
|
|
||||||
msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
|
|
||||||
ReleaseMessage(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
LogError("Packet parsing error: " + ex.Message + " from " + ipsender);
|
LogDebug("Failed to parse UPnP response: " + ex.ToString());
|
||||||
|
|
||||||
|
// don't try to parse this packet further
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
ptr += payloadByteLength;
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NetConnection sender = null;
|
||||||
|
m_connectionLookup.TryGetValue(ipsender, out sender);
|
||||||
|
|
||||||
|
//
|
||||||
|
// parse packet into messages
|
||||||
|
//
|
||||||
|
int numMessages = 0;
|
||||||
|
int numFragments = 0;
|
||||||
|
int ptr = 0;
|
||||||
|
while ((bytesReceived - ptr) >= NetConstants.HeaderByteSize)
|
||||||
|
{
|
||||||
|
// decode header
|
||||||
|
// 8 bits - NetMessageType
|
||||||
|
// 1 bit - Fragment?
|
||||||
|
// 15 bits - Sequence number
|
||||||
|
// 16 bits - Payload length in bits
|
||||||
|
|
||||||
|
numMessages++;
|
||||||
|
|
||||||
|
NetMessageType tp = (NetMessageType)m_receiveBuffer[ptr++];
|
||||||
|
|
||||||
|
byte low = m_receiveBuffer[ptr++];
|
||||||
|
byte high = m_receiveBuffer[ptr++];
|
||||||
|
|
||||||
|
bool isFragment = ((low & 1) == 1);
|
||||||
|
ushort sequenceNumber = (ushort)((low >> 1) | (((int)high) << 7));
|
||||||
|
|
||||||
|
if (isFragment)
|
||||||
|
numFragments++;
|
||||||
|
|
||||||
|
ushort payloadBitLength = (ushort)(m_receiveBuffer[ptr++] | (m_receiveBuffer[ptr++] << 8));
|
||||||
|
int payloadByteLength = NetUtility.BytesToHoldBits(payloadBitLength);
|
||||||
|
|
||||||
|
if (bytesReceived - ptr < payloadByteLength)
|
||||||
|
{
|
||||||
|
LogWarning("Malformed packet; stated payload length " + payloadByteLength + ", remaining bytes " + (bytesReceived - ptr));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
|
if (tp >= NetMessageType.Unused1 && tp <= NetMessageType.Unused29)
|
||||||
if (sender != null)
|
{
|
||||||
sender.m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
|
ThrowOrLog("Unexpected NetMessageType: " + tp);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
} while (m_socket.Available > 0);
|
try
|
||||||
}
|
{
|
||||||
|
if (tp >= NetMessageType.LibraryError)
|
||||||
|
{
|
||||||
|
if (sender != null)
|
||||||
|
sender.ReceivedLibraryMessage(tp, ptr, payloadByteLength);
|
||||||
|
else
|
||||||
|
ReceivedUnconnectedLibraryMessage(now, ipsender, tp, ptr, payloadByteLength);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sender == null && !m_configuration.IsMessageTypeEnabled(NetIncomingMessageType.UnconnectedData))
|
||||||
|
return; // dropping unconnected message since it's not enabled
|
||||||
|
|
||||||
/// <summary>
|
NetIncomingMessage msg = CreateIncomingMessage(NetIncomingMessageType.Data, payloadByteLength);
|
||||||
|
msg.m_isFragment = isFragment;
|
||||||
|
msg.m_receiveTime = now;
|
||||||
|
msg.m_sequenceNumber = sequenceNumber;
|
||||||
|
msg.m_receivedMessageType = tp;
|
||||||
|
msg.m_senderConnection = sender;
|
||||||
|
msg.m_senderEndPoint = ipsender;
|
||||||
|
msg.m_bitLength = payloadBitLength;
|
||||||
|
|
||||||
|
Buffer.BlockCopy(m_receiveBuffer, ptr, msg.m_data, 0, payloadByteLength);
|
||||||
|
if (sender != null)
|
||||||
|
{
|
||||||
|
if (tp == NetMessageType.Unconnected)
|
||||||
|
{
|
||||||
|
// We're connected; but we can still send unconnected messages to this peer
|
||||||
|
msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
|
||||||
|
ReleaseMessage(msg);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// connected application (non-library) message
|
||||||
|
sender.ReceivedMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// at this point we know the message type is enabled
|
||||||
|
// unconnected application (non-library) message
|
||||||
|
msg.m_incomingMessageType = NetIncomingMessageType.UnconnectedData;
|
||||||
|
ReleaseMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
LogError("Packet parsing error: " + ex.Message + " from " + ipsender);
|
||||||
|
}
|
||||||
|
ptr += payloadByteLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
|
||||||
|
if (sender != null)
|
||||||
|
sender.m_statistics.PacketReceived(bytesReceived, numMessages, numFragments);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
/// If NetPeerConfiguration.AutoFlushSendQueue() is false; you need to call this to send all messages queued using SendMessage()
|
/// If NetPeerConfiguration.AutoFlushSendQueue() is false; you need to call this to send all messages queued using SendMessage()
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void FlushSendQueue()
|
public void FlushSendQueue()
|
||||||
|
@ -686,7 +701,7 @@ namespace Lidgren.Network
|
||||||
case NetMessageType.Connect:
|
case NetMessageType.Connect:
|
||||||
if (m_configuration.AcceptIncomingConnections == false)
|
if (m_configuration.AcceptIncomingConnections == false)
|
||||||
{
|
{
|
||||||
LogWarning(m_configuration.AppIdentifier + " Received Connect, but we're not accepting incoming connections!");
|
LogWarning("Received Connect, but we're not accepting incoming connections!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// handle connect
|
// handle connect
|
||||||
|
|
|
@ -132,6 +132,9 @@ namespace Lidgren.Network
|
||||||
catch { }
|
catch { }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Avoids allocation on mapping to IPv6
|
||||||
|
private IPEndPoint targetCopy = new IPEndPoint(IPAddress.Any, 0);
|
||||||
|
|
||||||
internal bool ActuallySendPacket(byte[] data, int numBytes, NetEndPoint target, out bool connectionReset)
|
internal bool ActuallySendPacket(byte[] data, int numBytes, NetEndPoint target, out bool connectionReset)
|
||||||
{
|
{
|
||||||
connectionReset = false;
|
connectionReset = false;
|
||||||
|
@ -140,17 +143,25 @@ namespace Lidgren.Network
|
||||||
{
|
{
|
||||||
ba = NetUtility.GetCachedBroadcastAddress();
|
ba = NetUtility.GetCachedBroadcastAddress();
|
||||||
|
|
||||||
// TODO: refactor this check outta here
|
// TODO: refactor this check outta here
|
||||||
if (target.Address.Equals(ba))
|
if (target.Address.Equals(ba))
|
||||||
{
|
{
|
||||||
// Some networks do not allow
|
// Some networks do not allow
|
||||||
// a global broadcast so we use the BroadcastAddress from the configuration
|
// a global broadcast so we use the BroadcastAddress from the configuration
|
||||||
// this can be resolved to a local broadcast addresss e.g 192.168.x.255
|
// this can be resolved to a local broadcast addresss e.g 192.168.x.255
|
||||||
target.Address = m_configuration.BroadcastAddress;
|
targetCopy.Address = m_configuration.BroadcastAddress;
|
||||||
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
|
targetCopy.Port = target.Port;
|
||||||
}
|
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, true);
|
||||||
|
}
|
||||||
|
else if(m_configuration.DualStack && m_configuration.LocalAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
|
NetUtility.CopyEndpoint(target, targetCopy); //Maps to IPv6 for Dual Mode
|
||||||
|
else
|
||||||
|
{
|
||||||
|
targetCopy.Port = target.Port;
|
||||||
|
targetCopy.Address = target.Address;
|
||||||
|
}
|
||||||
|
|
||||||
int bytesSent = m_socket.SendTo(data, 0, numBytes, SocketFlags.None, target);
|
int bytesSent = m_socket.SendTo(data, 0, numBytes, SocketFlags.None, targetCopy);
|
||||||
if (numBytes != bytesSent)
|
if (numBytes != bytesSent)
|
||||||
LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
|
LogWarning("Failed to send the full " + numBytes + "; only " + bytesSent + " bytes sent in packet!");
|
||||||
|
|
||||||
|
@ -178,7 +189,7 @@ namespace Lidgren.Network
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
if (target.Address == ba)
|
if (target.Address.Equals(ba))
|
||||||
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false);
|
m_socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.Broadcast, false);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -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,9 +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>();
|
||||||
m_senderRemote = (EndPoint)new NetEndPoint(IPAddress.Any, 0);
|
if (m_configuration.LocalAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
|
{
|
||||||
|
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>
|
||||||
|
@ -148,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;
|
||||||
|
@ -183,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...
|
||||||
|
@ -191,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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -215,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.
|
||||||
|
@ -303,6 +310,8 @@ namespace Lidgren.Network
|
||||||
{
|
{
|
||||||
if (remoteEndPoint == null)
|
if (remoteEndPoint == null)
|
||||||
throw new ArgumentNullException("remoteEndPoint");
|
throw new ArgumentNullException("remoteEndPoint");
|
||||||
|
if(m_configuration.DualStack)
|
||||||
|
remoteEndPoint = NetUtility.MapToIPv6(remoteEndPoint);
|
||||||
|
|
||||||
lock (m_connections)
|
lock (m_connections)
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -48,6 +48,8 @@ namespace Lidgren.Network
|
||||||
private string m_networkThreadName;
|
private string m_networkThreadName;
|
||||||
private IPAddress m_localAddress;
|
private IPAddress m_localAddress;
|
||||||
private IPAddress m_broadcastAddress;
|
private IPAddress m_broadcastAddress;
|
||||||
|
private bool m_dualStack;
|
||||||
|
|
||||||
internal bool m_acceptIncomingConnections;
|
internal bool m_acceptIncomingConnections;
|
||||||
internal int m_maximumConnections;
|
internal int m_maximumConnections;
|
||||||
internal int m_defaultOutgoingMessageCapacity;
|
internal int m_defaultOutgoingMessageCapacity;
|
||||||
|
@ -341,10 +343,26 @@ namespace Lidgren.Network
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the local broadcast address to use when broadcasting
|
/// Gets or sets a value indicating whether the library should use IPv6 dual stack mode.
|
||||||
/// </summary>
|
/// If you enable this you should make sure that the <see cref="LocalAddress"/> is an IPv6 address.
|
||||||
public IPAddress BroadcastAddress
|
/// Cannot be changed once NetPeer is initialized.
|
||||||
|
/// </summary>
|
||||||
|
public bool DualStack
|
||||||
|
{
|
||||||
|
get { return m_dualStack; }
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (m_isLocked)
|
||||||
|
throw new NetException(c_isLockedMessage);
|
||||||
|
m_dualStack = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the local broadcast address to use when broadcasting
|
||||||
|
/// </summary>
|
||||||
|
public IPAddress BroadcastAddress
|
||||||
{
|
{
|
||||||
get { return m_broadcastAddress; }
|
get { return m_broadcastAddress; }
|
||||||
set
|
set
|
||||||
|
|
|
@ -98,7 +98,7 @@ namespace Lidgren.Network
|
||||||
NetAddress ipAddress = null;
|
NetAddress ipAddress = null;
|
||||||
if (NetAddress.TryParse(ipOrHost, out ipAddress))
|
if (NetAddress.TryParse(ipOrHost, out ipAddress))
|
||||||
{
|
{
|
||||||
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
|
if (ipAddress.AddressFamily == AddressFamily.InterNetwork || ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
{
|
{
|
||||||
callback(ipAddress);
|
callback(ipAddress);
|
||||||
return;
|
return;
|
||||||
|
@ -139,7 +139,7 @@ namespace Lidgren.Network
|
||||||
// check each entry for a valid IP address
|
// check each entry for a valid IP address
|
||||||
foreach (var ipCurrent in entry.AddressList)
|
foreach (var ipCurrent in entry.AddressList)
|
||||||
{
|
{
|
||||||
if (ipCurrent.AddressFamily == AddressFamily.InterNetwork)
|
if (ipCurrent.AddressFamily == AddressFamily.InterNetwork || ipCurrent.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
{
|
{
|
||||||
callback(ipCurrent);
|
callback(ipCurrent);
|
||||||
return;
|
return;
|
||||||
|
@ -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)
|
||||||
|
@ -176,9 +176,9 @@ namespace Lidgren.Network
|
||||||
NetAddress ipAddress = null;
|
NetAddress ipAddress = null;
|
||||||
if (NetAddress.TryParse(ipOrHost, out ipAddress))
|
if (NetAddress.TryParse(ipOrHost, out ipAddress))
|
||||||
{
|
{
|
||||||
if (ipAddress.AddressFamily == AddressFamily.InterNetwork)
|
if (ipAddress.AddressFamily == AddressFamily.InterNetwork || ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
return ipAddress;
|
return ipAddress;
|
||||||
throw new ArgumentException("This method will not currently resolve other than ipv4 addresses");
|
throw new ArgumentException("This method will not currently resolve other than IPv4 or IPv6 addresses");
|
||||||
}
|
}
|
||||||
|
|
||||||
// ok must be a host name
|
// ok must be a host name
|
||||||
|
@ -189,7 +189,7 @@ namespace Lidgren.Network
|
||||||
return null;
|
return null;
|
||||||
foreach (var address in addresses)
|
foreach (var address in addresses)
|
||||||
{
|
{
|
||||||
if (address.AddressFamily == AddressFamily.InterNetwork)
|
if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6)
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -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>
|
||||||
|
@ -465,5 +465,29 @@ namespace Lidgren.Network
|
||||||
// this is defined in the platform specific files
|
// this is defined in the platform specific files
|
||||||
return ComputeSHAHash(bytes, 0, bytes.Length);
|
return ComputeSHAHash(bytes, 0, bytes.Length);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
/// <summary>
|
||||||
|
/// Copies from <paramref name="src"/> to <paramref name="dst"/>. Maps to an IPv6 address
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="src">Source.</param>
|
||||||
|
/// <param name="dst">Destination.</param>
|
||||||
|
internal static void CopyEndpoint(IPEndPoint src, IPEndPoint dst)
|
||||||
|
{
|
||||||
|
dst.Port = src.Port;
|
||||||
|
if (src.AddressFamily == AddressFamily.InterNetwork)
|
||||||
|
dst.Address = src.Address.MapToIPv6();
|
||||||
|
else
|
||||||
|
dst.Address = src.Address;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maps the IPEndPoint object to an IPv6 address. Has allocation
|
||||||
|
/// </summary>
|
||||||
|
internal static IPEndPoint MapToIPv6(IPEndPoint endPoint)
|
||||||
|
{
|
||||||
|
if (endPoint.AddressFamily == AddressFamily.InterNetwork)
|
||||||
|
return new IPEndPoint(endPoint.Address.MapToIPv6(), endPoint.Port);
|
||||||
|
return endPoint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ using System.Resources;
|
||||||
[assembly: AssemblyCulture("")]
|
[assembly: AssemblyCulture("")]
|
||||||
|
|
||||||
// Version informationr(
|
// Version informationr(
|
||||||
[assembly: AssemblyVersion("0.0.0.1524")]
|
[assembly: AssemblyVersion("0.0.0.1525")]
|
||||||
[assembly: AssemblyFileVersion("0.0.0.1524")]
|
[assembly: AssemblyFileVersion("0.0.0.1525")]
|
||||||
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
|
[assembly: NeutralResourcesLanguageAttribute( "en-US" )]
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"id": "srmp",
|
"id": "srmp",
|
||||||
"name": "Slime Rancher Multiplayer",
|
"name": "Slime Rancher Multiplayer",
|
||||||
"version": "0.0.1524",
|
"version": "0.0.1525",
|
||||||
"author": "SatyPardus",
|
"author": "SatyPardus",
|
||||||
"dependencies": [
|
"dependencies": [
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue