using MediaBrowser.Common.Net; using MediaBrowser.Model.Net; using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Net; using System.Net.NetworkInformation; using System.Net.Sockets; using System.Runtime.InteropServices; namespace MediaBrowser.Common.Implementations.NetworkManagement { /// /// Class NetUtils /// public class NetworkManager : INetworkManager { /// /// Gets the machine's local ip address /// /// IPAddress. public IEnumerable GetLocalIpAddresses() { var host = Dns.GetHostEntry(Dns.GetHostName()); // Reverse them because the last one is usually the correct one // It's not fool-proof so ultimately the consumer will have to examine them and decide return host.AddressList .Where(i => i.AddressFamily == AddressFamily.InterNetwork) .Select(i => i.ToString()) .Reverse(); } /// /// Gets a random port number that is currently available /// /// System.Int32. public int GetRandomUnusedPort() { var listener = new TcpListener(IPAddress.Any, 0); listener.Start(); var port = ((IPEndPoint)listener.LocalEndpoint).Port; listener.Stop(); return port; } /// /// Returns MAC Address from first Network Card in Computer /// /// [string] MAC Address public string GetMacAddress() { return NetworkInterface.GetAllNetworkInterfaces() .Where(i => i.NetworkInterfaceType != NetworkInterfaceType.Loopback) .Select(i => BitConverter.ToString(i.GetPhysicalAddress().GetAddressBytes())) .FirstOrDefault(); } /// /// Uses the DllImport : NetServerEnum with all its required parameters /// (see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp /// for full details or method signature) to retrieve a list of domain SV_TYPE_WORKSTATION /// and SV_TYPE_SERVER PC's /// /// Arraylist that represents all the SV_TYPE_WORKSTATION and SV_TYPE_SERVER /// PC's in the Domain public IEnumerable GetNetworkDevices() { //local fields const int MAX_PREFERRED_LENGTH = -1; var SV_TYPE_WORKSTATION = 1; var SV_TYPE_SERVER = 2; var buffer = IntPtr.Zero; var tmpBuffer = IntPtr.Zero; var entriesRead = 0; var totalEntries = 0; var resHandle = 0; var sizeofINFO = Marshal.SizeOf(typeof(_SERVER_INFO_100)); try { //call the DllImport : NetServerEnum with all its required parameters //see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp //for full details of method signature var ret = NativeMethods.NetServerEnum(null, 100, ref buffer, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, SV_TYPE_WORKSTATION | SV_TYPE_SERVER, null, out resHandle); //if the returned with a NERR_Success (C++ term), =0 for C# if (ret == 0) { //loop through all SV_TYPE_WORKSTATION and SV_TYPE_SERVER PC's for (var i = 0; i < totalEntries; i++) { //get pointer to, Pointer to the buffer that received the data from //the call to NetServerEnum. Must ensure to use correct size of //STRUCTURE to ensure correct location in memory is pointed to tmpBuffer = new IntPtr((int)buffer + (i * sizeofINFO)); //Have now got a pointer to the list of SV_TYPE_WORKSTATION and //SV_TYPE_SERVER PC's, which is unmanaged memory //Needs to Marshal data from an unmanaged block of memory to a //managed object, again using STRUCTURE to ensure the correct data //is marshalled var svrInfo = (_SERVER_INFO_100)Marshal.PtrToStructure(tmpBuffer, typeof(_SERVER_INFO_100)); //add the PC names to the ArrayList if (!string.IsNullOrEmpty(svrInfo.sv100_name)) { yield return svrInfo.sv100_name; } } } } finally { //The NetApiBufferFree function frees //the memory that the NetApiBufferAllocate function allocates NativeMethods.NetApiBufferFree(buffer); } } /// /// Gets the network shares. /// /// The path. /// IEnumerable{NetworkShare}. public IEnumerable GetNetworkShares(string path) { return new ShareCollection(path).OfType().Select(ToNetworkShare); } /// /// To the network share. /// /// The share. /// NetworkShare. private NetworkShare ToNetworkShare(Share share) { return new NetworkShare { Name = share.NetName, Path = share.Path, Remark = share.Remark, Server = share.Server, ShareType = ToNetworkShareType(share.ShareType) }; } /// /// To the type of the network share. /// /// Type of the share. /// NetworkShareType. /// Unknown share type private NetworkShareType ToNetworkShareType(ShareType shareType) { if (shareType.HasFlag(ShareType.Special)) { return NetworkShareType.Special; } if (shareType.HasFlag(ShareType.Device)) { return NetworkShareType.Device; } if (shareType.HasFlag(ShareType.Disk)) { return NetworkShareType.Disk; } if (shareType.HasFlag(ShareType.IPC)) { return NetworkShareType.Ipc; } if (shareType.HasFlag(ShareType.Printer)) { return NetworkShareType.Printer; } throw new ArgumentException("Unknown share type"); } /// /// Parses the specified endpointstring. /// /// The endpointstring. /// IPEndPoint. public IPEndPoint Parse(string endpointstring) { return Parse(endpointstring, -1); } /// /// Parses the specified endpointstring. /// /// The endpointstring. /// The defaultport. /// IPEndPoint. /// Endpoint descriptor may not be empty. /// private static IPEndPoint Parse(string endpointstring, int defaultport) { if (string.IsNullOrEmpty(endpointstring) || endpointstring.Trim().Length == 0) { throw new ArgumentException("Endpoint descriptor may not be empty."); } if (defaultport != -1 && (defaultport < IPEndPoint.MinPort || defaultport > IPEndPoint.MaxPort)) { throw new ArgumentException(string.Format("Invalid default port '{0}'", defaultport)); } string[] values = endpointstring.Split(new char[] { ':' }); IPAddress ipaddy; int port = -1; //check if we have an IPv6 or ports if (values.Length <= 2) // ipv4 or hostname { port = values.Length == 1 ? defaultport : GetPort(values[1]); //try to use the address as IPv4, otherwise get hostname if (!IPAddress.TryParse(values[0], out ipaddy)) ipaddy = GetIPfromHost(values[0]); } else if (values.Length > 2) //ipv6 { //could [a:b:c]:d if (values[0].StartsWith("[") && values[values.Length - 2].EndsWith("]")) { string ipaddressstring = string.Join(":", values.Take(values.Length - 1).ToArray()); ipaddy = IPAddress.Parse(ipaddressstring); port = GetPort(values[values.Length - 1]); } else //[a:b:c] or a:b:c { ipaddy = IPAddress.Parse(endpointstring); port = defaultport; } } else { throw new FormatException(string.Format("Invalid endpoint ipaddress '{0}'", endpointstring)); } if (port == -1) throw new ArgumentException(string.Format("No port specified: '{0}'", endpointstring)); return new IPEndPoint(ipaddy, port); } protected static readonly CultureInfo UsCulture = new CultureInfo("en-US"); /// /// Gets the port. /// /// The p. /// System.Int32. /// private static int GetPort(string p) { int port; if (!int.TryParse(p, out port) || port < IPEndPoint.MinPort || port > IPEndPoint.MaxPort) { throw new FormatException(string.Format("Invalid end point port '{0}'", p)); } return port; } /// /// Gets the I pfrom host. /// /// The p. /// IPAddress. /// private static IPAddress GetIPfromHost(string p) { var hosts = Dns.GetHostAddresses(p); if (hosts == null || hosts.Length == 0) throw new ArgumentException(string.Format("Host not found: {0}", p)); return hosts[0]; } } }