From 2d0613516626960de5d7e3ea83b6386ce00dcb74 Mon Sep 17 00:00:00 2001 From: Adam Frisby Date: Sat, 23 May 2009 05:09:10 +0000 Subject: * Adds new NetworkUtil class, contains methods for handling IP resolution when located on the same subnet. (Eg, can be used to avoid NAT Loopback requirements if fully utilized.) * Adds a few new network-related methods to Util. --- OpenSim/Framework/NetworkUtil.cs | 122 +++++++++++++++++++++++++++++++++++++++ OpenSim/Framework/Util.cs | 14 +++++ 2 files changed, 136 insertions(+) create mode 100644 OpenSim/Framework/NetworkUtil.cs diff --git a/OpenSim/Framework/NetworkUtil.cs b/OpenSim/Framework/NetworkUtil.cs new file mode 100644 index 0000000..1abf0d8 --- /dev/null +++ b/OpenSim/Framework/NetworkUtil.cs @@ -0,0 +1,122 @@ +using System.Collections.Generic; +using System.Net.Sockets; +using System.Net; +using System.Net.NetworkInformation; + +namespace OpenSim.Framework +{ + /// <summary> + /// Handles NAT translation in a 'manner of speaking' + /// Allows you to return multiple different external + /// hostnames depending on the requestors network + /// + /// This enables standard port forwarding techniques + /// to work correctly with OpenSim. + /// </summary> + static class NetworkUtil + { + // IPv4Address, Subnet + static readonly Dictionary<IPAddress,IPAddress> m_subnets = new Dictionary<IPAddress, IPAddress>(); + + private static IPAddress GetExternalIPFor(IPAddress destination, string defaultHostname) + { + // Adds IPv6 Support (Not that any of the major protocols supports it...) + if (destination.AddressFamily == AddressFamily.InterNetworkV6) + { + foreach (IPAddress host in Dns.GetHostAddresses(defaultHostname)) + { + if (host.AddressFamily == AddressFamily.InterNetworkV6) + return host; + } + } + + if(destination.AddressFamily != AddressFamily.InterNetwork) + return null; + + // Check if we're accessing localhost. + foreach (IPAddress host in Dns.GetHostAddresses(Dns.GetHostName())) + { + if (host.Equals(destination)) + return destination; + } + + // Check for same LAN segment + foreach (KeyValuePair<IPAddress, IPAddress> subnet in m_subnets) + { + byte[] subnetBytes = subnet.Value.GetAddressBytes(); + byte[] localBytes = subnet.Key.GetAddressBytes(); + byte[] destBytes = destination.GetAddressBytes(); + + if(subnetBytes.Length != destBytes.Length || subnetBytes.Length != localBytes.Length) + return null; + + bool valid = true; + + for(int i=0;i<subnetBytes.Length;i++) + { + if ((localBytes[i] & subnetBytes[i]) != (destBytes[i] & subnetBytes[i])) + { + valid = false; + break; + } + } + + if (valid) + return subnet.Key; + } + + // None found. Assume outside network. + return null; + } + + static NetworkUtil() + { + foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces()) + { + foreach (UnicastIPAddressInformation address in ni.GetIPProperties().UnicastAddresses) + { + if (address.Address.AddressFamily == AddressFamily.InterNetwork) + { + m_subnets.Add(address.Address, address.IPv4Mask); + } + } + } + } + + public static IPAddress GetIPFor(IPEndPoint user, string defaultHostname) + { + // Try subnet matching + IPAddress rtn = GetExternalIPFor(user.Address, defaultHostname); + if (rtn != null) + return rtn; + + // Otherwise use the old algorithm + IPAddress ia; + + if (IPAddress.TryParse(defaultHostname, out ia)) + return ia; + + ia = null; + + foreach (IPAddress Adr in Dns.GetHostAddresses(defaultHostname)) + { + if (Adr.AddressFamily == AddressFamily.InterNetwork) + { + ia = Adr; + break; + } + } + + return ia; + } + + public static string GetHostFor(IPAddress user, string defaultHostname) + { + IPAddress rtn = GetExternalIPFor(user, defaultHostname); + if(rtn != null) + return rtn.ToString(); + + return defaultHostname; + } + } +} diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 35efa02..0128735 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -517,6 +517,20 @@ namespace OpenSim.Framework return null; } + public static Uri GetURI(string protocol, string hostname, int port, string path) + { + return new UriBuilder(protocol, hostname, port, path).Uri; + } + + /// <summary> + /// Gets a list of all local system IP addresses + /// </summary> + /// <returns></returns> + public static IPAddress[] GetLocalHosts() + { + return Dns.GetHostAddresses(Dns.GetHostName()); + } + public static IPAddress GetLocalHost() { string dnsAddress = "localhost"; -- cgit v1.1