aboutsummaryrefslogtreecommitdiff
path: root/Emby.Common.Implementations/Net
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-11-08 13:44:23 -0500
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-11-08 13:44:23 -0500
commita8b340cbb29dbcf7fd5d101e640d66470c6d32bf (patch)
treea626c151e9ccb8809dd6d667fb9146fe4bb3ffea /Emby.Common.Implementations/Net
parent05a5ce58a9293f6669960c735911e9455c5d8188 (diff)
update portable projects
Diffstat (limited to 'Emby.Common.Implementations/Net')
-rw-r--r--Emby.Common.Implementations/Net/NetSocket.cs85
-rw-r--r--Emby.Common.Implementations/Net/SocketAcceptor.cs111
-rw-r--r--Emby.Common.Implementations/Net/SocketFactory.cs37
-rw-r--r--Emby.Common.Implementations/Net/UdpSocket.cs12
4 files changed, 223 insertions, 22 deletions
diff --git a/Emby.Common.Implementations/Net/NetSocket.cs b/Emby.Common.Implementations/Net/NetSocket.cs
new file mode 100644
index 000000000..72faa41a9
--- /dev/null
+++ b/Emby.Common.Implementations/Net/NetSocket.cs
@@ -0,0 +1,85 @@
+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 NetSocket(Socket socket, ILogger logger)
+ {
+ Socket = socket;
+ _logger = logger;
+ }
+
+ public IpEndPointInfo LocalEndPoint
+ {
+ get
+ {
+ return BaseNetworkManager.ToIpEndPointInfo((IPEndPoint)Socket.LocalEndPoint);
+ }
+ }
+
+ public IpEndPointInfo RemoteEndPoint
+ {
+ get
+ {
+ return BaseNetworkManager.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 = BaseNetworkManager.ToIPEndPoint(endpoint);
+
+ Socket.Bind(nativeEndpoint);
+ }
+
+ private SocketAcceptor _acceptor;
+ public void StartAccept(Action<ISocket> onAccept, Func<bool> isClosed)
+ {
+ _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed);
+
+ _acceptor.StartAccept();
+ }
+
+ public void Dispose()
+ {
+ Socket.Dispose();
+ }
+ }
+}
diff --git a/Emby.Common.Implementations/Net/SocketAcceptor.cs b/Emby.Common.Implementations/Net/SocketAcceptor.cs
new file mode 100644
index 000000000..fd65e9fbc
--- /dev/null
+++ b/Emby.Common.Implementations/Net/SocketAcceptor.cs
@@ -0,0 +1,111 @@
+using System;
+using System.Net.Sockets;
+using MediaBrowser.Model.Logging;
+using MediaBrowser.Model.Net;
+
+namespace Emby.Common.Implementations.Net
+{
+ public class SocketAcceptor
+ {
+ private readonly ILogger _logger;
+ private readonly Socket _originalSocket;
+ private readonly Func<bool> _isClosed;
+ private readonly Action<ISocket> _onAccept;
+
+ public SocketAcceptor(ILogger logger, Socket originalSocket, Action<ISocket> onAccept, Func<bool> isClosed)
+ {
+ _logger = logger;
+ _originalSocket = originalSocket;
+ _isClosed = isClosed;
+ _onAccept = onAccept;
+ }
+
+ public void StartAccept()
+ {
+ Socket dummy = null;
+ StartAccept(null, ref dummy);
+ }
+
+ public void StartAccept(SocketAsyncEventArgs acceptEventArg, ref Socket accepted)
+ {
+ if (acceptEventArg == null)
+ {
+ acceptEventArg = new SocketAsyncEventArgs();
+ acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(AcceptEventArg_Completed);
+ }
+ else
+ {
+ // socket must be cleared since the context object is being reused
+ acceptEventArg.AcceptSocket = null;
+ }
+
+ try
+ {
+ bool willRaiseEvent = _originalSocket.AcceptAsync(acceptEventArg);
+
+ if (!willRaiseEvent)
+ {
+ ProcessAccept(acceptEventArg);
+ }
+ }
+ catch (Exception ex)
+ {
+ if (accepted != null)
+ {
+ try
+ {
+#if NET46
+ accepted.Close();
+#else
+ accepted.Dispose();
+#endif
+ }
+ catch
+ {
+ }
+ accepted = null;
+ }
+ }
+ }
+
+ // This method is the callback method associated with Socket.AcceptAsync
+ // operations and is invoked when an accept operation is complete
+ //
+ void AcceptEventArg_Completed(object sender, SocketAsyncEventArgs e)
+ {
+ ProcessAccept(e);
+ }
+
+ private void ProcessAccept(SocketAsyncEventArgs e)
+ {
+ if (_isClosed())
+ {
+ return;
+ }
+
+ // http://msdn.microsoft.com/en-us/library/system.net.sockets.socket.acceptasync%28v=vs.110%29.aspx
+ // Under certain conditions ConnectionReset can occur
+ // Need to attept to re-accept
+ if (e.SocketError == SocketError.ConnectionReset)
+ {
+ _logger.Error("SocketError.ConnectionReset reported. Attempting to re-accept.");
+ Socket dummy = null;
+ StartAccept(e, ref dummy);
+ return;
+ }
+
+ var acceptSocket = e.AcceptSocket;
+ if (acceptSocket != null)
+ {
+ //ProcessAccept(acceptSocket);
+ _onAccept(new NetSocket(acceptSocket, _logger));
+ }
+
+ if (_originalSocket != null)
+ {
+ // Accept the next connection request
+ StartAccept(e, ref acceptSocket);
+ }
+ }
+ }
+}
diff --git a/Emby.Common.Implementations/Net/SocketFactory.cs b/Emby.Common.Implementations/Net/SocketFactory.cs
index bb38c72da..922b0f3cc 100644
--- a/Emby.Common.Implementations/Net/SocketFactory.cs
+++ b/Emby.Common.Implementations/Net/SocketFactory.cs
@@ -4,6 +4,7 @@ using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
+using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
namespace Emby.Common.Implementations.Net
@@ -22,16 +23,28 @@ namespace Emby.Common.Implementations.Net
/// </summary>
private IPAddress _LocalIP;
- /// <summary>
- /// Default constructor.
- /// </summary>
- /// <param name="localIP">A string containing the IP address of the local network adapter to bind sockets to. Null or empty string will use <see cref="IPAddress.Any"/>.</param>
- public SocketFactory(string localIP)
+ private ILogger _logger;
+
+ public SocketFactory(ILogger logger)
+ {
+ _logger = logger;
+ _LocalIP = IPAddress.Any;
+ }
+
+ public ISocket CreateSocket(IpAddressFamily family, MediaBrowser.Model.Net.SocketType socketType, MediaBrowser.Model.Net.ProtocolType protocolType, bool dualMode)
{
- if (String.IsNullOrEmpty(localIP))
- _LocalIP = IPAddress.Any;
- else
- _LocalIP = IPAddress.Parse(localIP);
+ var addressFamily = family == IpAddressFamily.InterNetwork
+ ? AddressFamily.InterNetwork
+ : AddressFamily.InterNetworkV6;
+
+ var socket = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
+
+ if (dualMode)
+ {
+ socket.DualMode = true;
+ }
+
+ return new NetSocket(socket, _logger);
}
#region ISocketFactory Members
@@ -44,7 +57,7 @@ namespace Emby.Common.Implementations.Net
{
if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort");
- var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
try
{
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
@@ -68,7 +81,7 @@ namespace Emby.Common.Implementations.Net
{
if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort");
- var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
try
{
retVal.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
@@ -99,7 +112,7 @@ namespace Emby.Common.Implementations.Net
if (multicastTimeToLive <= 0) throw new ArgumentException("multicastTimeToLive cannot be zero or less.", "multicastTimeToLive");
if (localPort < 0) throw new ArgumentException("localPort cannot be less than zero.", "localPort");
- var retVal = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
+ var retVal = new Socket(AddressFamily.InterNetwork, System.Net.Sockets.SocketType.Dgram, System.Net.Sockets.ProtocolType.Udp);
try
{
diff --git a/Emby.Common.Implementations/Net/UdpSocket.cs b/Emby.Common.Implementations/Net/UdpSocket.cs
index d999d3fe8..244b37bb4 100644
--- a/Emby.Common.Implementations/Net/UdpSocket.cs
+++ b/Emby.Common.Implementations/Net/UdpSocket.cs
@@ -5,6 +5,7 @@ using System.Net;
using System.Net.Sockets;
using System.Security;
using System.Threading.Tasks;
+using Emby.Common.Implementations.Networking;
using MediaBrowser.Model.Net;
namespace Emby.Common.Implementations.Net
@@ -174,16 +175,7 @@ namespace Emby.Common.Implementations.Net
return null;
}
- return new IpEndPointInfo
- {
- IpAddress = new IpAddressInfo
- {
- Address = endpoint.Address.ToString(),
- IsIpv6 = endpoint.AddressFamily == AddressFamily.InterNetworkV6
- },
-
- Port = endpoint.Port
- };
+ return BaseNetworkManager.ToIpEndPointInfo(endpoint);
}
private void ProcessResponse(IAsyncResult asyncResult)