From 9776ca09db59a1e382045a072813a29cf07cadb3 Mon Sep 17 00:00:00 2001 From: Luke Pulverenti Date: Thu, 2 Mar 2017 15:50:09 -0500 Subject: update socket interfaces --- Emby.Common.Implementations/Net/NetAcceptSocket.cs | 97 ++++++++++++++++++++++ Emby.Common.Implementations/Net/NetSocket.cs | 97 ---------------------- Emby.Common.Implementations/Net/SocketAcceptor.cs | 10 +-- Emby.Common.Implementations/Net/SocketFactory.cs | 47 +++++++---- Emby.Common.Implementations/Net/UdpSocket.cs | 16 ++-- 5 files changed, 143 insertions(+), 124 deletions(-) create mode 100644 Emby.Common.Implementations/Net/NetAcceptSocket.cs delete mode 100644 Emby.Common.Implementations/Net/NetSocket.cs (limited to 'Emby.Common.Implementations/Net') diff --git a/Emby.Common.Implementations/Net/NetAcceptSocket.cs b/Emby.Common.Implementations/Net/NetAcceptSocket.cs new file mode 100644 index 000000000..0672a9e98 --- /dev/null +++ b/Emby.Common.Implementations/Net/NetAcceptSocket.cs @@ -0,0 +1,97 @@ +using System; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using Emby.Common.Implementations.Networking; +using MediaBrowser.Model.Net; +using MediaBrowser.Model.Logging; + +namespace Emby.Common.Implementations.Net +{ + public class NetAcceptSocket : IAcceptSocket + { + public Socket Socket { get; private set; } + private readonly ILogger _logger; + + public bool DualMode { get; private set; } + + public NetAcceptSocket(Socket socket, ILogger logger, bool isDualMode) + { + if (socket == null) + { + throw new ArgumentNullException("socket"); + } + if (logger == null) + { + throw new ArgumentNullException("logger"); + } + + Socket = socket; + _logger = logger; + DualMode = isDualMode; + } + + public IpEndPointInfo LocalEndPoint + { + get + { + return NetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.LocalEndPoint); + } + } + + public IpEndPointInfo RemoteEndPoint + { + get + { + return NetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.RemoteEndPoint); + } + } + + public void Close() + { +#if NET46 + Socket.Close(); +#else + Socket.Dispose(); +#endif + } + + public void Shutdown(bool both) + { + if (both) + { + Socket.Shutdown(SocketShutdown.Both); + } + else + { + // Change interface if ever needed + throw new NotImplementedException(); + } + } + + public void Listen(int backlog) + { + Socket.Listen(backlog); + } + + public void Bind(IpEndPointInfo endpoint) + { + var nativeEndpoint = NetworkManager.ToIPEndPoint(endpoint); + + Socket.Bind(nativeEndpoint); + } + + private SocketAcceptor _acceptor; + public void StartAccept(Action onAccept, Func isClosed) + { + _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed, DualMode); + + _acceptor.StartAccept(); + } + + public void Dispose() + { + Socket.Dispose(); + } + } +} diff --git a/Emby.Common.Implementations/Net/NetSocket.cs b/Emby.Common.Implementations/Net/NetSocket.cs deleted file mode 100644 index bc012dfe2..000000000 --- a/Emby.Common.Implementations/Net/NetSocket.cs +++ /dev/null @@ -1,97 +0,0 @@ -using System; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using Emby.Common.Implementations.Networking; -using MediaBrowser.Model.Net; -using MediaBrowser.Model.Logging; - -namespace Emby.Common.Implementations.Net -{ - public class NetSocket : ISocket - { - public Socket Socket { get; private set; } - private readonly ILogger _logger; - - public bool DualMode { get; private set; } - - public NetSocket(Socket socket, ILogger logger, bool isDualMode) - { - if (socket == null) - { - throw new ArgumentNullException("socket"); - } - if (logger == null) - { - throw new ArgumentNullException("logger"); - } - - Socket = socket; - _logger = logger; - DualMode = isDualMode; - } - - public IpEndPointInfo LocalEndPoint - { - get - { - return NetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.LocalEndPoint); - } - } - - public IpEndPointInfo RemoteEndPoint - { - get - { - return NetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.RemoteEndPoint); - } - } - - public void Close() - { -#if NET46 - Socket.Close(); -#else - Socket.Dispose(); -#endif - } - - public void Shutdown(bool both) - { - if (both) - { - Socket.Shutdown(SocketShutdown.Both); - } - else - { - // Change interface if ever needed - throw new NotImplementedException(); - } - } - - public void Listen(int backlog) - { - Socket.Listen(backlog); - } - - public void Bind(IpEndPointInfo endpoint) - { - var nativeEndpoint = NetworkManager.ToIPEndPoint(endpoint); - - Socket.Bind(nativeEndpoint); - } - - private SocketAcceptor _acceptor; - public void StartAccept(Action onAccept, Func isClosed) - { - _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed, DualMode); - - _acceptor.StartAccept(); - } - - public void Dispose() - { - Socket.Dispose(); - } - } -} diff --git a/Emby.Common.Implementations/Net/SocketAcceptor.cs b/Emby.Common.Implementations/Net/SocketAcceptor.cs index d4c6d33e5..11a8e5381 100644 --- a/Emby.Common.Implementations/Net/SocketAcceptor.cs +++ b/Emby.Common.Implementations/Net/SocketAcceptor.cs @@ -10,10 +10,10 @@ namespace Emby.Common.Implementations.Net private readonly ILogger _logger; private readonly Socket _originalSocket; private readonly Func _isClosed; - private readonly Action _onAccept; + private readonly Action _onAccept; private readonly bool _isDualMode; - public SocketAcceptor(ILogger logger, Socket originalSocket, Action onAccept, Func isClosed, bool isDualMode) + public SocketAcceptor(ILogger logger, Socket originalSocket, Action onAccept, Func isClosed, bool isDualMode) { if (logger == null) { @@ -54,7 +54,7 @@ namespace Emby.Common.Implementations.Net } else { - // socket must be cleared since the context object is being reused + // acceptSocket must be cleared since the context object is being reused acceptEventArg.AcceptSocket = null; } @@ -102,7 +102,7 @@ namespace Emby.Common.Implementations.Net return; } - // http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.acceptasync%28v=vs.110%29.aspx + // http://msdn.microsoft.com/en-us/library/system.net.sockets.acceptSocket.acceptasync%28v=vs.110%29.aspx // Under certain conditions ConnectionReset can occur // Need to attept to re-accept if (e.SocketError == SocketError.ConnectionReset) @@ -117,7 +117,7 @@ namespace Emby.Common.Implementations.Net if (acceptSocket != null) { //ProcessAccept(acceptSocket); - _onAccept(new NetSocket(acceptSocket, _logger, _isDualMode)); + _onAccept(new NetAcceptSocket(acceptSocket, _logger, _isDualMode)); } // Accept the next connection request diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs index 70c7ba845..bb964fe00 100644 --- a/Emby.Common.Implementations/Net/SocketFactory.cs +++ b/Emby.Common.Implementations/Net/SocketFactory.cs @@ -31,7 +31,7 @@ namespace Emby.Common.Implementations.Net _logger = logger; } - public ISocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode) + public IAcceptSocket CreateAcceptSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode) { try { @@ -46,7 +46,7 @@ namespace Emby.Common.Implementations.Net socket.DualMode = true; } - return new NetSocket(socket, _logger, dualMode); + return new NetAcceptSocket(socket, _logger, dualMode); } catch (SocketException ex) { @@ -54,13 +54,30 @@ namespace Emby.Common.Implementations.Net } } - #region ISocketFactory Members + public ISocket CreateTcpSocket(IpAddressInfo remoteAddress, int remotePort) + { + if (remotePort < 0) throw new ArgumentException("remotePort cannot be less than zero.", "remotePort"); + + var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp); + try + { + retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true); + return new UdpSocket(retVal, new IpEndPointInfo(remoteAddress, remotePort)); + } + catch + { + if (retVal != null) + retVal.Dispose(); + + throw; + } + } /// - /// Creates a new UDP socket and binds it to the specified local port. + /// Creates a new UDP acceptSocket and binds it to the specified local port. /// - /// An integer specifying the local port to bind the socket to. - public IUdpSocket CreateUdpSocket(int localPort) + /// An integer specifying the local port to bind the acceptSocket to. + public ISocket CreateUdpSocket(int localPort) { if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); @@ -80,10 +97,10 @@ namespace Emby.Common.Implementations.Net } /// - /// Creates a new UDP socket that is a member of the SSDP multicast local admin group and binds it to the specified local port. + /// 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 socket operations. - public IUdpSocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort) + /// An implementation of the interface used by RSSDP components to perform acceptSocket operations. + public ISocket CreateSsdpUdpSocket(IpAddressInfo localIpAddress, int localPort) { if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort"); @@ -108,13 +125,13 @@ namespace Emby.Common.Implementations.Net } /// - /// Creates a new UDP socket that is a member of the specified multicast IP address, and binds it to the specified local port. + /// Creates a new UDP acceptSocket that is a member of the specified multicast IP address, and binds it to the specified local port. /// - /// The multicast IP address to make the socket a member of. - /// The multicast time to live value for the socket. + /// The multicast IP address to make the acceptSocket a member of. + /// The multicast time to live value for the acceptSocket. /// The number of the local port to bind to. /// - public IUdpSocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort) + public ISocket CreateUdpMulticastSocket(string ipAddress, int multicastTimeToLive, int localPort) { if (ipAddress == null) throw new ArgumentNullException("ipAddress"); if (ipAddress.Length == 0) throw new ArgumentException("ipAddress cannot be an empty string.", "ipAddress"); @@ -128,7 +145,7 @@ namespace Emby.Common.Implementations.Net #if NET46 retVal.ExclusiveAddressUse = false; #else - // The ExclusiveAddressUse socket option is a Windows-specific option that, when set to "true," tells Windows not to allow another socket to use the same local address as this socket + // The ExclusiveAddressUse acceptSocket option is a Windows-specific option that, when set to "true," tells Windows not to allow another acceptSocket to use the same local address as this acceptSocket // See https://github.com/dotnet/corefx/pull/11509 for more details if (System.Runtime.InteropServices.RuntimeInformation.IsOSPlatform(System.Runtime.InteropServices.OSPlatform.Windows)) { @@ -154,7 +171,5 @@ namespace Emby.Common.Implementations.Net throw; } } - - #endregion } } diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs index e4b0c7d6d..8e2a1da6f 100644 --- a/Emby.Common.Implementations/Net/UdpSocket.cs +++ b/Emby.Common.Implementations/Net/UdpSocket.cs @@ -14,7 +14,7 @@ namespace Emby.Common.Implementations.Net // 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. - internal sealed class UdpSocket : DisposableManagedObjectBase, IUdpSocket + internal sealed class UdpSocket : DisposableManagedObjectBase, ISocket { #region Fields @@ -23,8 +23,6 @@ namespace Emby.Common.Implementations.Net private int _LocalPort; #endregion - #region Constructors - public UdpSocket(Socket socket, int localPort, IPAddress ip) { if (socket == null) throw new ArgumentNullException("socket"); @@ -36,7 +34,13 @@ namespace Emby.Common.Implementations.Net _Socket.Bind(new IPEndPoint(ip, _LocalPort)); } - #endregion + public UdpSocket(Socket socket, IpEndPointInfo endPoint) + { + if (socket == null) throw new ArgumentNullException("socket"); + + _Socket = socket; + _Socket.Connect(NetworkManager.ToIPEndPoint(endPoint)); + } public IpAddressInfo LocalIPAddress { @@ -44,9 +48,9 @@ namespace Emby.Common.Implementations.Net private set; } - #region IUdpSocket Members + #region ISocket Members - public Task ReceiveAsync() + public Task ReceiveAsync(CancellationToken cancellationToken) { ThrowIfDisposed(); -- cgit v1.2.3