diff --git a/Lidgren.Network/NetPeer.cs b/Lidgren.Network/NetPeer.cs
index dec79af4..3ea06a91 100644
--- a/Lidgren.Network/NetPeer.cs
+++ b/Lidgren.Network/NetPeer.cs
@@ -271,9 +271,10 @@ internal void SendLibrary(NetOutgoingMessage msg, NetEndPoint recipient)
Recycle(msg);
}
- static NetEndPoint GetNetEndPoint(string host, int port)
+ private NetEndPoint GetNetEndPoint(string host, int port)
{
- IPAddress address = NetUtility.Resolve(host);
+ var family = m_configuration.DualStack ? null : (AddressFamily?) m_configuration.LocalAddress.AddressFamily;
+ IPAddress address = NetUtility.Resolve(host, family);
if (address == null)
throw new NetException("Could not resolve host");
return new NetEndPoint(address, port);
diff --git a/Lidgren.Network/NetUtility.cs b/Lidgren.Network/NetUtility.cs
index 1120faa9..c23fe48a 100644
--- a/Lidgren.Network/NetUtility.cs
+++ b/Lidgren.Network/NetUtility.cs
@@ -55,28 +55,38 @@ public static partial class NetUtility
///
public static void ResolveAsync(string ipOrHost, int port, ResolveEndPointCallback callback)
{
- ResolveAsync(ipOrHost, delegate(NetAddress adr)
- {
- if (adr == null)
- {
- callback(null);
- }
- else
- {
- callback(new NetEndPoint(adr, port));
- }
- });
+ ResolveAsync(ipOrHost, port, null, callback);
}
+ public static void ResolveAsync(string ipOrHost, int port, AddressFamily? allowedFamily, ResolveEndPointCallback callback)
+ {
+ ResolveAsync(ipOrHost, allowedFamily, delegate(NetAddress adr)
+ {
+ if (adr == null)
+ {
+ callback(null);
+ }
+ else
+ {
+ callback(new NetEndPoint(adr, port));
+ }
+ });
+ }
+
///
/// Get IPv4 endpoint from notation (xxx.xxx.xxx.xxx) or hostname and port number
///
public static NetEndPoint Resolve(string ipOrHost, int port)
{
- var adr = Resolve(ipOrHost);
- return adr == null ? null : new NetEndPoint(adr, port);
+ return Resolve(ipOrHost, port, null);
}
+ public static NetEndPoint Resolve(string ipOrHost, int port, AddressFamily? allowedFamily)
+ {
+ var adr = Resolve(ipOrHost, allowedFamily);
+ return adr == null ? null : new NetEndPoint(adr, port);
+ }
+
private static IPAddress s_broadcastAddress;
public static IPAddress GetCachedBroadcastAddress()
{
@@ -89,15 +99,35 @@ public static IPAddress GetCachedBroadcastAddress()
/// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname (asynchronous version)
///
public static void ResolveAsync(string ipOrHost, ResolveAddressCallback callback)
+ {
+
+ }
+
+ ///
+ /// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname (asynchronous version)
+ ///
+ public static void ResolveAsync(string ipOrHost, AddressFamily? allowedFamily, ResolveAddressCallback callback)
{
if (string.IsNullOrEmpty(ipOrHost))
throw new ArgumentException("Supplied string must not be empty", "ipOrHost");
+ if (allowedFamily != null && allowedFamily != AddressFamily.InterNetwork
+ && allowedFamily != AddressFamily.InterNetworkV6)
+ {
+ throw new ArgumentException("Address family must be either InterNetwork, InterNetworkV6 or null",
+ nameof(allowedFamily));
+ }
+
ipOrHost = ipOrHost.Trim();
NetAddress ipAddress = null;
if (NetAddress.TryParse(ipOrHost, out ipAddress))
{
+ if (allowedFamily != null && ipAddress.AddressFamily != allowedFamily)
+ {
+ callback(null);
+ return;
+ }
if (ipAddress.AddressFamily == AddressFamily.InterNetwork || ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
{
callback(ipAddress);
@@ -139,11 +169,12 @@ public static void ResolveAsync(string ipOrHost, ResolveAddressCallback callback
// check each entry for a valid IP address
foreach (var ipCurrent in entry.AddressList)
{
- if (ipCurrent.AddressFamily == AddressFamily.InterNetwork || ipCurrent.AddressFamily == AddressFamily.InterNetworkV6)
- {
+ var family = ipCurrent.AddressFamily;
+ if (family != AddressFamily.InterNetwork && family != AddressFamily.InterNetworkV6)
+ continue;
+ if (allowedFamily == null || allowedFamily == family)
callback(ipCurrent);
- return;
- }
+ return;
}
callback(null);
@@ -164,49 +195,85 @@ public static void ResolveAsync(string ipOrHost, ResolveAddressCallback callback
}
///
- /// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname
+ /// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname
///
public static NetAddress Resolve(string ipOrHost)
- {
- if (string.IsNullOrEmpty(ipOrHost))
- throw new ArgumentException("Supplied string must not be empty", "ipOrHost");
+ {
+ return Resolve(ipOrHost, null);
+ }
- ipOrHost = ipOrHost.Trim();
- NetAddress ipAddress = null;
- if (NetAddress.TryParse(ipOrHost, out ipAddress))
- {
- if (ipAddress.AddressFamily == AddressFamily.InterNetwork || ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
- return ipAddress;
- throw new ArgumentException("This method will not currently resolve other than IPv4 or IPv6 addresses");
- }
+ ///
+ /// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname,
+ /// taking in an allowed address family to filter resolved addresses by.
+ ///
+ ///
+ /// If is not null, the address returned will only be of the specified family.
+ ///
+ /// The hostname or IP address to parse.
+ /// If not null, the allowed address family to return.
+ ///
+ /// A resolved address matching the specified filter if it exists,
+ /// null if no such address exists or a lookup error occured.
+ ///
+ ///
+ /// is null or empty OR
+ /// is not one of null,
+ /// or
+ ///
+ public static NetAddress Resolve(string ipOrHost, AddressFamily? allowedFamily)
+ {
+ if (string.IsNullOrEmpty(ipOrHost))
+ throw new ArgumentException("Supplied string must not be empty", "ipOrHost");
- // ok must be a host name
- try
+ if (allowedFamily != null && allowedFamily != AddressFamily.InterNetwork
+ && allowedFamily != AddressFamily.InterNetworkV6)
{
- var addresses = Dns.GetHostAddresses(ipOrHost);
- if (addresses == null)
- return null;
- foreach (var address in addresses)
- {
- if (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6)
- return address;
- }
- return null;
- }
- catch (SocketException ex)
- {
- if (ex.SocketErrorCode == SocketError.HostNotFound)
- {
- //LogWrite(string.Format(CultureInfo.InvariantCulture, "Failed to resolve host '{0}'.", ipOrHost));
- return null;
- }
- else
- {
- throw;
- }
+ throw new ArgumentException("Address family must be either InterNetwork, InterNetworkV6 or null",
+ nameof(allowedFamily));
}
- }
+
+ ipOrHost = ipOrHost.Trim();
+
+ NetAddress ipAddress = null;
+ if (NetAddress.TryParse(ipOrHost, out ipAddress))
+ {
+ if (allowedFamily != null && ipAddress.AddressFamily != allowedFamily)
+ return null;
+ if (ipAddress.AddressFamily == AddressFamily.InterNetwork || ipAddress.AddressFamily == AddressFamily.InterNetworkV6)
+ return ipAddress;
+ throw new ArgumentException("This method will not currently resolve other than IPv4 or IPv6 addresses");
+ }
+
+ // ok must be a host name
+ try
+ {
+ var addresses = Dns.GetHostAddresses(ipOrHost);
+ if (addresses == null)
+ return null;
+ foreach (var address in addresses)
+ {
+ var family = address.AddressFamily;
+ if (family != AddressFamily.InterNetwork && family != AddressFamily.InterNetworkV6)
+ continue;
+ if (allowedFamily == null || allowedFamily == family)
+ return address;
+ }
+ return null;
+ }
+ catch (SocketException ex)
+ {
+ if (ex.SocketErrorCode == SocketError.HostNotFound)
+ {
+ //LogWrite(string.Format(CultureInfo.InvariantCulture, "Failed to resolve host '{0}'.", ipOrHost));
+ return null;
+ }
+ else
+ {
+ throw;
+ }
+ }
+ }
///
/// Create a hex string from an Int64 value