From ddd1a282ea6398ee26d74321338d0445d0a0c796 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Sun, 7 Jul 2019 21:03:26 +0200 Subject: Remove IpAddressInfo and IpEndPointInfo classes --- Emby.Server.Implementations/Net/SocketFactory.cs | 14 +++++------ Emby.Server.Implementations/Net/UdpSocket.cs | 30 +++++++----------------- 2 files changed, 15 insertions(+), 29 deletions(-) (limited to 'Emby.Server.Implementations/Net') diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index 492f48abe..42ffa4e22 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -16,14 +16,14 @@ namespace Emby.Server.Implementations.Net // but that wasn't really the point so kept to YAGNI principal for now, even if the // interfaces are a bit ugly, specific and make assumptions. - public ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort) + public ISocket CreateTcpSocket(IPAddress remoteAddress, int remotePort) { if (remotePort < 0) { throw new ArgumentException("remotePort cannot be less than zero.", nameof(remotePort)); } - var addressFamily = remoteAddress.AddressFamily == IpAddressFamily.InterNetwork + var addressFamily = remoteAddress.AddressFamily == AddressFamily.InterNetwork ? AddressFamily.InterNetwork : AddressFamily.InterNetworkV6; @@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.Net try { - return new UdpSocket(retVal, new IpEndPointInfo(remoteAddress, remotePort)); + return new UdpSocket(retVal, new IPEndPoint(remoteAddress, remotePort)); } catch { @@ -102,7 +102,7 @@ namespace Emby.Server.Implementations.Net /// Creates a new UDP acceptSocket that is a member of the SSDP multicast local admin group and binds it to the specified local port. /// /// An implementation of the interface used by RSSDP components to perform acceptSocket operations. - public ISocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort) + public ISocket CreateSsdpUdpSocket(IPAddress localIpAddress, int localPort) { if (localPort < 0) { @@ -115,10 +115,8 @@ namespace Emby.Server.Implementations.Net retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); - var localIp = NetworkManager.ToIPAddress(localIpAddress); - - retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIp)); - return new UdpSocket(retVal, localPort, localIp); + retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), localIpAddress)); + return new UdpSocket(retVal, localPort, localIpAddress); } catch { diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs index 6c55085c8..2908ee9af 100644 --- a/Emby.Server.Implementations/Net/UdpSocket.cs +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -19,7 +19,7 @@ namespace Emby.Server.Implementations.Net public Socket Socket => _socket; - public IpAddressInfo LocalIPAddress { get; } + public IPAddress LocalIPAddress { get; } private readonly SocketAsyncEventArgs _receiveSocketAsyncEventArgs = new SocketAsyncEventArgs() { @@ -40,7 +40,7 @@ namespace Emby.Server.Implementations.Net _socket = socket; _localPort = localPort; - LocalIPAddress = NetworkManager.ToIpAddressInfo(ip); + LocalIPAddress = ip; _socket.Bind(new IPEndPoint(ip, _localPort)); @@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.Net { Buffer = e.Buffer, ReceivedBytes = e.BytesTransferred, - RemoteEndPoint = ToIpEndPointInfo(e.RemoteEndPoint as IPEndPoint), + RemoteEndPoint = e.RemoteEndPoint as IPEndPoint, LocalIPAddress = LocalIPAddress }); } @@ -100,12 +100,12 @@ namespace Emby.Server.Implementations.Net } } - public UdpSocket(Socket socket, IpEndPointInfo endPoint) + public UdpSocket(Socket socket, IPEndPoint endPoint) { if (socket == null) throw new ArgumentNullException(nameof(socket)); _socket = socket; - _socket.Connect(NetworkManager.ToIPEndPoint(endPoint)); + _socket.Connect(endPoint); InitReceiveSocketAsyncEventArgs(); } @@ -140,7 +140,7 @@ namespace Emby.Server.Implementations.Net return new SocketReceiveResult { ReceivedBytes = receivedBytes, - RemoteEndPoint = ToIpEndPointInfo((IPEndPoint)remoteEndPoint), + RemoteEndPoint = (IPEndPoint)remoteEndPoint, Buffer = buffer, LocalIPAddress = LocalIPAddress }; @@ -191,7 +191,7 @@ namespace Emby.Server.Implementations.Net return ReceiveAsync(buffer, 0, buffer.Length, cancellationToken); } - public Task SendToAsync(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, CancellationToken cancellationToken) + public Task SendToAsync(byte[] buffer, int offset, int size, IPEndPoint endPoint, CancellationToken cancellationToken) { ThrowIfDisposed(); @@ -227,13 +227,11 @@ namespace Emby.Server.Implementations.Net return taskCompletion.Task; } - public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, IpEndPointInfo endPoint, AsyncCallback callback, object state) + public IAsyncResult BeginSendTo(byte[] buffer, int offset, int size, IPEndPoint endPoint, AsyncCallback callback, object state) { ThrowIfDisposed(); - var ipEndPoint = NetworkManager.ToIPEndPoint(endPoint); - - return _socket.BeginSendTo(buffer, offset, size, SocketFlags.None, ipEndPoint, callback, state); + return _socket.BeginSendTo(buffer, offset, size, SocketFlags.None, endPoint, callback, state); } public int EndSendTo(IAsyncResult result) @@ -268,15 +266,5 @@ namespace Emby.Server.Implementations.Net _disposed = true; } - - private static IpEndPointInfo ToIpEndPointInfo(IPEndPoint endpoint) - { - if (endpoint == null) - { - return null; - } - - return NetworkManager.ToIpEndPointInfo(endpoint); - } } } -- cgit v1.2.3 From 998017a76d7e0fcc340bf9dbc3436caef583f6b4 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 29 Jul 2019 16:01:14 +0200 Subject: Include library via NuGet instead of via source --- .../Emby.Server.Implementations.csproj | 1 + Emby.Server.Implementations/Net/UdpSocket.cs | 1 - .../Networking/IPNetwork/BigIntegerExt.cs | 167 -- .../Networking/IPNetwork/IPAddressCollection.cs | 94 - .../Networking/IPNetwork/IPNetwork.cs | 2008 -------------------- .../Networking/IPNetwork/IPNetworkCollection.cs | 129 -- .../Networking/IPNetwork/LICENSE.txt | 24 - .../Networking/NetworkManager.cs | 2 +- 8 files changed, 2 insertions(+), 2424 deletions(-) delete mode 100644 Emby.Server.Implementations/Networking/IPNetwork/BigIntegerExt.cs delete mode 100644 Emby.Server.Implementations/Networking/IPNetwork/IPAddressCollection.cs delete mode 100644 Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs delete mode 100644 Emby.Server.Implementations/Networking/IPNetwork/IPNetworkCollection.cs delete mode 100644 Emby.Server.Implementations/Networking/IPNetwork/LICENSE.txt (limited to 'Emby.Server.Implementations/Net') diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj index 49015a07e..abbaef26b 100644 --- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj +++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj @@ -20,6 +20,7 @@ + diff --git a/Emby.Server.Implementations/Net/UdpSocket.cs b/Emby.Server.Implementations/Net/UdpSocket.cs index 2908ee9af..dde4a2a34 100644 --- a/Emby.Server.Implementations/Net/UdpSocket.cs +++ b/Emby.Server.Implementations/Net/UdpSocket.cs @@ -3,7 +3,6 @@ using System.Net; using System.Net.Sockets; using System.Threading; using System.Threading.Tasks; -using Emby.Server.Implementations.Networking; using MediaBrowser.Model.Net; namespace Emby.Server.Implementations.Net diff --git a/Emby.Server.Implementations/Networking/IPNetwork/BigIntegerExt.cs b/Emby.Server.Implementations/Networking/IPNetwork/BigIntegerExt.cs deleted file mode 100644 index e4e944839..000000000 --- a/Emby.Server.Implementations/Networking/IPNetwork/BigIntegerExt.cs +++ /dev/null @@ -1,167 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Numerics; -using System.Text; - -namespace Emby.Server.Implementations.Networking.IPNetwork -{ - /// - /// Extension methods to convert - /// instances to hexadecimal, octal, and binary strings. - /// - public static class BigIntegerExtensions - { - /// - /// Converts a to a binary string. - /// - /// A . - /// - /// A containing a binary - /// representation of the supplied . - /// - public static string ToBinaryString(this BigInteger bigint) - { - var bytes = bigint.ToByteArray(); - var idx = bytes.Length - 1; - - // Create a StringBuilder having appropriate capacity. - var base2 = new StringBuilder(bytes.Length * 8); - - // Convert first byte to binary. - var binary = Convert.ToString(bytes[idx], 2); - - // Ensure leading zero exists if value is positive. - if (binary[0] != '0' && bigint.Sign == 1) - { - base2.Append('0'); - } - - // Append binary string to StringBuilder. - base2.Append(binary); - - // Convert remaining bytes adding leading zeros. - for (idx--; idx >= 0; idx--) - { - base2.Append(Convert.ToString(bytes[idx], 2).PadLeft(8, '0')); - } - - return base2.ToString(); - } - - /// - /// Converts a to a hexadecimal string. - /// - /// A . - /// - /// A containing a hexadecimal - /// representation of the supplied . - /// - public static string ToHexadecimalString(this BigInteger bigint) - { - return bigint.ToString("X"); - } - - /// - /// Converts a to a octal string. - /// - /// A . - /// - /// A containing an octal - /// representation of the supplied . - /// - public static string ToOctalString(this BigInteger bigint) - { - var bytes = bigint.ToByteArray(); - var idx = bytes.Length - 1; - - // Create a StringBuilder having appropriate capacity. - var base8 = new StringBuilder(((bytes.Length / 3) + 1) * 8); - - // Calculate how many bytes are extra when byte array is split - // into three-byte (24-bit) chunks. - var extra = bytes.Length % 3; - - // If no bytes are extra, use three bytes for first chunk. - if (extra == 0) - { - extra = 3; - } - - // Convert first chunk (24-bits) to integer value. - int int24 = 0; - for (; extra != 0; extra--) - { - int24 <<= 8; - int24 += bytes[idx--]; - } - - // Convert 24-bit integer to octal without adding leading zeros. - var octal = Convert.ToString(int24, 8); - - // Ensure leading zero exists if value is positive. - if (octal[0] != '0') - { - if (bigint.Sign == 1) - { - base8.Append('0'); - } - } - - // Append first converted chunk to StringBuilder. - base8.Append(octal); - - // Convert remaining 24-bit chunks, adding leading zeros. - for (; idx >= 0; idx -= 3) - { - int24 = (bytes[idx] << 16) + (bytes[idx - 1] << 8) + bytes[idx - 2]; - base8.Append(Convert.ToString(int24, 8).PadLeft(8, '0')); - } - - return base8.ToString(); - } - - /// - /// - /// Reverse a Positive BigInteger ONLY - /// Bitwise ~ operator - /// - /// Input : FF FF FF FF - /// Width : 4 - /// Result : 00 00 00 00 - /// - /// - /// Input : 00 00 00 00 - /// Width : 4 - /// Result : FF FF FF FF - /// - /// Input : FF FF FF FF - /// Width : 8 - /// Result : FF FF FF FF 00 00 00 00 - /// - /// - /// Input : 00 00 00 00 - /// Width : 8 - /// Result : FF FF FF FF FF FF FF FF - /// - /// - /// - /// - /// - public static BigInteger PositiveReverse(this BigInteger input, int width) - { - - var result = new List(); - var bytes = input.ToByteArray(); - var work = new byte[width]; - Array.Copy(bytes, 0, work, 0, bytes.Length - 1); // Length -1 : positive BigInteger - - for (int i = 0; i < work.Length; i++) - { - result.Add((byte)(~work[i])); - } - result.Add(0); // positive BigInteger - return new BigInteger(result.ToArray()); - - } - } -} diff --git a/Emby.Server.Implementations/Networking/IPNetwork/IPAddressCollection.cs b/Emby.Server.Implementations/Networking/IPNetwork/IPAddressCollection.cs deleted file mode 100644 index a0c5f73af..000000000 --- a/Emby.Server.Implementations/Networking/IPNetwork/IPAddressCollection.cs +++ /dev/null @@ -1,94 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Net; -using System.Numerics; - -namespace Emby.Server.Implementations.Networking.IPNetwork -{ - public class IPAddressCollection : IEnumerable, IEnumerator - { - - private IPNetwork _ipnetwork; - private BigInteger _enumerator; - - internal IPAddressCollection(IPNetwork ipnetwork) - { - this._ipnetwork = ipnetwork; - this._enumerator = -1; - } - - - #region Count, Array, Enumerator - - public BigInteger Count => this._ipnetwork.Total; - - public IPAddress this[BigInteger i] - { - get - { - if (i >= this.Count) - { - throw new ArgumentOutOfRangeException(nameof(i)); - } - byte width = this._ipnetwork.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? (byte)32 : (byte)128; - var ipn = this._ipnetwork.Subnet(width); - return ipn[i].Network; - } - } - - #endregion - - #region IEnumerable Members - - IEnumerator IEnumerable.GetEnumerator() - { - return this; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return this; - } - - #region IEnumerator Members - - public IPAddress Current => this[this._enumerator]; - - #endregion - - #region IDisposable Members - - public void Dispose() - { - // nothing to dispose - return; - } - - #endregion - - #region IEnumerator Members - - object IEnumerator.Current => this.Current; - - public bool MoveNext() - { - this._enumerator++; - if (this._enumerator >= this.Count) - { - return false; - } - return true; - - } - - public void Reset() - { - this._enumerator = -1; - } - - #endregion - - #endregion - } -} diff --git a/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs b/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs deleted file mode 100644 index d6de61c0c..000000000 --- a/Emby.Server.Implementations/Networking/IPNetwork/IPNetwork.cs +++ /dev/null @@ -1,2008 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Numerics; -using System.Text.RegularExpressions; - -namespace Emby.Server.Implementations.Networking.IPNetwork -{ - /// - /// IP Network utility class. - /// Use IPNetwork.Parse to create instances. - /// - public class IPNetwork : IComparable - { - - #region properties - - //private uint _network; - private BigInteger _ipaddress; - private AddressFamily _family; - //private uint _netmask; - //private uint _broadcast; - //private uint _firstUsable; - //private uint _lastUsable; - //private uint _usable; - private byte _cidr; - - #endregion - - #region accessors - - private BigInteger _network - { - get - { - var uintNetwork = this._ipaddress & this._netmask; - return uintNetwork; - } - } - - /// - /// Network address - /// - public IPAddress Network => IPNetwork.ToIPAddress(this._network, this._family); - - /// - /// Address Family - /// - public AddressFamily AddressFamily => this._family; - - private BigInteger _netmask => IPNetwork.ToUint(this._cidr, this._family); - - /// - /// Netmask - /// - public IPAddress Netmask => IPNetwork.ToIPAddress(this._netmask, this._family); - - private BigInteger _broadcast - { - get - { - - int width = this._family == System.Net.Sockets.AddressFamily.InterNetwork ? 4 : 16; - var uintBroadcast = this._network + this._netmask.PositiveReverse(width); - return uintBroadcast; - } - } - - /// - /// Broadcast address - /// - public IPAddress Broadcast - { - get - { - if (this._family == System.Net.Sockets.AddressFamily.InterNetworkV6) - { - return null; - } - return IPNetwork.ToIPAddress(this._broadcast, this._family); - } - } - - /// - /// First usable IP adress in Network - /// - public IPAddress FirstUsable - { - get - { - var fisrt = this._family == System.Net.Sockets.AddressFamily.InterNetworkV6 - ? this._network - : (this.Usable <= 0) ? this._network : this._network + 1; - return IPNetwork.ToIPAddress(fisrt, this._family); - } - } - - /// - /// Last usable IP adress in Network - /// - public IPAddress LastUsable - { - get - { - var last = this._family == System.Net.Sockets.AddressFamily.InterNetworkV6 - ? this._broadcast - : (this.Usable <= 0) ? this._network : this._broadcast - 1; - return IPNetwork.ToIPAddress(last, this._family); - } - } - - /// - /// Number of usable IP adress in Network - /// - public BigInteger Usable - { - get - { - - if (this._family == System.Net.Sockets.AddressFamily.InterNetworkV6) - { - return this.Total; - } - byte[] mask = new byte[] { 0xff, 0xff, 0xff, 0xff, 0x00 }; - var bmask = new BigInteger(mask); - var usableIps = (_cidr > 30) ? 0 : ((bmask >> _cidr) - 1); - return usableIps; - } - } - - /// - /// Number of IP adress in Network - /// - public BigInteger Total - { - get - { - - int max = this._family == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; - var count = BigInteger.Pow(2, (max - _cidr)); - return count; - } - } - - - /// - /// The CIDR netmask notation - /// - public byte Cidr => this._cidr; - - #endregion - - #region constructor - -#if TRAVISCI - public -#else - internal -#endif - - IPNetwork(BigInteger ipaddress, AddressFamily family, byte cidr) - { - - int maxCidr = family == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; - if (cidr > maxCidr) - { - throw new ArgumentOutOfRangeException(nameof(cidr)); - } - - this._ipaddress = ipaddress; - this._family = family; - this._cidr = cidr; - - } - - #endregion - - #region parsers - - /// - /// 192.168.168.100 - 255.255.255.0 - /// - /// Network : 192.168.168.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.168.1 - /// End : 192.168.168.254 - /// Broadcast : 192.168.168.255 - /// - /// - /// - /// - public static IPNetwork Parse(string ipaddress, string netmask) - { - - IPNetwork ipnetwork = null; - IPNetwork.InternalParse(false, ipaddress, netmask, out ipnetwork); - return ipnetwork; - } - - /// - /// 192.168.168.100/24 - /// - /// Network : 192.168.168.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.168.1 - /// End : 192.168.168.254 - /// Broadcast : 192.168.168.255 - /// - /// - /// - /// - public static IPNetwork Parse(string ipaddress, byte cidr) - { - - IPNetwork ipnetwork = null; - IPNetwork.InternalParse(false, ipaddress, cidr, out ipnetwork); - return ipnetwork; - - } - - /// - /// 192.168.168.100 255.255.255.0 - /// - /// Network : 192.168.168.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.168.1 - /// End : 192.168.168.254 - /// Broadcast : 192.168.168.255 - /// - /// - /// - /// - public static IPNetwork Parse(IPAddress ipaddress, IPAddress netmask) - { - - IPNetwork ipnetwork = null; - IPNetwork.InternalParse(false, ipaddress, netmask, out ipnetwork); - return ipnetwork; - - } - - /// - /// 192.168.0.1/24 - /// 192.168.0.1 255.255.255.0 - /// - /// Network : 192.168.0.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.0.1 - /// End : 192.168.0.254 - /// Broadcast : 192.168.0.255 - /// - /// - /// - public static IPNetwork Parse(string network) - { - - IPNetwork ipnetwork = null; - IPNetwork.InternalParse(false, network, out ipnetwork); - return ipnetwork; - - } - - #endregion - - #region TryParse - - - - /// - /// 192.168.168.100 - 255.255.255.0 - /// - /// Network : 192.168.168.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.168.1 - /// End : 192.168.168.254 - /// Broadcast : 192.168.168.255 - /// - /// - /// - /// - public static bool TryParse(string ipaddress, string netmask, out IPNetwork ipnetwork) - { - - IPNetwork ipnetwork2 = null; - IPNetwork.InternalParse(true, ipaddress, netmask, out ipnetwork2); - bool parsed = (ipnetwork2 != null); - ipnetwork = ipnetwork2; - return parsed; - - } - - - - /// - /// 192.168.168.100/24 - /// - /// Network : 192.168.168.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.168.1 - /// End : 192.168.168.254 - /// Broadcast : 192.168.168.255 - /// - /// - /// - /// - public static bool TryParse(string ipaddress, byte cidr, out IPNetwork ipnetwork) - { - - IPNetwork ipnetwork2 = null; - IPNetwork.InternalParse(true, ipaddress, cidr, out ipnetwork2); - bool parsed = (ipnetwork2 != null); - ipnetwork = ipnetwork2; - return parsed; - - } - - /// - /// 192.168.0.1/24 - /// 192.168.0.1 255.255.255.0 - /// - /// Network : 192.168.0.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.0.1 - /// End : 192.168.0.254 - /// Broadcast : 192.168.0.255 - /// - /// - /// - /// - public static bool TryParse(string network, out IPNetwork ipnetwork) - { - - IPNetwork ipnetwork2 = null; - IPNetwork.InternalParse(true, network, out ipnetwork2); - bool parsed = (ipnetwork2 != null); - ipnetwork = ipnetwork2; - return parsed; - - } - - /// - /// 192.168.0.1/24 - /// 192.168.0.1 255.255.255.0 - /// - /// Network : 192.168.0.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.0.1 - /// End : 192.168.0.254 - /// Broadcast : 192.168.0.255 - /// - /// - /// - /// - /// - public static bool TryParse(IPAddress ipaddress, IPAddress netmask, out IPNetwork ipnetwork) - { - - IPNetwork ipnetwork2 = null; - IPNetwork.InternalParse(true, ipaddress, netmask, out ipnetwork2); - bool parsed = (ipnetwork2 != null); - ipnetwork = ipnetwork2; - return parsed; - - } - - - #endregion - - #region InternalParse - - /// - /// 192.168.168.100 - 255.255.255.0 - /// - /// Network : 192.168.168.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.168.1 - /// End : 192.168.168.254 - /// Broadcast : 192.168.168.255 - /// - /// - /// - /// - private static void InternalParse(bool tryParse, string ipaddress, string netmask, out IPNetwork ipnetwork) - { - - if (string.IsNullOrEmpty(ipaddress)) - { - if (tryParse == false) - { - throw new ArgumentNullException(nameof(ipaddress)); - } - ipnetwork = null; - return; - } - - if (string.IsNullOrEmpty(netmask)) - { - if (tryParse == false) - { - throw new ArgumentNullException(nameof(netmask)); - } - ipnetwork = null; - return; - } - - IPAddress ip = null; - bool ipaddressParsed = IPAddress.TryParse(ipaddress, out ip); - if (ipaddressParsed == false) - { - if (tryParse == false) - { - throw new ArgumentException("ipaddress"); - } - ipnetwork = null; - return; - } - - IPAddress mask = null; - bool netmaskParsed = IPAddress.TryParse(netmask, out mask); - if (netmaskParsed == false) - { - if (tryParse == false) - { - throw new ArgumentException("netmask"); - } - ipnetwork = null; - return; - } - - IPNetwork.InternalParse(tryParse, ip, mask, out ipnetwork); - } - - private static void InternalParse(bool tryParse, string network, out IPNetwork ipnetwork) - { - - if (string.IsNullOrEmpty(network)) - { - if (tryParse == false) - { - throw new ArgumentNullException(nameof(network)); - } - ipnetwork = null; - return; - } - - network = Regex.Replace(network, @"[^0-9a-fA-F\.\/\s\:]+", ""); - network = Regex.Replace(network, @"\s{2,}", " "); - network = network.Trim(); - string[] args = network.Split(new char[] { ' ', '/' }); - byte cidr = 0; - if (args.Length == 1) - { - - if (IPNetwork.TryGuessCidr(args[0], out cidr)) - { - IPNetwork.InternalParse(tryParse, args[0], cidr, out ipnetwork); - return; - } - - if (tryParse == false) - { - throw new ArgumentException("network"); - } - ipnetwork = null; - return; - } - - if (byte.TryParse(args[1], out cidr)) - { - IPNetwork.InternalParse(tryParse, args[0], cidr, out ipnetwork); - return; - } - - IPNetwork.InternalParse(tryParse, args[0], args[1], out ipnetwork); - return; - - } - - - - /// - /// 192.168.168.100 255.255.255.0 - /// - /// Network : 192.168.168.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.168.1 - /// End : 192.168.168.254 - /// Broadcast : 192.168.168.255 - /// - /// - /// - /// - private static void InternalParse(bool tryParse, IPAddress ipaddress, IPAddress netmask, out IPNetwork ipnetwork) - { - - if (ipaddress == null) - { - if (tryParse == false) - { - throw new ArgumentNullException(nameof(ipaddress)); - } - ipnetwork = null; - return; - } - - if (netmask == null) - { - if (tryParse == false) - { - throw new ArgumentNullException(nameof(netmask)); - } - ipnetwork = null; - return; - } - - var uintIpAddress = IPNetwork.ToBigInteger(ipaddress); - bool parsed = IPNetwork.TryToCidr(netmask, out var cidr2); - if (parsed == false) - { - if (tryParse == false) - { - throw new ArgumentException("netmask"); - } - ipnetwork = null; - return; - } - byte cidr = (byte)cidr2; - - var ipnet = new IPNetwork(uintIpAddress, ipaddress.AddressFamily, cidr); - ipnetwork = ipnet; - - return; - } - - - - /// - /// 192.168.168.100/24 - /// - /// Network : 192.168.168.0 - /// Netmask : 255.255.255.0 - /// Cidr : 24 - /// Start : 192.168.168.1 - /// End : 192.168.168.254 - /// Broadcast : 192.168.168.255 - /// - /// - /// - /// - private static void InternalParse(bool tryParse, string ipaddress, byte cidr, out IPNetwork ipnetwork) - { - - if (string.IsNullOrEmpty(ipaddress)) - { - if (tryParse == false) - { - throw new ArgumentNullException(nameof(ipaddress)); - } - ipnetwork = null; - return; - } - - - IPAddress ip = null; - bool ipaddressParsed = IPAddress.TryParse(ipaddress, out ip); - if (ipaddressParsed == false) - { - if (tryParse == false) - { - throw new ArgumentException("ipaddress"); - } - ipnetwork = null; - return; - } - - IPAddress mask = null; - bool parsedNetmask = IPNetwork.TryToNetmask(cidr, ip.AddressFamily, out mask); - if (parsedNetmask == false) - { - if (tryParse == false) - { - throw new ArgumentException("cidr"); - } - ipnetwork = null; - return; - } - - - IPNetwork.InternalParse(tryParse, ip, mask, out ipnetwork); - } - - #endregion - - #region converters - - #region ToUint - - /// - /// Convert an ipadress to decimal - /// 0.0.0.0 -> 0 - /// 0.0.1.0 -> 256 - /// - /// - /// - public static BigInteger ToBigInteger(IPAddress ipaddress) - { - IPNetwork.InternalToBigInteger(false, ipaddress, out var uintIpAddress); - return (BigInteger)uintIpAddress; - - } - - /// - /// Convert an ipadress to decimal - /// 0.0.0.0 -> 0 - /// 0.0.1.0 -> 256 - /// - /// - /// - public static bool TryToBigInteger(IPAddress ipaddress, out BigInteger? uintIpAddress) - { - IPNetwork.InternalToBigInteger(true, ipaddress, out var uintIpAddress2); - bool parsed = (uintIpAddress2 != null); - uintIpAddress = uintIpAddress2; - return parsed; - } - -#if TRAVISCI - public -#else - internal -#endif - static void InternalToBigInteger(bool tryParse, IPAddress ipaddress, out BigInteger? uintIpAddress) - { - - if (ipaddress == null) - { - if (tryParse == false) - { - throw new ArgumentNullException(nameof(ipaddress)); - } - uintIpAddress = null; - return; - } - - byte[] bytes = ipaddress.GetAddressBytes(); - /// 20180217 lduchosal - /// code impossible to reach, GetAddressBytes returns either 4 or 16 bytes length addresses - /// if (bytes.Length != 4 && bytes.Length != 16) { - /// if (tryParse == false) { - /// throw new ArgumentException("bytes"); - /// } - /// uintIpAddress = null; - /// return; - /// } - - Array.Reverse(bytes); - var unsigned = new List(bytes); - unsigned.Add(0); - uintIpAddress = new BigInteger(unsigned.ToArray()); - return; - } - - - /// - /// Convert a cidr to BigInteger netmask - /// - /// - /// - public static BigInteger ToUint(byte cidr, AddressFamily family) - { - IPNetwork.InternalToBigInteger(false, cidr, family, out var uintNetmask); - return (BigInteger)uintNetmask; - } - - - /// - /// Convert a cidr to uint netmask - /// - /// - /// - public static bool TryToUint(byte cidr, AddressFamily family, out BigInteger? uintNetmask) - { - IPNetwork.InternalToBigInteger(true, cidr, family, out var uintNetmask2); - bool parsed = (uintNetmask2 != null); - uintNetmask = uintNetmask2; - return parsed; - } - - /// - /// Convert a cidr to uint netmask - /// - /// - /// -#if TRAVISCI - public -#else - internal -#endif - static void InternalToBigInteger(bool tryParse, byte cidr, AddressFamily family, out BigInteger? uintNetmask) - { - - if (family == AddressFamily.InterNetwork && cidr > 32) - { - if (tryParse == false) - { - throw new ArgumentOutOfRangeException(nameof(cidr)); - } - uintNetmask = null; - return; - } - - if (family == AddressFamily.InterNetworkV6 && cidr > 128) - { - if (tryParse == false) - { - throw new ArgumentOutOfRangeException(nameof(cidr)); - } - uintNetmask = null; - return; - } - - if (family != AddressFamily.InterNetwork - && family != AddressFamily.InterNetworkV6) - { - if (tryParse == false) - { - throw new NotSupportedException(family.ToString()); - } - uintNetmask = null; - return; - } - - if (family == AddressFamily.InterNetwork) - { - - uintNetmask = cidr == 0 ? 0 : 0xffffffff << (32 - cidr); - return; - } - - var mask = new BigInteger(new byte[] { - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x00 - }); - - var masked = cidr == 0 ? 0 : mask << (128 - cidr); - byte[] m = masked.ToByteArray(); - byte[] bmask = new byte[17]; - int copy = m.Length > 16 ? 16 : m.Length; - Array.Copy(m, 0, bmask, 0, copy); - uintNetmask = new BigInteger(bmask); - - - } - - #endregion - - #region ToCidr - - /// - /// Convert netmask to CIDR - /// 255.255.255.0 -> 24 - /// 255.255.0.0 -> 16 - /// 255.0.0.0 -> 8 - /// - /// - /// - private static void InternalToCidr(bool tryParse, BigInteger netmask, AddressFamily family, out byte? cidr) - { - - if (!IPNetwork.InternalValidNetmask(netmask, family)) - { - if (tryParse == false) - { - throw new ArgumentException("netmask"); - } - cidr = null; - return; - } - - byte cidr2 = IPNetwork.BitsSet(netmask, family); - cidr = cidr2; - return; - - } - /// - /// Convert netmask to CIDR - /// 255.255.255.0 -> 24 - /// 255.255.0.0 -> 16 - /// 255.0.0.0 -> 8 - /// - /// - /// - public static byte ToCidr(IPAddress netmask) - { - IPNetwork.InternalToCidr(false, netmask, out var cidr); - return (byte)cidr; - } - - /// - /// Convert netmask to CIDR - /// 255.255.255.0 -> 24 - /// 255.255.0.0 -> 16 - /// 255.0.0.0 -> 8 - /// - /// - /// - public static bool TryToCidr(IPAddress netmask, out byte? cidr) - { - IPNetwork.InternalToCidr(true, netmask, out var cidr2); - bool parsed = (cidr2 != null); - cidr = cidr2; - return parsed; - } - - private static void InternalToCidr(bool tryParse, IPAddress netmask, out byte? cidr) - { - - if (netmask == null) - { - if (tryParse == false) - { - throw new ArgumentNullException(nameof(netmask)); - } - cidr = null; - return; - } - - bool parsed = IPNetwork.TryToBigInteger(netmask, out var uintNetmask2); - - /// 20180217 lduchosal - /// impossible to reach code. - /// if (parsed == false) { - /// if (tryParse == false) { - /// throw new ArgumentException("netmask"); - /// } - /// cidr = null; - /// return; - /// } - var uintNetmask = (BigInteger)uintNetmask2; - - IPNetwork.InternalToCidr(tryParse, uintNetmask, netmask.AddressFamily, out var cidr2); - cidr = cidr2; - - return; - - } - - - #endregion - - #region ToNetmask - - /// - /// Convert CIDR to netmask - /// 24 -> 255.255.255.0 - /// 16 -> 255.255.0.0 - /// 8 -> 255.0.0.0 - /// - /// - /// - /// - public static IPAddress ToNetmask(byte cidr, AddressFamily family) - { - - IPAddress netmask = null; - IPNetwork.InternalToNetmask(false, cidr, family, out netmask); - return netmask; - } - - /// - /// Convert CIDR to netmask - /// 24 -> 255.255.255.0 - /// 16 -> 255.255.0.0 - /// 8 -> 255.0.0.0 - /// - /// - /// - /// - public static bool TryToNetmask(byte cidr, AddressFamily family, out IPAddress netmask) - { - - IPAddress netmask2 = null; - IPNetwork.InternalToNetmask(true, cidr, family, out netmask2); - bool parsed = (netmask2 != null); - netmask = netmask2; - return parsed; - } - - -#if TRAVISCI - public -#else - internal -#endif - static void InternalToNetmask(bool tryParse, byte cidr, AddressFamily family, out IPAddress netmask) - { - - if (family != AddressFamily.InterNetwork - && family != AddressFamily.InterNetworkV6) - { - if (tryParse == false) - { - throw new ArgumentException("family"); - } - netmask = null; - return; - } - - /// 20180217 lduchosal - /// impossible to reach code, byte cannot be negative : - /// - /// if (cidr < 0) { - /// if (tryParse == false) { - /// throw new ArgumentOutOfRangeException("cidr"); - /// } - /// netmask = null; - /// return; - /// } - - int maxCidr = family == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; - if (cidr > maxCidr) - { - if (tryParse == false) - { - throw new ArgumentOutOfRangeException(nameof(cidr)); - } - netmask = null; - return; - } - - var mask = IPNetwork.ToUint(cidr, family); - var netmask2 = IPNetwork.ToIPAddress(mask, family); - netmask = netmask2; - - return; - } - - #endregion - - #endregion - - #region utils - - #region BitsSet - - /// - /// Count bits set to 1 in netmask - /// - /// - /// - /// - private static byte BitsSet(BigInteger netmask, AddressFamily family) - { - - string s = netmask.ToBinaryString(); - return (byte)s.Replace("0", "") - .ToCharArray() - .Length; - - } - - - /// - /// Count bits set to 1 in netmask - /// - /// - /// - public static uint BitsSet(IPAddress netmask) - { - var uintNetmask = IPNetwork.ToBigInteger(netmask); - uint bits = IPNetwork.BitsSet(uintNetmask, netmask.AddressFamily); - return bits; - } - - #endregion - - #region ValidNetmask - - /// - /// return true if netmask is a valid netmask - /// 255.255.255.0, 255.0.0.0, 255.255.240.0, ... - /// - /// - /// - /// - public static bool ValidNetmask(IPAddress netmask) - { - - if (netmask == null) - { - throw new ArgumentNullException(nameof(netmask)); - } - var uintNetmask = IPNetwork.ToBigInteger(netmask); - bool valid = IPNetwork.InternalValidNetmask(uintNetmask, netmask.AddressFamily); - return valid; - } - -#if TRAVISCI - public -#else - internal -#endif - static bool InternalValidNetmask(BigInteger netmask, AddressFamily family) - { - - if (family != AddressFamily.InterNetwork - && family != AddressFamily.InterNetworkV6) - { - throw new ArgumentException("family"); - } - - var mask = family == AddressFamily.InterNetwork - ? new BigInteger(0x0ffffffff) - : new BigInteger(new byte[]{ - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, - 0x00 - }); - - var neg = ((~netmask) & (mask)); - bool isNetmask = ((neg + 1) & neg) == 0; - return isNetmask; - - } - - #endregion - - #region ToIPAddress - - /// - /// Transform a uint ipaddress into IPAddress object - /// - /// - /// - public static IPAddress ToIPAddress(BigInteger ipaddress, AddressFamily family) - { - - int width = family == AddressFamily.InterNetwork ? 4 : 16; - byte[] bytes = ipaddress.ToByteArray(); - byte[] bytes2 = new byte[width]; - int copy = bytes.Length > width ? width : bytes.Length; - Array.Copy(bytes, 0, bytes2, 0, copy); - Array.Reverse(bytes2); - - byte[] sized = Resize(bytes2, family); - var ip = new IPAddress(sized); - return ip; - } - -#if TRAVISCI - public -#else - internal -#endif - static byte[] Resize(byte[] bytes, AddressFamily family) - { - - if (family != AddressFamily.InterNetwork - && family != AddressFamily.InterNetworkV6) - { - throw new ArgumentException("family"); - } - - int width = family == AddressFamily.InterNetwork ? 4 : 16; - - if (bytes.Length > width) - { - throw new ArgumentException("bytes"); - } - - byte[] result = new byte[width]; - Array.Copy(bytes, 0, result, 0, bytes.Length); - return result; - } - - #endregion - - #endregion - - #region contains - - /// - /// return true if ipaddress is contained in network - /// - /// - /// - public bool Contains(IPAddress ipaddress) - { - - if (ipaddress == null) - { - throw new ArgumentNullException(nameof(ipaddress)); - } - - if (AddressFamily != ipaddress.AddressFamily) - { - return false; - } - - var uintNetwork = _network; - var uintBroadcast = _broadcast; - var uintAddress = IPNetwork.ToBigInteger(ipaddress); - - bool contains = (uintAddress >= uintNetwork - && uintAddress <= uintBroadcast); - - return contains; - - } - - /// - /// return true is network2 is fully contained in network - /// - /// - /// - public bool Contains(IPNetwork network2) - { - - if (network2 == null) - { - throw new ArgumentNullException(nameof(network2)); - } - - var uintNetwork = _network; - var uintBroadcast = _broadcast; - - var uintFirst = network2._network; - var uintLast = network2._broadcast; - - bool contains = (uintFirst >= uintNetwork - && uintLast <= uintBroadcast); - - return contains; - } - - #endregion - - #region overlap - - /// - /// return true is network2 overlap network - /// - /// - /// - public bool Overlap(IPNetwork network2) - { - - if (network2 == null) - { - throw new ArgumentNullException(nameof(network2)); - } - - var uintNetwork = _network; - var uintBroadcast = _broadcast; - - var uintFirst = network2._network; - var uintLast = network2._broadcast; - - bool overlap = - (uintFirst >= uintNetwork && uintFirst <= uintBroadcast) - || (uintLast >= uintNetwork && uintLast <= uintBroadcast) - || (uintFirst <= uintNetwork && uintLast >= uintBroadcast) - || (uintFirst >= uintNetwork && uintLast <= uintBroadcast); - - return overlap; - } - - #endregion - - #region ToString - - public override string ToString() - { - return string.Format("{0}/{1}", this.Network, this.Cidr); - } - - #endregion - - #region IANA block - - private static readonly Lazy _iana_ablock_reserved = new Lazy(() => IPNetwork.Parse("10.0.0.0/8")); - private static readonly Lazy _iana_bblock_reserved = new Lazy(() => IPNetwork.Parse("172.16.0.0/12")); - private static readonly Lazy _iana_cblock_reserved = new Lazy(() => IPNetwork.Parse("192.168.0.0/16")); - - /// - /// 10.0.0.0/8 - /// - /// - public static IPNetwork IANA_ABLK_RESERVED1 => _iana_ablock_reserved.Value; - - /// - /// 172.12.0.0/12 - /// - /// - public static IPNetwork IANA_BBLK_RESERVED1 => _iana_bblock_reserved.Value; - - /// - /// 192.168.0.0/16 - /// - /// - public static IPNetwork IANA_CBLK_RESERVED1 => _iana_cblock_reserved.Value; - - /// - /// return true if ipaddress is contained in - /// IANA_ABLK_RESERVED1, IANA_BBLK_RESERVED1, IANA_CBLK_RESERVED1 - /// - /// - /// - public static bool IsIANAReserved(IPAddress ipaddress) - { - - if (ipaddress == null) - { - throw new ArgumentNullException(nameof(ipaddress)); - } - - return IPNetwork.IANA_ABLK_RESERVED1.Contains(ipaddress) - || IPNetwork.IANA_BBLK_RESERVED1.Contains(ipaddress) - || IPNetwork.IANA_CBLK_RESERVED1.Contains(ipaddress); - } - - /// - /// return true if ipnetwork is contained in - /// IANA_ABLK_RESERVED1, IANA_BBLK_RESERVED1, IANA_CBLK_RESERVED1 - /// - /// - public bool IsIANAReserved() - { - return IPNetwork.IANA_ABLK_RESERVED1.Contains(this) - || IPNetwork.IANA_BBLK_RESERVED1.Contains(this) - || IPNetwork.IANA_CBLK_RESERVED1.Contains(this); - } - - #endregion - - #region Subnet - - /// - /// Subnet a network into multiple nets of cidr mask - /// Subnet 192.168.0.0/24 into cidr 25 gives 192.168.0.0/25, 192.168.0.128/25 - /// Subnet 10.0.0.0/8 into cidr 9 gives 10.0.0.0/9, 10.128.0.0/9 - /// - /// - /// - public IPNetworkCollection Subnet(byte cidr) - { - IPNetworkCollection ipnetworkCollection = null; - IPNetwork.InternalSubnet(false, this, cidr, out ipnetworkCollection); - return ipnetworkCollection; - } - - /// - /// Subnet a network into multiple nets of cidr mask - /// Subnet 192.168.0.0/24 into cidr 25 gives 192.168.0.0/25, 192.168.0.128/25 - /// Subnet 10.0.0.0/8 into cidr 9 gives 10.0.0.0/9, 10.128.0.0/9 - /// - /// - /// - public bool TrySubnet(byte cidr, out IPNetworkCollection ipnetworkCollection) - { - IPNetworkCollection inc = null; - IPNetwork.InternalSubnet(true, this, cidr, out inc); - if (inc == null) - { - ipnetworkCollection = null; - return false; - } - - ipnetworkCollection = inc; - return true; - } - -#if TRAVISCI - public -#else - internal -#endif - static void InternalSubnet(bool trySubnet, IPNetwork network, byte cidr, out IPNetworkCollection ipnetworkCollection) - { - - if (network == null) - { - if (trySubnet == false) - { - throw new ArgumentNullException(nameof(network)); - } - ipnetworkCollection = null; - return; - } - - int maxCidr = network._family == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; - if (cidr > maxCidr) - { - if (trySubnet == false) - { - throw new ArgumentOutOfRangeException(nameof(cidr)); - } - ipnetworkCollection = null; - return; - } - - if (cidr < network.Cidr) - { - if (trySubnet == false) - { - throw new ArgumentException("cidr"); - } - ipnetworkCollection = null; - return; - } - - ipnetworkCollection = new IPNetworkCollection(network, cidr); - return; - } - - - - #endregion - - #region Supernet - - /// - /// Supernet two consecutive cidr equal subnet into a single one - /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23 - /// 10.1.0.0/16 + 10.0.0.0/16 = 10.0.0.0/15 - /// 192.168.0.0/24 + 192.168.0.0/25 = 192.168.0.0/24 - /// - /// - /// - public IPNetwork Supernet(IPNetwork network2) - { - IPNetwork supernet = null; - IPNetwork.InternalSupernet(false, this, network2, out supernet); - return supernet; - } - - /// - /// Try to supernet two consecutive cidr equal subnet into a single one - /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23 - /// 10.1.0.0/16 + 10.0.0.0/16 = 10.0.0.0/15 - /// 192.168.0.0/24 + 192.168.0.0/25 = 192.168.0.0/24 - /// - /// - /// - public bool TrySupernet(IPNetwork network2, out IPNetwork supernet) - { - - IPNetwork outSupernet = null; - IPNetwork.InternalSupernet(true, this, network2, out outSupernet); - bool parsed = (outSupernet != null); - supernet = outSupernet; - return parsed; - } - -#if TRAVISCI - public -#else - internal -#endif - static void InternalSupernet(bool trySupernet, IPNetwork network1, IPNetwork network2, out IPNetwork supernet) - { - - if (network1 == null) - { - if (trySupernet == false) - { - throw new ArgumentNullException(nameof(network1)); - } - supernet = null; - return; - } - - if (network2 == null) - { - if (trySupernet == false) - { - throw new ArgumentNullException(nameof(network2)); - } - supernet = null; - return; - } - - - if (network1.Contains(network2)) - { - supernet = new IPNetwork(network1._network, network1._family, network1.Cidr); - return; - } - - if (network2.Contains(network1)) - { - supernet = new IPNetwork(network2._network, network2._family, network2.Cidr); - return; - } - - if (network1._cidr != network2._cidr) - { - if (trySupernet == false) - { - throw new ArgumentException("cidr"); - } - supernet = null; - return; - } - - var first = (network1._network < network2._network) ? network1 : network2; - var last = (network1._network > network2._network) ? network1 : network2; - - /// Starting from here : - /// network1 and network2 have the same cidr, - /// network1 does not contain network2, - /// network2 does not contain network1, - /// first is the lower subnet - /// last is the higher subnet - - - if ((first._broadcast + 1) != last._network) - { - if (trySupernet == false) - { - throw new ArgumentOutOfRangeException(nameof(trySupernet), "TrySupernet was false while the first and last networks are not adjacent."); - } - supernet = null; - return; - } - - var uintSupernet = first._network; - byte cidrSupernet = (byte)(first._cidr - 1); - - var networkSupernet = new IPNetwork(uintSupernet, first._family, cidrSupernet); - if (networkSupernet._network != first._network) - { - if (trySupernet == false) - { - throw new ArgumentException("network"); - } - supernet = null; - return; - } - supernet = networkSupernet; - return; - } - - #endregion - - #region GetHashCode - - public override int GetHashCode() - { - return string.Format("{0}|{1}|{2}", - this._ipaddress.GetHashCode(), - this._network.GetHashCode(), - this._cidr.GetHashCode()).GetHashCode(); - } - - #endregion - - #region SupernetArray - - /// - /// Supernet a list of subnet - /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23 - /// 192.168.0.0/24 + 192.168.1.0/24 + 192.168.2.0/24 + 192.168.3.0/24 = 192.168.0.0/22 - /// - /// The IP networks - /// - public static IPNetwork[] Supernet(IPNetwork[] ipnetworks) - { - InternalSupernet(false, ipnetworks, out var supernet); - return supernet; - } - - /// - /// Supernet a list of subnet - /// 192.168.0.0/24 + 192.168.1.0/24 = 192.168.0.0/23 - /// 192.168.0.0/24 + 192.168.1.0/24 + 192.168.2.0/24 + 192.168.3.0/24 = 192.168.0.0/22 - /// - /// - /// - /// - public static bool TrySupernet(IPNetwork[] ipnetworks, out IPNetwork[] supernet) - { - bool supernetted = InternalSupernet(true, ipnetworks, out supernet); - return supernetted; - - } - -#if TRAVISCI - public -#else - internal -#endif - static bool InternalSupernet(bool trySupernet, IPNetwork[] ipnetworks, out IPNetwork[] supernet) - { - - if (ipnetworks == null) - { - if (trySupernet == false) - { - throw new ArgumentNullException(nameof(ipnetworks)); - } - supernet = null; - return false; - } - - if (ipnetworks.Length <= 0) - { - supernet = new IPNetwork[0]; - return true; - } - - var supernetted = new List(); - var ipns = IPNetwork.Array2List(ipnetworks); - var current = IPNetwork.List2Stack(ipns); - int previousCount = 0; - int currentCount = current.Count; - - while (previousCount != currentCount) - { - - supernetted.Clear(); - while (current.Count > 1) - { - var ipn1 = current.Pop(); - var ipn2 = current.Peek(); - - IPNetwork outNetwork = null; - bool success = ipn1.TrySupernet(ipn2, out outNetwork); - if (success) - { - current.Pop(); - current.Push(outNetwork); - } - else - { - supernetted.Add(ipn1); - } - } - if (current.Count == 1) - { - supernetted.Add(current.Pop()); - } - - previousCount = currentCount; - currentCount = supernetted.Count; - current = IPNetwork.List2Stack(supernetted); - - } - supernet = supernetted.ToArray(); - return true; - } - - private static Stack List2Stack(List list) - { - var stack = new Stack(); - list.ForEach(new Action( - delegate (IPNetwork ipn) - { - stack.Push(ipn); - } - )); - return stack; - } - - private static List Array2List(IPNetwork[] array) - { - var ipns = new List(); - ipns.AddRange(array); - IPNetwork.RemoveNull(ipns); - ipns.Sort(new Comparison( - delegate (IPNetwork ipn1, IPNetwork ipn2) - { - int networkCompare = ipn1._network.CompareTo(ipn2._network); - if (networkCompare == 0) - { - int cidrCompare = ipn1._cidr.CompareTo(ipn2._cidr); - return cidrCompare; - } - return networkCompare; - } - )); - ipns.Reverse(); - - return ipns; - } - - private static void RemoveNull(List ipns) - { - ipns.RemoveAll(new Predicate( - delegate (IPNetwork ipn) - { - if (ipn == null) - { - return true; - } - return false; - } - )); - - } - - #endregion - - #region WideSubnet - - public static IPNetwork WideSubnet(string start, string end) - { - - if (string.IsNullOrEmpty(start)) - { - throw new ArgumentNullException(nameof(start)); - } - - if (string.IsNullOrEmpty(end)) - { - throw new ArgumentNullException(nameof(end)); - } - - if (!IPAddress.TryParse(start, out var startIP)) - { - throw new ArgumentException("start"); - } - - if (!IPAddress.TryParse(end, out var endIP)) - { - throw new ArgumentException("end"); - } - - if (startIP.AddressFamily != endIP.AddressFamily) - { - throw new NotSupportedException("MixedAddressFamily"); - } - - var ipnetwork = new IPNetwork(0, startIP.AddressFamily, 0); - for (byte cidr = 32; cidr >= 0; cidr--) - { - var wideSubnet = IPNetwork.Parse(start, cidr); - if (wideSubnet.Contains(endIP)) - { - ipnetwork = wideSubnet; - break; - } - } - return ipnetwork; - - } - - public static bool TryWideSubnet(IPNetwork[] ipnetworks, out IPNetwork ipnetwork) - { - IPNetwork ipn = null; - IPNetwork.InternalWideSubnet(true, ipnetworks, out ipn); - if (ipn == null) - { - ipnetwork = null; - return false; - } - ipnetwork = ipn; - return true; - } - - public static IPNetwork WideSubnet(IPNetwork[] ipnetworks) - { - IPNetwork ipn = null; - IPNetwork.InternalWideSubnet(false, ipnetworks, out ipn); - return ipn; - } - - internal static void InternalWideSubnet(bool tryWide, IPNetwork[] ipnetworks, out IPNetwork ipnetwork) - { - - if (ipnetworks == null) - { - if (tryWide == false) - { - throw new ArgumentNullException(nameof(ipnetworks)); - } - ipnetwork = null; - return; - } - - - IPNetwork[] nnin = Array.FindAll(ipnetworks, new Predicate( - delegate (IPNetwork ipnet) - { - return ipnet != null; - } - )); - - if (nnin.Length <= 0) - { - if (tryWide == false) - { - throw new ArgumentException("ipnetworks"); - } - ipnetwork = null; - return; - } - - if (nnin.Length == 1) - { - var ipn0 = nnin[0]; - ipnetwork = ipn0; - return; - } - - Array.Sort(nnin); - var nnin0 = nnin[0]; - var uintNnin0 = nnin0._ipaddress; - - var nninX = nnin[nnin.Length - 1]; - var ipaddressX = nninX.Broadcast; - - var family = ipnetworks[0]._family; - foreach (var ipnx in ipnetworks) - { - if (ipnx._family != family) - { - throw new ArgumentException("MixedAddressFamily"); - } - } - - var ipn = new IPNetwork(0, family, 0); - for (byte cidr = nnin0._cidr; cidr >= 0; cidr--) - { - var wideSubnet = new IPNetwork(uintNnin0, family, cidr); - if (wideSubnet.Contains(ipaddressX)) - { - ipn = wideSubnet; - break; - } - } - - ipnetwork = ipn; - return; - } - - #endregion - - #region Print - - /// - /// Print an ipnetwork in a clear representation string - /// - /// - public string Print() - { - - var sw = new StringWriter(); - - sw.WriteLine("IPNetwork : {0}", ToString()); - sw.WriteLine("Network : {0}", Network); - sw.WriteLine("Netmask : {0}", Netmask); - sw.WriteLine("Cidr : {0}", Cidr); - sw.WriteLine("Broadcast : {0}", Broadcast); - sw.WriteLine("FirstUsable : {0}", FirstUsable); - sw.WriteLine("LastUsable : {0}", LastUsable); - sw.WriteLine("Usable : {0}", Usable); - - return sw.ToString(); - } - - #endregion - - #region TryGuessCidr - - /// - /// - /// Class Leading bits Default netmask - /// A (CIDR /8) 00 255.0.0.0 - /// A (CIDR /8) 01 255.0.0.0 - /// B (CIDR /16) 10 255.255.0.0 - /// C (CIDR /24) 11 255.255.255.0 - /// - /// - /// - /// - /// - public static bool TryGuessCidr(string ip, out byte cidr) - { - - IPAddress ipaddress = null; - bool parsed = IPAddress.TryParse(string.Format("{0}", ip), out ipaddress); - if (parsed == false) - { - cidr = 0; - return false; - } - - if (ipaddress.AddressFamily == AddressFamily.InterNetworkV6) - { - cidr = 64; - return true; - } - var uintIPAddress = IPNetwork.ToBigInteger(ipaddress); - uintIPAddress = uintIPAddress >> 29; - if (uintIPAddress <= 3) - { - cidr = 8; - return true; - } - else if (uintIPAddress <= 5) - { - cidr = 16; - return true; - } - else if (uintIPAddress <= 6) - { - cidr = 24; - return true; - } - - cidr = 0; - return false; - - } - - /// - /// Try to parse cidr. Have to be >= 0 and <= 32 or 128 - /// - /// - /// - /// - public static bool TryParseCidr(string sidr, AddressFamily family, out byte? cidr) - { - - byte b = 0; - if (!byte.TryParse(sidr, out b)) - { - cidr = null; - return false; - } - - IPAddress netmask = null; - if (!IPNetwork.TryToNetmask(b, family, out netmask)) - { - cidr = null; - return false; - } - - cidr = b; - return true; - } - - #endregion - - #region ListIPAddress - - public IPAddressCollection ListIPAddress() - { - return new IPAddressCollection(this); - } - - #endregion - - /** - * Need a better way to do it - * -#region TrySubstractNetwork - - public static bool TrySubstractNetwork(IPNetwork[] ipnetworks, IPNetwork substract, out IEnumerable result) { - - if (ipnetworks == null) { - result = null; - return false; - } - if (ipnetworks.Length <= 0) { - result = null; - return false; - } - if (substract == null) { - result = null; - return false; - } - var results = new List(); - foreach (var ipn in ipnetworks) { - if (!Overlap(ipn, substract)) { - results.Add(ipn); - continue; - } - - var collection = ipn.Subnet(substract.Cidr); - var rtemp = new List(); - foreach(var subnet in collection) { - if (subnet != substract) { - rtemp.Add(subnet); - } - } - var supernets = Supernet(rtemp.ToArray()); - results.AddRange(supernets); - } - result = results; - return true; - } -#endregion - * **/ - - #region IComparable Members - - public static int Compare(IPNetwork left, IPNetwork right) - { - // two null IPNetworks are equal - if (ReferenceEquals(left, null) && ReferenceEquals(right, null)) return 0; - - // two same IPNetworks are equal - if (ReferenceEquals(left, right)) return 0; - - // null is always sorted first - if (ReferenceEquals(left, null)) return -1; - if (ReferenceEquals(right, null)) return 1; - - // first test the network - var result = left._network.CompareTo(right._network); - if (result != 0) return result; - - // then test the cidr - result = left._cidr.CompareTo(right._cidr); - return result; - } - - public int CompareTo(IPNetwork other) - { - return Compare(this, other); - } - - public int CompareTo(object obj) - { - // null is at less - if (obj == null) return 1; - - // convert to a proper Cidr object - var other = obj as IPNetwork; - - // type problem if null - if (other == null) - { - throw new ArgumentException( - "The supplied parameter is an invalid type. Please supply an IPNetwork type.", - nameof(obj)); - } - - // perform the comparision - return CompareTo(other); - } - - #endregion - - #region IEquatable Members - - public static bool Equals(IPNetwork left, IPNetwork right) - { - return Compare(left, right) == 0; - } - - public bool Equals(IPNetwork other) - { - return Equals(this, other); - } - - public override bool Equals(object obj) - { - return Equals(this, obj as IPNetwork); - } - - #endregion - - #region Operators - - public static bool operator ==(IPNetwork left, IPNetwork right) - { - return Equals(left, right); - } - - public static bool operator !=(IPNetwork left, IPNetwork right) - { - return !Equals(left, right); - } - - public static bool operator <(IPNetwork left, IPNetwork right) - { - return Compare(left, right) < 0; - } - - public static bool operator >(IPNetwork left, IPNetwork right) - { - return Compare(left, right) > 0; - } - - #endregion - - } -} diff --git a/Emby.Server.Implementations/Networking/IPNetwork/IPNetworkCollection.cs b/Emby.Server.Implementations/Networking/IPNetwork/IPNetworkCollection.cs deleted file mode 100644 index 4cda421e5..000000000 --- a/Emby.Server.Implementations/Networking/IPNetwork/IPNetworkCollection.cs +++ /dev/null @@ -1,129 +0,0 @@ -using System; -using System.Collections; -using System.Collections.Generic; -using System.Numerics; - -namespace Emby.Server.Implementations.Networking.IPNetwork -{ - public class IPNetworkCollection : IEnumerable, IEnumerator - { - - private BigInteger _enumerator; - private byte _cidrSubnet; - private IPNetwork _ipnetwork; - - private byte _cidr => this._ipnetwork.Cidr; - - private BigInteger _broadcast => IPNetwork.ToBigInteger(this._ipnetwork.Broadcast); - - private BigInteger _lastUsable => IPNetwork.ToBigInteger(this._ipnetwork.LastUsable); - private BigInteger _network => IPNetwork.ToBigInteger(this._ipnetwork.Network); -#if TRAVISCI - public -#else - internal -#endif - IPNetworkCollection(IPNetwork ipnetwork, byte cidrSubnet) - { - - int maxCidr = ipnetwork.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork ? 32 : 128; - if (cidrSubnet > maxCidr) - { - throw new ArgumentOutOfRangeException(nameof(cidrSubnet)); - } - - if (cidrSubnet < ipnetwork.Cidr) - { - throw new ArgumentException("cidr"); - } - - this._cidrSubnet = cidrSubnet; - this._ipnetwork = ipnetwork; - this._enumerator = -1; - } - - #region Count, Array, Enumerator - - public BigInteger Count - { - get - { - var count = BigInteger.Pow(2, this._cidrSubnet - this._cidr); - return count; - } - } - - public IPNetwork this[BigInteger i] - { - get - { - if (i >= this.Count) - { - throw new ArgumentOutOfRangeException(nameof(i)); - } - - var last = this._ipnetwork.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6 - ? this._lastUsable : this._broadcast; - var increment = (last - this._network) / this.Count; - var uintNetwork = this._network + ((increment + 1) * i); - var ipn = new IPNetwork(uintNetwork, this._ipnetwork.AddressFamily, this._cidrSubnet); - return ipn; - } - } - - #endregion - - #region IEnumerable Members - - IEnumerator IEnumerable.GetEnumerator() - { - return this; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return this; - } - - #region IEnumerator Members - - public IPNetwork Current => this[this._enumerator]; - - #endregion - - #region IDisposable Members - - public void Dispose() - { - // nothing to dispose - return; - } - - #endregion - - #region IEnumerator Members - - object IEnumerator.Current => this.Current; - - public bool MoveNext() - { - this._enumerator++; - if (this._enumerator >= this.Count) - { - return false; - } - return true; - - } - - public void Reset() - { - this._enumerator = -1; - } - - #endregion - - #endregion - - } -} diff --git a/Emby.Server.Implementations/Networking/IPNetwork/LICENSE.txt b/Emby.Server.Implementations/Networking/IPNetwork/LICENSE.txt deleted file mode 100644 index 45d7392ac..000000000 --- a/Emby.Server.Implementations/Networking/IPNetwork/LICENSE.txt +++ /dev/null @@ -1,24 +0,0 @@ -Copyright (c) 2015, lduchosal -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/Emby.Server.Implementations/Networking/NetworkManager.cs b/Emby.Server.Implementations/Networking/NetworkManager.cs index 3cacacf07..82add242a 100644 --- a/Emby.Server.Implementations/Networking/NetworkManager.cs +++ b/Emby.Server.Implementations/Networking/NetworkManager.cs @@ -258,7 +258,7 @@ namespace Emby.Server.Implementations.Networking if (normalizedSubnet.IndexOf('/') != -1) { - var ipnetwork = IPNetwork.IPNetwork.Parse(normalizedSubnet); + var ipnetwork = IPNetwork.Parse(normalizedSubnet); if (ipnetwork.Contains(address)) { return true; -- cgit v1.2.3 From 1cad93c276fef512d6d4731d32704e05433aed01 Mon Sep 17 00:00:00 2001 From: Bond_009 Date: Mon, 29 Jul 2019 15:26:17 +0200 Subject: Use System.Net abstractions instead of raw socket --- .../LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs | 2 +- .../TunerHosts/HdHomerun/HdHomerunManager.cs | 207 ++++++++++++--------- .../TunerHosts/HdHomerun/HdHomerunUdpStream.cs | 139 +------------- Emby.Server.Implementations/Net/SocketFactory.cs | 42 ----- MediaBrowser.Model/Net/ISocketFactory.cs | 12 -- 5 files changed, 127 insertions(+), 275 deletions(-) (limited to 'Emby.Server.Implementations/Net') diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs index ed524cae3..42acfbc5c 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunHost.cs @@ -255,7 +255,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var uri = new Uri(GetApiUrl(info)); - using (var manager = new HdHomerunManager(_socketFactory, Logger)) + using (var manager = new HdHomerunManager(Logger)) { // Legacy HdHomeruns are IPv4 only var ipInfo = IPAddress.Parse(uri.Host); diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs index 6e79441da..a6538be78 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunManager.cs @@ -1,12 +1,13 @@ using System; +using System.Buffers; using System.Collections.Generic; using System.Net; +using System.Net.Sockets; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.LiveTv; -using MediaBrowser.Model.Net; using Microsoft.Extensions.Logging; namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun @@ -78,37 +79,36 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public class HdHomerunManager : IDisposable { - public static int HdHomeRunPort = 65001; + public const int HdHomeRunPort = 65001; // Message constants - private static byte GetSetName = 3; - private static byte GetSetValue = 4; - private static byte GetSetLockkey = 21; - private static ushort GetSetRequest = 4; - private static ushort GetSetReply = 5; + private const byte GetSetName = 3; + private const byte GetSetValue = 4; + private const byte GetSetLockkey = 21; + private const ushort GetSetRequest = 4; + private const ushort GetSetReply = 5; + + private readonly ILogger _logger; private uint? _lockkey = null; private int _activeTuner = -1; - private readonly ISocketFactory _socketFactory; - private IPAddress _remoteIp; + private IPEndPoint _remoteEndPoint; - private ILogger _logger; - private ISocket _currentTcpSocket; + private TcpClient _tcpClient; - public HdHomerunManager(ISocketFactory socketFactory, ILogger logger) + public HdHomerunManager(ILogger logger) { - _socketFactory = socketFactory; _logger = logger; } public void Dispose() { - using (var socket = _currentTcpSocket) + using (var socket = _tcpClient) { if (socket != null) { - _currentTcpSocket = null; + _tcpClient = null; - var task = StopStreaming(socket); + var task = StopStreaming(_tcpClient); Task.WaitAll(task); } } @@ -116,35 +116,38 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public async Task CheckTunerAvailability(IPAddress remoteIp, int tuner, CancellationToken cancellationToken) { - using (var socket = _socketFactory.CreateTcpSocket(remoteIp, HdHomeRunPort)) + using (var client = new TcpClient(new IPEndPoint(remoteIp, HdHomeRunPort))) + using (var stream = client.GetStream()) { - return await CheckTunerAvailability(socket, remoteIp, tuner, cancellationToken).ConfigureAwait(false); + return await CheckTunerAvailability(stream, tuner, cancellationToken).ConfigureAwait(false); } } - private static async Task CheckTunerAvailability(ISocket socket, IPAddress remoteIp, int tuner, CancellationToken cancellationToken) + private static async Task CheckTunerAvailability(NetworkStream stream, int tuner, CancellationToken cancellationToken) { - var ipEndPoint = new IPEndPoint(remoteIp, HdHomeRunPort); - var lockkeyMsg = CreateGetMessage(tuner, "lockkey"); - await socket.SendToAsync(lockkeyMsg, 0, lockkeyMsg.Length, ipEndPoint, cancellationToken); + await stream.WriteAsync(lockkeyMsg, 0, lockkeyMsg.Length, cancellationToken).ConfigureAwait(false); - var receiveBuffer = new byte[8192]; - var response = await socket.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false); + byte[] buffer = ArrayPool.Shared.Rent(8192); + try + { + int receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); - ParseReturnMessage(response.Buffer, response.ReceivedBytes, out string returnVal); + ParseReturnMessage(buffer, receivedBytes, out string returnVal); - return string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase); + return string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase); + } + finally + { + ArrayPool.Shared.Return(buffer); + } } public async Task StartStreaming(IPAddress remoteIp, IPAddress localIp, int localPort, IHdHomerunChannelCommands commands, int numTuners, CancellationToken cancellationToken) { - _remoteIp = remoteIp; + _remoteEndPoint = new IPEndPoint(remoteIp, HdHomeRunPort); - var tcpClient = _socketFactory.CreateTcpSocket(_remoteIp, HdHomeRunPort); - _currentTcpSocket = tcpClient; - - var receiveBuffer = new byte[8192]; + _tcpClient = new TcpClient(_remoteEndPoint); if (!_lockkey.HasValue) { @@ -153,51 +156,61 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } var lockKeyValue = _lockkey.Value; + var stream = _tcpClient.GetStream(); - var ipEndPoint = new IPEndPoint(_remoteIp, HdHomeRunPort); - - for (int i = 0; i < numTuners; ++i) + byte[] buffer = ArrayPool.Shared.Rent(8192); + try { - if (!await CheckTunerAvailability(tcpClient, _remoteIp, i, cancellationToken).ConfigureAwait(false)) - continue; - - _activeTuner = i; - var lockKeyString = string.Format("{0:d}", lockKeyValue); - var lockkeyMsg = CreateSetMessage(i, "lockkey", lockKeyString, null); - await tcpClient.SendToAsync(lockkeyMsg, 0, lockkeyMsg.Length, ipEndPoint, cancellationToken).ConfigureAwait(false); - var response = await tcpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false); - // parse response to make sure it worked - if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out var returnVal)) - continue; - - var commandList = commands.GetCommands(); - foreach (Tuple command in commandList) + for (int i = 0; i < numTuners; ++i) { - var channelMsg = CreateSetMessage(i, command.Item1, command.Item2, lockKeyValue); - await tcpClient.SendToAsync(channelMsg, 0, channelMsg.Length, ipEndPoint, cancellationToken).ConfigureAwait(false); - response = await tcpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false); + if (!await CheckTunerAvailability(stream, i, cancellationToken).ConfigureAwait(false)) + { + continue; + } + + _activeTuner = i; + var lockKeyString = string.Format("{0:d}", lockKeyValue); + var lockkeyMsg = CreateSetMessage(i, "lockkey", lockKeyString, null); + await stream.WriteAsync(lockkeyMsg, 0, lockkeyMsg.Length, cancellationToken).ConfigureAwait(false); + int receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); // parse response to make sure it worked - if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out returnVal)) + if (!ParseReturnMessage(buffer, receivedBytes, out var returnVal)) { - await ReleaseLockkey(tcpClient, lockKeyValue).ConfigureAwait(false); continue; } - } + var commandList = commands.GetCommands(); + foreach (Tuple command in commandList) + { + var channelMsg = CreateSetMessage(i, command.Item1, command.Item2, lockKeyValue); + await stream.WriteAsync(channelMsg, 0, channelMsg.Length, cancellationToken).ConfigureAwait(false); + receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + // parse response to make sure it worked + if (!ParseReturnMessage(buffer, receivedBytes, out returnVal)) + { + await ReleaseLockkey(_tcpClient, lockKeyValue).ConfigureAwait(false); + continue; + } + } - var targetValue = string.Format("rtp://{0}:{1}", localIp, localPort); - var targetMsg = CreateSetMessage(i, "target", targetValue, lockKeyValue); + var targetValue = string.Format("rtp://{0}:{1}", localIp, localPort); + var targetMsg = CreateSetMessage(i, "target", targetValue, lockKeyValue); - await tcpClient.SendToAsync(targetMsg, 0, targetMsg.Length, ipEndPoint, cancellationToken).ConfigureAwait(false); - response = await tcpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false); - // parse response to make sure it worked - if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out returnVal)) - { - await ReleaseLockkey(tcpClient, lockKeyValue).ConfigureAwait(false); - continue; - } + await stream.WriteAsync(targetMsg, 0, targetMsg.Length, cancellationToken).ConfigureAwait(false); + receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + // parse response to make sure it worked + if (!ParseReturnMessage(buffer, receivedBytes, out returnVal)) + { + await ReleaseLockkey(_tcpClient, lockKeyValue).ConfigureAwait(false); + continue; + } - return; + return; + } + } + finally + { + ArrayPool.Shared.Return(buffer); } _activeTuner = -1; @@ -207,53 +220,70 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun public async Task ChangeChannel(IHdHomerunChannelCommands commands, CancellationToken cancellationToken) { if (!_lockkey.HasValue) + { return; + } - using (var tcpClient = _socketFactory.CreateTcpSocket(_remoteIp, HdHomeRunPort)) + using (var tcpClient = new TcpClient(_remoteEndPoint)) + using (var stream = tcpClient.GetStream()) { var commandList = commands.GetCommands(); - var receiveBuffer = new byte[8192]; - - foreach (Tuple command in commandList) + byte[] buffer = ArrayPool.Shared.Rent(8192); + try { - var channelMsg = CreateSetMessage(_activeTuner, command.Item1, command.Item2, _lockkey); - await tcpClient.SendToAsync(channelMsg, 0, channelMsg.Length, new IPEndPoint(_remoteIp, HdHomeRunPort), cancellationToken).ConfigureAwait(false); - var response = await tcpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false); - // parse response to make sure it worked - if (!ParseReturnMessage(response.Buffer, response.ReceivedBytes, out string returnVal)) + foreach (Tuple command in commandList) { - return; + var channelMsg = CreateSetMessage(_activeTuner, command.Item1, command.Item2, _lockkey); + await stream.WriteAsync(channelMsg, 0, channelMsg.Length, cancellationToken).ConfigureAwait(false); + int receivedBytes = await stream.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false); + // parse response to make sure it worked + if (!ParseReturnMessage(buffer, receivedBytes, out string returnVal)) + { + return; + } } } + finally + { + ArrayPool.Shared.Return(buffer); + } } } - public Task StopStreaming(ISocket socket) + public Task StopStreaming(TcpClient client) { var lockKey = _lockkey; if (!lockKey.HasValue) + { return Task.CompletedTask; + } - return ReleaseLockkey(socket, lockKey.Value); + return ReleaseLockkey(client, lockKey.Value); } - private async Task ReleaseLockkey(ISocket tcpClient, uint lockKeyValue) + private async Task ReleaseLockkey(TcpClient client, uint lockKeyValue) { _logger.LogInformation("HdHomerunManager.ReleaseLockkey {0}", lockKeyValue); - var ipEndPoint = new IPEndPoint(_remoteIp, HdHomeRunPort); + var stream = client.GetStream(); var releaseTarget = CreateSetMessage(_activeTuner, "target", "none", lockKeyValue); - await tcpClient.SendToAsync(releaseTarget, 0, releaseTarget.Length, ipEndPoint, CancellationToken.None).ConfigureAwait(false); - - var receiveBuffer = new byte[8192]; + await stream.WriteAsync(releaseTarget, 0, releaseTarget.Length, CancellationToken.None).ConfigureAwait(false); - await tcpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, CancellationToken.None).ConfigureAwait(false); - var releaseKeyMsg = CreateSetMessage(_activeTuner, "lockkey", "none", lockKeyValue); - _lockkey = null; - await tcpClient.SendToAsync(releaseKeyMsg, 0, releaseKeyMsg.Length, ipEndPoint, CancellationToken.None).ConfigureAwait(false); - await tcpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, CancellationToken.None).ConfigureAwait(false); + var buffer = ArrayPool.Shared.Rent(8192); + try + { + await stream.ReadAsync(buffer, 0, buffer.Length, CancellationToken.None).ConfigureAwait(false); + var releaseKeyMsg = CreateSetMessage(_activeTuner, "lockkey", "none", lockKeyValue); + _lockkey = null; + await stream.WriteAsync(releaseKeyMsg, 0, releaseKeyMsg.Length, CancellationToken.None).ConfigureAwait(false); + await stream.ReadAsync(buffer, 0, buffer.Length, CancellationToken.None).ConfigureAwait(false); + } + finally + { + ArrayPool.Shared.Return(buffer); + } } private static byte[] CreateGetMessage(int tuner, string name) @@ -270,7 +300,10 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun // calculate crc and insert at the end of the message var crcBytes = BitConverter.GetBytes(HdHomerunCrc.GetCrc32(message, messageLength - 4)); if (flipEndian) + { Array.Reverse(crcBytes); + } + Buffer.BlockCopy(crcBytes, 0, message, offset, 4); return message; diff --git a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs index ec708cf20..1d79a5f96 100644 --- a/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs +++ b/Emby.Server.Implementations/LiveTv/TunerHosts/HdHomerun/HdHomerunUdpStream.cs @@ -49,13 +49,6 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun EnableStreamSharing = true; } - private static Socket CreateSocket(AddressFamily addressFamily, SocketType socketType, ProtocolType protocolType) - { - var socket = new Socket(addressFamily, SocketType.Stream, ProtocolType.Tcp); - - return socket; - } - public override async Task Open(CancellationToken openCancellationToken) { LiveStreamCancellationTokenSource.Token.ThrowIfCancellationRequested(); @@ -71,13 +64,13 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun var remoteAddress = IPAddress.Parse(uri.Host); IPAddress localAddress = null; - using (var tcpSocket = CreateSocket(remoteAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) + using (var tcpClient = new TcpClient()) { try { - tcpSocket.Connect(new IPEndPoint(remoteAddress, HdHomerunManager.HdHomeRunPort)); - localAddress = ((IPEndPoint)tcpSocket.LocalEndPoint).Address; - tcpSocket.Close(); + await tcpClient.ConnectAsync(remoteAddress, HdHomerunManager.HdHomeRunPort).ConfigureAwait(false); + localAddress = ((IPEndPoint)tcpClient.Client.RemoteEndPoint).Address; + tcpClient.Close(); } catch (Exception ex) { @@ -87,7 +80,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } var udpClient = _socketFactory.CreateUdpSocket(localPort); - var hdHomerunManager = new HdHomerunManager(_socketFactory, Logger); + var hdHomerunManager = new HdHomerunManager(Logger); try { @@ -103,6 +96,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun { Logger.LogError(ex, "Error opening live stream:"); } + throw; } } @@ -199,126 +193,5 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun } } } - - public class UdpClientStream : Stream - { - private static int RtpHeaderBytes = 12; - private static int PacketSize = 1316; - private readonly MediaBrowser.Model.Net.ISocket _udpClient; - bool disposed; - - public UdpClientStream(MediaBrowser.Model.Net.ISocket udpClient) : base() - { - _udpClient = udpClient; - } - - public override async Task ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken) - { - if (buffer == null) - throw new ArgumentNullException(nameof(buffer)); - - if (offset + count < 0) - throw new ArgumentOutOfRangeException(nameof(offset), "offset + count must not be negative"); - - if (offset + count > buffer.Length) - throw new ArgumentException("offset + count must not be greater than the length of buffer"); - - if (disposed) - throw new ObjectDisposedException(nameof(UdpClientStream)); - - // This will always receive a 1328 packet size (PacketSize + RtpHeaderSize) - // The RTP header will be stripped so see how many reads we need to make to fill the buffer. - int numReads = count / PacketSize; - int totalBytesRead = 0; - byte[] receiveBuffer = new byte[81920]; - - for (int i = 0; i < numReads; ++i) - { - var data = await _udpClient.ReceiveAsync(receiveBuffer, 0, receiveBuffer.Length, cancellationToken).ConfigureAwait(false); - - var bytesRead = data.ReceivedBytes - RtpHeaderBytes; - - // remove rtp header - Buffer.BlockCopy(data.Buffer, RtpHeaderBytes, buffer, offset, bytesRead); - offset += bytesRead; - totalBytesRead += bytesRead; - } - return totalBytesRead; - } - - public override int Read(byte[] buffer, int offset, int count) - { - if (buffer == null) - throw new ArgumentNullException(nameof(buffer)); - - if (offset + count < 0) - throw new ArgumentOutOfRangeException("offset + count must not be negative", "offset+count"); - - if (offset + count > buffer.Length) - throw new ArgumentException("offset + count must not be greater than the length of buffer"); - - if (disposed) - throw new ObjectDisposedException(nameof(UdpClientStream)); - - // This will always receive a 1328 packet size (PacketSize + RtpHeaderSize) - // The RTP header will be stripped so see how many reads we need to make to fill the buffer. - int numReads = count / PacketSize; - int totalBytesRead = 0; - byte[] receiveBuffer = new byte[81920]; - - for (int i = 0; i < numReads; ++i) - { - var receivedBytes = _udpClient.Receive(receiveBuffer, 0, receiveBuffer.Length); - - var bytesRead = receivedBytes - RtpHeaderBytes; - - // remove rtp header - Buffer.BlockCopy(receiveBuffer, RtpHeaderBytes, buffer, offset, bytesRead); - offset += bytesRead; - totalBytesRead += bytesRead; - } - return totalBytesRead; - } - - protected override void Dispose(bool disposing) - { - disposed = true; - } - - public override bool CanRead => throw new NotImplementedException(); - - public override bool CanSeek => throw new NotImplementedException(); - - public override bool CanWrite => throw new NotImplementedException(); - - public override long Length => throw new NotImplementedException(); - - public override long Position - { - get => throw new NotImplementedException(); - - set => throw new NotImplementedException(); - } - - public override void Flush() - { - throw new NotImplementedException(); - } - - public override long Seek(long offset, SeekOrigin origin) - { - throw new NotImplementedException(); - } - - public override void SetLength(long value) - { - throw new NotImplementedException(); - } - - public override void Write(byte[] buffer, int offset, int count) - { - throw new NotImplementedException(); - } - } } } diff --git a/Emby.Server.Implementations/Net/SocketFactory.cs b/Emby.Server.Implementations/Net/SocketFactory.cs index 42ffa4e22..cb53ce50c 100644 --- a/Emby.Server.Implementations/Net/SocketFactory.cs +++ b/Emby.Server.Implementations/Net/SocketFactory.cs @@ -2,54 +2,12 @@ using System; using System.IO; using System.Net; using System.Net.Sockets; -using Emby.Server.Implementations.Networking; using MediaBrowser.Model.Net; namespace Emby.Server.Implementations.Net { public class SocketFactory : ISocketFactory { - // THIS IS A LINKED FILE - SHARED AMONGST MULTIPLE PLATFORMS - // Be careful to check any changes compile and work for all platform projects it is shared in. - - // Not entirely happy with this. Would have liked to have done something more generic/reusable, - // but that wasn't really the point so kept to YAGNI principal for now, even if the - // interfaces are a bit ugly, specific and make assumptions. - - public ISocket CreateTcpSocket(IPAddress remoteAddress, int remotePort) - { - if (remotePort < 0) - { - throw new ArgumentException("remotePort cannot be less than zero.", nameof(remotePort)); - } - - var addressFamily = remoteAddress.AddressFamily == AddressFamily.InterNetwork - ? AddressFamily.InterNetwork - : AddressFamily.InterNetworkV6; - - var retVal = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); - - try - { - retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); - } - catch (SocketException) - { - // This is not supported on all operating systems (qnap) - } - - try - { - return new UdpSocket(retVal, new IPEndPoint(remoteAddress, remotePort)); - } - catch - { - retVal?.Dispose(); - - throw; - } - } - /// /// Creates a new UDP acceptSocket and binds it to the specified local port. /// diff --git a/MediaBrowser.Model/Net/ISocketFactory.cs b/MediaBrowser.Model/Net/ISocketFactory.cs index e58f4cc14..2f857f1af 100644 --- a/MediaBrowser.Model/Net/ISocketFactory.cs +++ b/MediaBrowser.Model/Net/ISocketFactory.cs @@ -17,8 +17,6 @@ namespace MediaBrowser.Model.Net ISocket CreateUdpBroadcastSocket(int localPort); - ISocket CreateTcpSocket(IPAddress remoteAddress, int remotePort); - /// /// Creates a new unicast socket using the specified local port number. /// @@ -35,14 +33,4 @@ namespace MediaBrowser.Model.Net Stream CreateNetworkStream(ISocket socket, bool ownsSocket); } - - public enum SocketType - { - Stream - } - - public enum ProtocolType - { - Tcp - } } -- cgit v1.2.3