NetworkManager.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291
  1. using MediaBrowser.Common.Net;
  2. using MediaBrowser.Model.Net;
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Globalization;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Net.NetworkInformation;
  9. using System.Net.Sockets;
  10. using System.Runtime.InteropServices;
  11. namespace MediaBrowser.Common.Implementations.NetworkManagement
  12. {
  13. /// <summary>
  14. /// Class NetUtils
  15. /// </summary>
  16. public class NetworkManager : INetworkManager
  17. {
  18. /// <summary>
  19. /// Gets the machine's local ip address
  20. /// </summary>
  21. /// <returns>IPAddress.</returns>
  22. public IEnumerable<string> GetLocalIpAddresses()
  23. {
  24. var host = Dns.GetHostEntry(Dns.GetHostName());
  25. // Reverse them because the last one is usually the correct one
  26. // It's not fool-proof so ultimately the consumer will have to examine them and decide
  27. return host.AddressList
  28. .Where(i => i.AddressFamily == AddressFamily.InterNetwork)
  29. .Select(i => i.ToString())
  30. .Reverse();
  31. }
  32. /// <summary>
  33. /// Gets a random port number that is currently available
  34. /// </summary>
  35. /// <returns>System.Int32.</returns>
  36. public int GetRandomUnusedPort()
  37. {
  38. var listener = new TcpListener(IPAddress.Any, 0);
  39. listener.Start();
  40. var port = ((IPEndPoint)listener.LocalEndpoint).Port;
  41. listener.Stop();
  42. return port;
  43. }
  44. /// <summary>
  45. /// Returns MAC Address from first Network Card in Computer
  46. /// </summary>
  47. /// <returns>[string] MAC Address</returns>
  48. public string GetMacAddress()
  49. {
  50. return NetworkInterface.GetAllNetworkInterfaces()
  51. .Where(i => i.NetworkInterfaceType != NetworkInterfaceType.Loopback)
  52. .Select(i => BitConverter.ToString(i.GetPhysicalAddress().GetAddressBytes()))
  53. .FirstOrDefault();
  54. }
  55. /// <summary>
  56. /// Uses the DllImport : NetServerEnum with all its required parameters
  57. /// (see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp
  58. /// for full details or method signature) to retrieve a list of domain SV_TYPE_WORKSTATION
  59. /// and SV_TYPE_SERVER PC's
  60. /// </summary>
  61. /// <returns>Arraylist that represents all the SV_TYPE_WORKSTATION and SV_TYPE_SERVER
  62. /// PC's in the Domain</returns>
  63. public IEnumerable<string> GetNetworkDevices()
  64. {
  65. //local fields
  66. const int MAX_PREFERRED_LENGTH = -1;
  67. var SV_TYPE_WORKSTATION = 1;
  68. var SV_TYPE_SERVER = 2;
  69. var buffer = IntPtr.Zero;
  70. var tmpBuffer = IntPtr.Zero;
  71. var entriesRead = 0;
  72. var totalEntries = 0;
  73. var resHandle = 0;
  74. var sizeofINFO = Marshal.SizeOf(typeof(_SERVER_INFO_100));
  75. try
  76. {
  77. //call the DllImport : NetServerEnum with all its required parameters
  78. //see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/netmgmt/netmgmt/netserverenum.asp
  79. //for full details of method signature
  80. var ret = NativeMethods.NetServerEnum(null, 100, ref buffer, MAX_PREFERRED_LENGTH, out entriesRead, out totalEntries, SV_TYPE_WORKSTATION | SV_TYPE_SERVER, null, out resHandle);
  81. //if the returned with a NERR_Success (C++ term), =0 for C#
  82. if (ret == 0)
  83. {
  84. //loop through all SV_TYPE_WORKSTATION and SV_TYPE_SERVER PC's
  85. for (var i = 0; i < totalEntries; i++)
  86. {
  87. //get pointer to, Pointer to the buffer that received the data from
  88. //the call to NetServerEnum. Must ensure to use correct size of
  89. //STRUCTURE to ensure correct location in memory is pointed to
  90. tmpBuffer = new IntPtr((int)buffer + (i * sizeofINFO));
  91. //Have now got a pointer to the list of SV_TYPE_WORKSTATION and
  92. //SV_TYPE_SERVER PC's, which is unmanaged memory
  93. //Needs to Marshal data from an unmanaged block of memory to a
  94. //managed object, again using STRUCTURE to ensure the correct data
  95. //is marshalled
  96. var svrInfo = (_SERVER_INFO_100)Marshal.PtrToStructure(tmpBuffer, typeof(_SERVER_INFO_100));
  97. //add the PC names to the ArrayList
  98. if (!string.IsNullOrEmpty(svrInfo.sv100_name))
  99. {
  100. yield return svrInfo.sv100_name;
  101. }
  102. }
  103. }
  104. }
  105. finally
  106. {
  107. //The NetApiBufferFree function frees
  108. //the memory that the NetApiBufferAllocate function allocates
  109. NativeMethods.NetApiBufferFree(buffer);
  110. }
  111. }
  112. /// <summary>
  113. /// Gets the network shares.
  114. /// </summary>
  115. /// <param name="path">The path.</param>
  116. /// <returns>IEnumerable{NetworkShare}.</returns>
  117. public IEnumerable<NetworkShare> GetNetworkShares(string path)
  118. {
  119. return new ShareCollection(path).OfType<Share>().Select(ToNetworkShare);
  120. }
  121. /// <summary>
  122. /// To the network share.
  123. /// </summary>
  124. /// <param name="share">The share.</param>
  125. /// <returns>NetworkShare.</returns>
  126. private NetworkShare ToNetworkShare(Share share)
  127. {
  128. return new NetworkShare
  129. {
  130. Name = share.NetName,
  131. Path = share.Path,
  132. Remark = share.Remark,
  133. Server = share.Server,
  134. ShareType = ToNetworkShareType(share.ShareType)
  135. };
  136. }
  137. /// <summary>
  138. /// To the type of the network share.
  139. /// </summary>
  140. /// <param name="shareType">Type of the share.</param>
  141. /// <returns>NetworkShareType.</returns>
  142. /// <exception cref="System.ArgumentException">Unknown share type</exception>
  143. private NetworkShareType ToNetworkShareType(ShareType shareType)
  144. {
  145. if (shareType.HasFlag(ShareType.Special))
  146. {
  147. return NetworkShareType.Special;
  148. }
  149. if (shareType.HasFlag(ShareType.Device))
  150. {
  151. return NetworkShareType.Device;
  152. }
  153. if (shareType.HasFlag(ShareType.Disk))
  154. {
  155. return NetworkShareType.Disk;
  156. }
  157. if (shareType.HasFlag(ShareType.IPC))
  158. {
  159. return NetworkShareType.Ipc;
  160. }
  161. if (shareType.HasFlag(ShareType.Printer))
  162. {
  163. return NetworkShareType.Printer;
  164. }
  165. throw new ArgumentException("Unknown share type");
  166. }
  167. /// <summary>
  168. /// Parses the specified endpointstring.
  169. /// </summary>
  170. /// <param name="endpointstring">The endpointstring.</param>
  171. /// <returns>IPEndPoint.</returns>
  172. public IPEndPoint Parse(string endpointstring)
  173. {
  174. return Parse(endpointstring, -1);
  175. }
  176. /// <summary>
  177. /// Parses the specified endpointstring.
  178. /// </summary>
  179. /// <param name="endpointstring">The endpointstring.</param>
  180. /// <param name="defaultport">The defaultport.</param>
  181. /// <returns>IPEndPoint.</returns>
  182. /// <exception cref="System.ArgumentException">Endpoint descriptor may not be empty.</exception>
  183. /// <exception cref="System.FormatException"></exception>
  184. private static IPEndPoint Parse(string endpointstring, int defaultport)
  185. {
  186. if (string.IsNullOrEmpty(endpointstring)
  187. || endpointstring.Trim().Length == 0)
  188. {
  189. throw new ArgumentException("Endpoint descriptor may not be empty.");
  190. }
  191. if (defaultport != -1 &&
  192. (defaultport < IPEndPoint.MinPort
  193. || defaultport > IPEndPoint.MaxPort))
  194. {
  195. throw new ArgumentException(string.Format("Invalid default port '{0}'", defaultport));
  196. }
  197. string[] values = endpointstring.Split(new char[] { ':' });
  198. IPAddress ipaddy;
  199. int port = -1;
  200. //check if we have an IPv6 or ports
  201. if (values.Length <= 2) // ipv4 or hostname
  202. {
  203. port = values.Length == 1 ? defaultport : GetPort(values[1]);
  204. //try to use the address as IPv4, otherwise get hostname
  205. if (!IPAddress.TryParse(values[0], out ipaddy))
  206. ipaddy = GetIPfromHost(values[0]);
  207. }
  208. else if (values.Length > 2) //ipv6
  209. {
  210. //could [a:b:c]:d
  211. if (values[0].StartsWith("[") && values[values.Length - 2].EndsWith("]"))
  212. {
  213. string ipaddressstring = string.Join(":", values.Take(values.Length - 1).ToArray());
  214. ipaddy = IPAddress.Parse(ipaddressstring);
  215. port = GetPort(values[values.Length - 1]);
  216. }
  217. else //[a:b:c] or a:b:c
  218. {
  219. ipaddy = IPAddress.Parse(endpointstring);
  220. port = defaultport;
  221. }
  222. }
  223. else
  224. {
  225. throw new FormatException(string.Format("Invalid endpoint ipaddress '{0}'", endpointstring));
  226. }
  227. if (port == -1)
  228. throw new ArgumentException(string.Format("No port specified: '{0}'", endpointstring));
  229. return new IPEndPoint(ipaddy, port);
  230. }
  231. protected static readonly CultureInfo UsCulture = new CultureInfo("en-US");
  232. /// <summary>
  233. /// Gets the port.
  234. /// </summary>
  235. /// <param name="p">The p.</param>
  236. /// <returns>System.Int32.</returns>
  237. /// <exception cref="System.FormatException"></exception>
  238. private static int GetPort(string p)
  239. {
  240. int port;
  241. if (!int.TryParse(p, out port)
  242. || port < IPEndPoint.MinPort
  243. || port > IPEndPoint.MaxPort)
  244. {
  245. throw new FormatException(string.Format("Invalid end point port '{0}'", p));
  246. }
  247. return port;
  248. }
  249. /// <summary>
  250. /// Gets the I pfrom host.
  251. /// </summary>
  252. /// <param name="p">The p.</param>
  253. /// <returns>IPAddress.</returns>
  254. /// <exception cref="System.ArgumentException"></exception>
  255. private static IPAddress GetIPfromHost(string p)
  256. {
  257. var hosts = Dns.GetHostAddresses(p);
  258. if (hosts == null || hosts.Length == 0)
  259. throw new ArgumentException(string.Format("Host not found: {0}", p));
  260. return hosts[0];
  261. }
  262. }
  263. }