aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Pulverenti <luke.pulverenti@gmail.com>2016-12-07 15:02:34 -0500
committerLuke Pulverenti <luke.pulverenti@gmail.com>2016-12-07 15:02:34 -0500
commit0130209cdce07dc042b075c6cf972a7eb1339861 (patch)
treeaede8b599fe887f206fbe703e023ed3677ea5f4f
parent20c249979759a836f63a886a871db69ceaeb757e (diff)
improve ipv6 error handling
-rw-r--r--Emby.Common.Implementations/Net/NetSocket.cs7
-rw-r--r--Emby.Common.Implementations/Net/SocketAcceptor.cs6
-rw-r--r--Emby.Common.Implementations/Net/SocketFactory.cs14
-rw-r--r--Emby.Server.Core/ApplicationHost.cs47
-rw-r--r--MediaBrowser.Model/Net/ISocket.cs12
-rw-r--r--SocketHttpListener.Portable/Net/EndPointListener.cs20
6 files changed, 80 insertions, 26 deletions
diff --git a/Emby.Common.Implementations/Net/NetSocket.cs b/Emby.Common.Implementations/Net/NetSocket.cs
index 62ca3d6ac..bc012dfe2 100644
--- a/Emby.Common.Implementations/Net/NetSocket.cs
+++ b/Emby.Common.Implementations/Net/NetSocket.cs
@@ -13,7 +13,9 @@ namespace Emby.Common.Implementations.Net
public Socket Socket { get; private set; }
private readonly ILogger _logger;
- public NetSocket(Socket socket, ILogger logger)
+ public bool DualMode { get; private set; }
+
+ public NetSocket(Socket socket, ILogger logger, bool isDualMode)
{
if (socket == null)
{
@@ -26,6 +28,7 @@ namespace Emby.Common.Implementations.Net
Socket = socket;
_logger = logger;
+ DualMode = isDualMode;
}
public IpEndPointInfo LocalEndPoint
@@ -81,7 +84,7 @@ namespace Emby.Common.Implementations.Net
private SocketAcceptor _acceptor;
public void StartAccept(Action<ISocket> onAccept, Func<bool> isClosed)
{
- _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed);
+ _acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed, DualMode);
_acceptor.StartAccept();
}
diff --git a/Emby.Common.Implementations/Net/SocketAcceptor.cs b/Emby.Common.Implementations/Net/SocketAcceptor.cs
index bddb7a079..d4c6d33e5 100644
--- a/Emby.Common.Implementations/Net/SocketAcceptor.cs
+++ b/Emby.Common.Implementations/Net/SocketAcceptor.cs
@@ -11,8 +11,9 @@ namespace Emby.Common.Implementations.Net
private readonly Socket _originalSocket;
private readonly Func<bool> _isClosed;
private readonly Action<ISocket> _onAccept;
+ private readonly bool _isDualMode;
- public SocketAcceptor(ILogger logger, Socket originalSocket, Action<ISocket> onAccept, Func<bool> isClosed)
+ public SocketAcceptor(ILogger logger, Socket originalSocket, Action<ISocket> onAccept, Func<bool> isClosed, bool isDualMode)
{
if (logger == null)
{
@@ -34,6 +35,7 @@ namespace Emby.Common.Implementations.Net
_logger = logger;
_originalSocket = originalSocket;
_isClosed = isClosed;
+ _isDualMode = isDualMode;
_onAccept = onAccept;
}
@@ -115,7 +117,7 @@ namespace Emby.Common.Implementations.Net
if (acceptSocket != null)
{
//ProcessAccept(acceptSocket);
- _onAccept(new NetSocket(acceptSocket, _logger));
+ _onAccept(new NetSocket(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 79310e017..1f41ffff5 100644
--- a/Emby.Common.Implementations/Net/SocketFactory.cs
+++ b/Emby.Common.Implementations/Net/SocketFactory.cs
@@ -46,21 +46,11 @@ namespace Emby.Common.Implementations.Net
socket.DualMode = true;
}
- return new NetSocket(socket, _logger);
+ return new NetSocket(socket, _logger, dualMode);
}
catch (SocketException ex)
{
- if (dualMode)
- {
- _logger.Error("Error creating dual mode socket: {0}. Will retry with ipv4-only.", ex.SocketErrorCode);
-
- if (ex.SocketErrorCode == SocketError.AddressFamilyNotSupported)
- {
- return CreateSocket(IpAddressFamily.InterNetwork, socketType, protocolType, false);
- }
- }
-
- throw;
+ throw new SocketCreateException(ex.SocketErrorCode.ToString(), ex);
}
}
diff --git a/Emby.Server.Core/ApplicationHost.cs b/Emby.Server.Core/ApplicationHost.cs
index f7fe02fba..06c761f21 100644
--- a/Emby.Server.Core/ApplicationHost.cs
+++ b/Emby.Server.Core/ApplicationHost.cs
@@ -1305,19 +1305,49 @@ namespace Emby.Server.Core
public async Task<List<IpAddressInfo>> GetLocalIpAddresses()
{
- var addresses = NetworkManager.GetLocalIpAddresses().ToList();
- var list = new List<IpAddressInfo>();
+ var addresses = ServerConfigurationManager
+ .Configuration
+ .LocalNetworkAddresses
+ .Select(NormalizeConfiguredLocalAddress)
+ .Where(i => i != null)
+ .ToList();
- foreach (var address in addresses)
+ if (addresses.Count == 0)
{
- var valid = await IsIpAddressValidAsync(address).ConfigureAwait(false);
- if (valid)
+ addresses.AddRange(NetworkManager.GetLocalIpAddresses());
+
+ var list = new List<IpAddressInfo>();
+
+ foreach (var address in addresses)
{
- list.Add(address);
+ var valid = await IsIpAddressValidAsync(address).ConfigureAwait(false);
+ if (valid)
+ {
+ list.Add(address);
+ }
}
+
+ addresses = list;
}
- return list;
+ return addresses;
+ }
+
+ private IpAddressInfo NormalizeConfiguredLocalAddress(string address)
+ {
+ var index = address.Trim('/').IndexOf('/');
+
+ if (index != -1)
+ {
+ address = address.Substring(index + 1);
+ }
+
+ IpAddressInfo result;
+ if (NetworkManager.TryParseIpAddress(address.Trim('/'), out result))
+ {
+ return result;
+ }
+ return null;
}
private readonly ConcurrentDictionary<string, bool> _validAddressResults = new ConcurrentDictionary<string, bool>(StringComparer.OrdinalIgnoreCase);
@@ -1553,7 +1583,8 @@ namespace Emby.Server.Core
throw new NotImplementedException();
}
- var process = ProcessFactory.Create(new ProcessOptions {
+ var process = ProcessFactory.Create(new ProcessOptions
+ {
FileName = url,
EnableRaisingEvents = true,
UseShellExecute = true,
diff --git a/MediaBrowser.Model/Net/ISocket.cs b/MediaBrowser.Model/Net/ISocket.cs
index 371fbc567..aed35bce8 100644
--- a/MediaBrowser.Model/Net/ISocket.cs
+++ b/MediaBrowser.Model/Net/ISocket.cs
@@ -4,6 +4,7 @@ namespace MediaBrowser.Model.Net
{
public interface ISocket : IDisposable
{
+ bool DualMode { get; }
IpEndPointInfo LocalEndPoint { get; }
IpEndPointInfo RemoteEndPoint { get; }
void Close();
@@ -13,4 +14,15 @@ namespace MediaBrowser.Model.Net
void StartAccept(Action<ISocket> onAccept, Func<bool> isClosed);
}
+
+ public class SocketCreateException : Exception
+ {
+ public SocketCreateException(string errorCode, Exception originalException)
+ : base(errorCode, originalException)
+ {
+ ErrorCode = errorCode;
+ }
+
+ public string ErrorCode { get; private set; }
+ }
}
diff --git a/SocketHttpListener.Portable/Net/EndPointListener.cs b/SocketHttpListener.Portable/Net/EndPointListener.cs
index 52385e2ba..690dedd09 100644
--- a/SocketHttpListener.Portable/Net/EndPointListener.cs
+++ b/SocketHttpListener.Portable/Net/EndPointListener.cs
@@ -26,7 +26,7 @@ namespace SocketHttpListener.Net
Dictionary<HttpConnection, HttpConnection> unregistered;
private readonly ILogger _logger;
private bool _closed;
- private readonly bool _enableDualMode;
+ private bool _enableDualMode;
private readonly ICryptoProvider _cryptoProvider;
private readonly IStreamFactory _streamFactory;
private readonly ISocketFactory _socketFactory;
@@ -65,7 +65,23 @@ namespace SocketHttpListener.Net
private void CreateSocket()
{
- sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode);
+ try
+ {
+ sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode);
+ }
+ catch (SocketCreateException ex)
+ {
+ if (_enableDualMode && endpoint.IpAddress.Equals(IpAddressInfo.IPv6Any) && string.Equals(ex.ErrorCode, "AddressFamilyNotSupported", StringComparison.OrdinalIgnoreCase))
+ {
+ endpoint = new IpEndPointInfo(IpAddressInfo.Any, endpoint.Port);
+ _enableDualMode = false;
+ sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode);
+ }
+ else
+ {
+ throw;
+ }
+ }
sock.Bind(endpoint);