update SocketHttpListener

This commit is contained in:
Luke Pulverenti
2017-09-02 22:42:13 -04:00
parent da3d8894a8
commit 78165d78a2
22 changed files with 214 additions and 274 deletions
@@ -128,6 +128,7 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Tasks;
using MediaBrowser.Model.Threading;
using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions;
using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate;
namespace Emby.Server.Implementations
{
@@ -1168,7 +1169,7 @@ namespace Emby.Server.Implementations
}
}
private ICertificate GetCertificate(CertificateInfo info)
private X509Certificate GetCertificate(CertificateInfo info)
{
var certificateLocation = info == null ? null : info.Path;
@@ -1195,7 +1196,7 @@ namespace Emby.Server.Implementations
return null;
}
return new Certificate(localCert);
return localCert;
}
catch (Exception ex)
{
@@ -1584,7 +1585,7 @@ namespace Emby.Server.Implementations
}
private CertificateInfo CertificateInfo { get; set; }
private ICertificate Certificate { get; set; }
private X509Certificate Certificate { get; set; }
private IEnumerable<string> GetUrlPrefixes()
{
@@ -440,7 +440,6 @@
<Compile Include="Networking\NetworkManager.cs" />
<Compile Include="Net\DisposableManagedObjectBase.cs" />
<Compile Include="Net\NetAcceptSocket.cs" />
<Compile Include="Net\SocketAcceptor.cs" />
<Compile Include="Net\SocketFactory.cs" />
<Compile Include="Net\UdpSocket.cs" />
<Compile Include="News\NewsEntryPoint.cs" />
@@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
@@ -55,9 +56,8 @@ namespace Emby.Server.Implementations.HttpServer
private readonly IFileSystem _fileSystem;
private readonly IJsonSerializer _jsonSerializer;
private readonly IXmlSerializer _xmlSerializer;
private readonly ICertificate _certificate;
private readonly X509Certificate _certificate;
private readonly IEnvironmentInfo _environment;
private readonly IStreamFactory _streamFactory;
private readonly Func<Type, Func<string, object>> _funcParseFn;
private readonly bool _enableDualModeSockets;
@@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.HttpServer
ILogger logger,
IServerConfigurationManager config,
string serviceName,
string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IJsonSerializer jsonSerializer, IXmlSerializer xmlSerializer, IEnvironmentInfo environment, ICertificate certificate, IStreamFactory streamFactory, Func<Type, Func<string, object>> funcParseFn, bool enableDualModeSockets, IFileSystem fileSystem)
string defaultRedirectPath, INetworkManager networkManager, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IJsonSerializer jsonSerializer, IXmlSerializer xmlSerializer, IEnvironmentInfo environment, X509Certificate certificate, Func<Type, Func<string, object>> funcParseFn, bool enableDualModeSockets, IFileSystem fileSystem)
{
Instance = this;
@@ -86,7 +86,6 @@ namespace Emby.Server.Implementations.HttpServer
_xmlSerializer = xmlSerializer;
_environment = environment;
_certificate = certificate;
_streamFactory = streamFactory;
_funcParseFn = funcParseFn;
_enableDualModeSockets = enableDualModeSockets;
_fileSystem = fileSystem;
@@ -204,7 +203,6 @@ namespace Emby.Server.Implementations.HttpServer
_networkManager,
_socketFactory,
_cryptoProvider,
_streamFactory,
_enableDualModeSockets,
GetRequest,
_fileSystem,
@@ -4,6 +4,7 @@ using SocketHttpListener.Net;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Common.Net;
@@ -22,13 +23,12 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
private HttpListener _listener;
private readonly ILogger _logger;
private readonly ICertificate _certificate;
private readonly X509Certificate _certificate;
private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly ITextEncoding _textEncoding;
private readonly INetworkManager _networkManager;
private readonly ISocketFactory _socketFactory;
private readonly ICryptoProvider _cryptoProvider;
private readonly IStreamFactory _streamFactory;
private readonly IFileSystem _fileSystem;
private readonly Func<HttpListenerContext, IHttpRequest> _httpRequestFactory;
private readonly bool _enableDualMode;
@@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
private CancellationToken _disposeCancellationToken;
public WebSocketSharpListener(ILogger logger, ICertificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, bool enableDualMode, Func<HttpListenerContext, IHttpRequest> httpRequestFactory, IFileSystem fileSystem, IEnvironmentInfo environment)
public WebSocketSharpListener(ILogger logger, X509Certificate certificate, IMemoryStreamFactory memoryStreamProvider, ITextEncoding textEncoding, INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider, bool enableDualMode, Func<HttpListenerContext, IHttpRequest> httpRequestFactory, IFileSystem fileSystem, IEnvironmentInfo environment)
{
_logger = logger;
_certificate = certificate;
@@ -46,7 +46,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
_networkManager = networkManager;
_socketFactory = socketFactory;
_cryptoProvider = cryptoProvider;
_streamFactory = streamFactory;
_enableDualMode = enableDualMode;
_httpRequestFactory = httpRequestFactory;
_fileSystem = fileSystem;
@@ -65,7 +64,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
public void Start(IEnumerable<string> urlPrefixes)
{
if (_listener == null)
_listener = new HttpListener(_logger, _cryptoProvider, _streamFactory, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider, _fileSystem, _environment);
_listener = new HttpListener(_logger, _cryptoProvider, _socketFactory, _networkManager, _textEncoding, _memoryStreamProvider, _fileSystem, _environment);
_listener.EnableDualMode = _enableDualMode;
@@ -108,7 +108,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
return remoteIp ??
(remoteIp = (CheckBadChars(XForwardedFor)) ??
(NormalizeIp(CheckBadChars(XRealIp)) ??
(request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.IpAddress.ToString()) : null)));
(request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null)));
}
}
@@ -43,7 +43,7 @@ namespace Emby.Server.Implementations
IJsonSerializer json,
IXmlSerializer xml,
IEnvironmentInfo environment,
ICertificate certificate,
X509Certificate certificate,
IFileSystem fileSystem,
bool enableDualModeSockets)
{
@@ -63,7 +63,6 @@ namespace Emby.Server.Implementations
xml,
environment,
certificate,
new StreamFactory(),
GetParseFn,
enableDualModeSockets,
fileSystem);
@@ -74,37 +73,4 @@ namespace Emby.Server.Implementations
return s => JsvReader.GetParseFn(propertyType)(s);
}
}
public class StreamFactory : IStreamFactory
{
public Stream CreateNetworkStream(IAcceptSocket acceptSocket, bool ownsSocket)
{
var netSocket = (NetAcceptSocket)acceptSocket;
return new SocketStream(netSocket.Socket, ownsSocket);
}
public Task AuthenticateSslStreamAsServer(Stream stream, ICertificate certificate)
{
var sslStream = (SslStream)stream;
var cert = (Certificate)certificate;
return sslStream.AuthenticateAsServerAsync(cert.X509Certificate);
}
public Stream CreateSslStream(Stream innerStream, bool leaveInnerStreamOpen)
{
return new SslStream(innerStream, leaveInnerStreamOpen);
}
}
public class Certificate : ICertificate
{
public Certificate(X509Certificate x509Certificate)
{
X509Certificate = x509Certificate;
}
public X509Certificate X509Certificate { get; private set; }
}
}
@@ -89,63 +89,6 @@ namespace Emby.Server.Implementations.Net
Socket.Bind(nativeEndpoint);
}
private SocketAcceptor _acceptor;
public void StartAccept(Action<IAcceptSocket> onAccept, Func<bool> isClosed)
{
_acceptor = new SocketAcceptor(_logger, Socket, onAccept, isClosed, DualMode);
_acceptor.StartAccept();
}
public Task SendFile(string path, byte[] preBuffer, byte[] postBuffer, CancellationToken cancellationToken)
{
var options = TransmitFileOptions.UseDefaultWorkerThread;
var completionSource = new TaskCompletionSource<bool>();
var result = Socket.BeginSendFile(path, preBuffer, postBuffer, options, new AsyncCallback(FileSendCallback), new Tuple<Socket, string, TaskCompletionSource<bool>>(Socket, path, completionSource));
return completionSource.Task;
}
public IAsyncResult BeginSendFile(string path, byte[] preBuffer, byte[] postBuffer, AsyncCallback callback, object state)
{
var options = TransmitFileOptions.UseDefaultWorkerThread;
return Socket.BeginSendFile(path, preBuffer, postBuffer, options, new AsyncCallback(FileSendCallback), state);
}
public void EndSendFile(IAsyncResult result)
{
Socket.EndSendFile(result);
}
private void FileSendCallback(IAsyncResult ar)
{
// Retrieve the socket from the state object.
Tuple<Socket, string, TaskCompletionSource<bool>> data = (Tuple<Socket, string, TaskCompletionSource<bool>>)ar.AsyncState;
var client = data.Item1;
var path = data.Item2;
var taskCompletion = data.Item3;
// Complete sending the data to the remote device.
try
{
client.EndSendFile(ar);
taskCompletion.TrySetResult(true);
}
catch (SocketException ex)
{
_logger.Info("Socket.SendFile failed for {0}. error code {1}", path, ex.SocketErrorCode);
taskCompletion.TrySetException(ex);
}
catch (Exception ex)
{
taskCompletion.TrySetException(ex);
}
}
public void Dispose()
{
Socket.Dispose();
@@ -1,127 +0,0 @@
using System;
using System.Net.Sockets;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
namespace Emby.Server.Implementations.Net
{
public class SocketAcceptor
{
private readonly ILogger _logger;
private readonly Socket _originalSocket;
private readonly Func<bool> _isClosed;
private readonly Action<IAcceptSocket> _onAccept;
private readonly bool _isDualMode;
public SocketAcceptor(ILogger logger, Socket originalSocket, Action<IAcceptSocket> onAccept, Func<bool> isClosed, bool isDualMode)
{
if (logger == null)
{
throw new ArgumentNullException("logger");
}
if (originalSocket == null)
{
throw new ArgumentNullException("originalSocket");
}
if (onAccept == null)
{
throw new ArgumentNullException("onAccept");
}
if (isClosed == null)
{
throw new ArgumentNullException("isClosed");
}
_logger = logger;
_originalSocket = originalSocket;
_isClosed = isClosed;
_isDualMode = isDualMode;
_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
{
// acceptSocket 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.acceptSocket.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 NetAcceptSocket(acceptSocket, _logger, _isDualMode));
}
// Accept the next connection request
StartAccept(e, ref acceptSocket);
}
}
}