Skip to content

Commit

Permalink
Only resolve addresses with correct family in NetPeer.Connect
Browse files Browse the repository at this point in the history
  • Loading branch information
PJB3005 committed Jul 17, 2020
1 parent 3ab2d8d commit 423d059
Show file tree
Hide file tree
Showing 2 changed files with 123 additions and 55 deletions.
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
173 changes: 120 additions & 53 deletions Lidgren.Network/NetUtility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,38 @@ public static partial class NetUtility
/// </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);
}

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 endpoint from notation (xxx.xxx.xxx.xxx) or hostname and port number
/// </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 @@ -89,15 +99,35 @@ public static IPAddress GetCachedBroadcastAddress()
/// Get IPv4 address from notation (xxx.xxx.xxx.xxx) or hostname (asynchronous version)
/// </summary>
public static void ResolveAsync(string ipOrHost, ResolveAddressCallback callback)
{

}

/// <summary>
/// Get IPv4 address from notation (xxx.xxx.xxx.xxx) 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

0 comments on commit 423d059

Please sign in to comment.