Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Only resolve addresses with correct family in NetPeer.Connect #143

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Lidgren.Network/NetPeer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
183 changes: 125 additions & 58 deletions Lidgren.Network/NetUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,33 +50,43 @@ public static partial class NetUtility
/// </summary>
public delegate void ResolveAddressCallback(NetAddress adr);

/// <summary>
/// Get IPv4 endpoint from notation (xxx.xxx.xxx.xxx) or hostname and port number (asynchronous version)
/// <summary>
/// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname (asynchronous version)
/// </summary>
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);
}

/// <summary>
/// Get IPv4 endpoint from notation (xxx.xxx.xxx.xxx) or hostname and port number
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));
}
});
}

/// <summary>
/// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname
/// </summary>
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()
{
Expand All @@ -86,18 +96,38 @@ public static IPAddress GetCachedBroadcastAddress()
}

/// <summary>
/// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname (asynchronous version)
/// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname (asynchronous version)
/// </summary>
public static void ResolveAsync(string ipOrHost, ResolveAddressCallback callback)
{

}

/// <summary>
/// Get IPv4 or IPv6 address from notation (xxx.xxx.xxx.xxx or xxxx:xxxx:...:xxxx) or hostname (asynchronous version)
/// </summary>
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);
Expand Down Expand Up @@ -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);
Expand All @@ -164,49 +195,85 @@ public static void ResolveAsync(string ipOrHost, ResolveAddressCallback callback
}

/// <summary>
/// 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
/// </summary>
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");
}
/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// If <paramref name="allowedFamily"/> is not null, the address returned will only be of the specified family.
/// </remarks>
/// <param name="ipOrHost">The hostname or IP address to parse.</param>
/// <param name="allowedFamily">If not null, the allowed address family to return.</param>
/// <returns>
/// A resolved address matching the specified filter if it exists,
/// null if no such address exists or a lookup error occured.
/// </returns>
/// <exception cref="ArgumentException">
/// <paramref name="ipOrHost"/> is null or empty OR
/// <paramref name="allowedFamily"/> is not one of null, <see cref="AddressFamily.InterNetwork"/>
/// or <see cref="AddressFamily.InterNetworkV6"/>
/// </exception>
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;
}
}
}

/// <summary>
/// Create a hex string from an Int64 value
Expand Down