diff options
Diffstat (limited to 'Emby.Common.Implementations')
| -rw-r--r-- | Emby.Common.Implementations/Net/SocketFactory.cs | 30 | ||||
| -rw-r--r-- | Emby.Common.Implementations/Net/UdpSocket.cs | 38 | ||||
| -rw-r--r-- | Emby.Common.Implementations/Networking/BaseNetworkManager.cs | 31 |
3 files changed, 78 insertions, 21 deletions
diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index 3a2cea12a..6f0ff2996 100644 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ b/Emby.Common.Implementations/Net/SocketFactory.cs @@ -37,12 +37,36 @@ namespace Emby.Common.Implementations.Net #region ISocketFactory Members /// <summary> + /// Creates a new UDP socket and binds it to the specified local port. + /// </summary> + /// <param name="localPort">An integer specifying the local port to bind the socket to.</param> + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The purpose of this method is to create and returns a disposable result, it is up to the caller to dispose it when they are done with it.")] + public IUdpSocket CreateUdpSocket(int localPort) + { + if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); + + var retVal = new Socket(System.Net.Sockets.AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp); + try + { + retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + return new UdpSocket(retVal, localPort, _LocalIP); + } + catch + { + if (retVal != null) + retVal.Dispose(); + + throw; + } + } + + /// <summary> /// Creates a new UDP socket that is a member of the SSDP multicast local admin group and binds it to the specified local port. /// </summary> /// <param name="localPort">An integer specifying the local port to bind the socket to.</param> /// <returns>An implementation of the <see cref="IUdpSocket"/> interface used by RSSDP components to perform socket operations.</returns> [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "The purpose of this method is to create and returns a disposable result, it is up to the caller to dispose it when they are done with it.")] - public IUdpSocket CreateUdpSocket(int localPort) + public IUdpSocket CreateSsdpUdpSocket(int localPort) { if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); @@ -52,7 +76,7 @@ namespace Emby.Common.Implementations.Net retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.MulticastTimeToLive, 4); retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse("239.255.255.250"), _LocalIP)); - return new UdpSocket(retVal, localPort, _LocalIP.ToString()); + return new UdpSocket(retVal, localPort, _LocalIP); } catch { @@ -97,7 +121,7 @@ namespace Emby.Common.Implementations.Net retVal.SetSocketOption(SocketOptionLevel.IP, SocketOptionName.AddMembership, new MulticastOption(IPAddress.Parse(ipAddress), _LocalIP)); retVal.MulticastLoopback = true; - return new UdpSocket(retVal, localPort, _LocalIP.ToString()); + return new UdpSocket(retVal, localPort, _LocalIP); } catch { diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs index 86ce9c83b..997d3f25f 100644 --- a/Emby.Common.Implementations/Net/UdpSocket.cs +++ b/Emby.Common.Implementations/Net/UdpSocket.cs @@ -24,19 +24,13 @@ namespace Emby.Common.Implementations.Net #region Constructors - public UdpSocket(System.Net.Sockets.Socket socket, int localPort, string ipAddress) + public UdpSocket(System.Net.Sockets.Socket socket, int localPort, IPAddress ip) { if (socket == null) throw new ArgumentNullException("socket"); _Socket = socket; _LocalPort = localPort; - IPAddress ip = null; - if (String.IsNullOrEmpty(ipAddress)) - ip = IPAddress.Any; - else - ip = IPAddress.Parse(ipAddress); - _Socket.Bind(new IPEndPoint(ip, _LocalPort)); if (_LocalPort == 0) _LocalPort = (_Socket.LocalEndPoint as IPEndPoint).Port; @@ -46,11 +40,11 @@ namespace Emby.Common.Implementations.Net #region IUdpSocket Members - public Task<ReceivedUdpData> ReceiveAsync() + public Task<SocketReceiveResult> ReceiveAsync() { ThrowIfDisposed(); - var tcs = new TaskCompletionSource<ReceivedUdpData>(); + var tcs = new TaskCompletionSource<SocketReceiveResult>(); System.Net.EndPoint receivedFromEndPoint = new IPEndPoint(IPAddress.Any, 0); var state = new AsyncReceiveState(_Socket, receivedFromEndPoint); @@ -74,22 +68,30 @@ namespace Emby.Common.Implementations.Net return tcs.Task; } - public Task SendTo(byte[] messageData, IpEndPointInfo endPoint) + public Task SendAsync(byte[] buffer, int size, IpEndPointInfo endPoint) { ThrowIfDisposed(); - if (messageData == null) throw new ArgumentNullException("messageData"); + if (buffer == null) throw new ArgumentNullException("messageData"); if (endPoint == null) throw new ArgumentNullException("endPoint"); #if NETSTANDARD1_6 - _Socket.SendTo(messageData, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IpAddress.ToString()), endPoint.Port)); + + if (size != buffer.Length) + { + byte[] copy = new byte[size]; + Buffer.BlockCopy(buffer, 0, copy, 0, size); + buffer = copy; + } + + _Socket.SendTo(buffer, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IpAddress.ToString()), endPoint.Port)); return Task.FromResult(true); #else var taskSource = new TaskCompletionSource<bool>(); try { - _Socket.BeginSendTo(messageData, 0, messageData.Length, SocketFlags.None, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IpAddress.ToString()), endPoint.Port), result => + _Socket.BeginSendTo(buffer, 0, size, SocketFlags.None, new System.Net.IPEndPoint(IPAddress.Parse(endPoint.IpAddress.ToString()), endPoint.Port), result => { try { @@ -160,11 +162,11 @@ namespace Emby.Common.Implementations.Net var ipEndPoint = state.EndPoint as IPEndPoint; state.TaskCompletionSource.SetResult( - new ReceivedUdpData() + new SocketReceiveResult() { Buffer = state.Buffer, ReceivedBytes = bytesRead, - ReceivedFrom = ToIpEndPointInfo(ipEndPoint) + RemoteEndPoint = ToIpEndPointInfo(ipEndPoint) } ); } @@ -215,11 +217,11 @@ namespace Emby.Common.Implementations.Net var ipEndPoint = state.EndPoint as IPEndPoint; state.TaskCompletionSource.SetResult( - new ReceivedUdpData() + new SocketReceiveResult { Buffer = state.Buffer, ReceivedBytes = bytesRead, - ReceivedFrom = ToIpEndPointInfo(ipEndPoint) + RemoteEndPoint = ToIpEndPointInfo(ipEndPoint) } ); } @@ -258,7 +260,7 @@ namespace Emby.Common.Implementations.Net public System.Net.Sockets.Socket Socket { get; private set; } - public TaskCompletionSource<ReceivedUdpData> TaskCompletionSource { get; set; } + public TaskCompletionSource<SocketReceiveResult> TaskCompletionSource { get; set; } } diff --git a/Emby.Common.Implementations/Networking/BaseNetworkManager.cs b/Emby.Common.Implementations/Networking/BaseNetworkManager.cs index bab340e27..d1c299dc9 100644 --- a/Emby.Common.Implementations/Networking/BaseNetworkManager.cs +++ b/Emby.Common.Implementations/Networking/BaseNetworkManager.cs @@ -8,6 +8,7 @@ using System.Net.NetworkInformation; using System.Net.Sockets; using System.Threading.Tasks; using MediaBrowser.Model.Extensions; +using MediaBrowser.Model.Net; namespace Emby.Common.Implementations.Networking { @@ -382,5 +383,35 @@ namespace Emby.Common.Implementations.Networking return hosts[0]; } + + public IpAddressInfo ParseIpAddress(string ipAddress) + { + IpAddressInfo info; + if (TryParseIpAddress(ipAddress, out info)) + { + return info; + } + + throw new ArgumentException("Invalid ip address: " + ipAddress); + } + + public bool TryParseIpAddress(string ipAddress, out IpAddressInfo ipAddressInfo) + { + IPAddress address; + if (IPAddress.TryParse(ipAddress, out address)) + { + + ipAddressInfo = new IpAddressInfo + { + Address = address.ToString(), + IsIpv6 = address.AddressFamily == AddressFamily.InterNetworkV6 + }; + + return true; + } + + ipAddressInfo = null; + return false; + } } } |
