diff options
Diffstat (limited to 'SocketHttpListener.Portable')
| -rw-r--r-- | SocketHttpListener.Portable/Net/EndPointListener.cs | 7 | ||||
| -rw-r--r-- | SocketHttpListener.Portable/Net/EndPointManager.cs | 2 | ||||
| -rw-r--r-- | SocketHttpListener.Portable/Net/HttpConnection.cs | 11 | ||||
| -rw-r--r-- | SocketHttpListener.Portable/Net/HttpListener.cs | 13 | ||||
| -rw-r--r-- | SocketHttpListener.Portable/Net/ResponseStream.cs | 68 |
5 files changed, 84 insertions, 17 deletions
diff --git a/SocketHttpListener.Portable/Net/EndPointListener.cs b/SocketHttpListener.Portable/Net/EndPointListener.cs index 4f1a17fc0..2106bbec5 100644 --- a/SocketHttpListener.Portable/Net/EndPointListener.cs +++ b/SocketHttpListener.Portable/Net/EndPointListener.cs @@ -8,6 +8,7 @@ using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; +using MediaBrowser.Model.System; using MediaBrowser.Model.Text; using SocketHttpListener.Primitives; @@ -33,8 +34,9 @@ namespace SocketHttpListener.Net private readonly ITextEncoding _textEncoding; private readonly IMemoryStreamFactory _memoryStreamFactory; private readonly IFileSystem _fileSystem; + private readonly IEnvironmentInfo _environment; - public EndPointListener(HttpListener listener, IpAddressInfo addr, int port, bool secure, ICertificate cert, ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem) + public EndPointListener(HttpListener listener, IpAddressInfo addr, int port, bool secure, ICertificate cert, ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment) { this.listener = listener; _logger = logger; @@ -44,6 +46,7 @@ namespace SocketHttpListener.Net _memoryStreamFactory = memoryStreamFactory; _textEncoding = textEncoding; _fileSystem = fileSystem; + _environment = environment; this.secure = secure; this.cert = cert; @@ -109,7 +112,7 @@ namespace SocketHttpListener.Net return; } - HttpConnection conn = await HttpConnection.Create(_logger, accepted, listener, listener.secure, listener.cert, _cryptoProvider, _streamFactory, _memoryStreamFactory, _textEncoding, _fileSystem).ConfigureAwait(false); + HttpConnection conn = await HttpConnection.Create(_logger, accepted, listener, listener.secure, listener.cert, _cryptoProvider, _streamFactory, _memoryStreamFactory, _textEncoding, _fileSystem, _environment).ConfigureAwait(false); //_logger.Debug("Adding unregistered connection to {0}. Id: {1}", accepted.RemoteEndPoint, connectionId); lock (listener.unregistered) diff --git a/SocketHttpListener.Portable/Net/EndPointManager.cs b/SocketHttpListener.Portable/Net/EndPointManager.cs index 11f774915..6a00ed360 100644 --- a/SocketHttpListener.Portable/Net/EndPointManager.cs +++ b/SocketHttpListener.Portable/Net/EndPointManager.cs @@ -106,7 +106,7 @@ namespace SocketHttpListener.Net } else { - epl = new EndPointListener(listener, addr, port, secure, listener.Certificate, logger, listener.CryptoProvider, listener.StreamFactory, listener.SocketFactory, listener.MemoryStreamFactory, listener.TextEncoding, listener.FileSystem); + epl = new EndPointListener(listener, addr, port, secure, listener.Certificate, logger, listener.CryptoProvider, listener.StreamFactory, listener.SocketFactory, listener.MemoryStreamFactory, listener.TextEncoding, listener.FileSystem, listener.EnvironmentInfo); p[port] = epl; } diff --git a/SocketHttpListener.Portable/Net/HttpConnection.cs b/SocketHttpListener.Portable/Net/HttpConnection.cs index ac8ada486..65e7470f7 100644 --- a/SocketHttpListener.Portable/Net/HttpConnection.cs +++ b/SocketHttpListener.Portable/Net/HttpConnection.cs @@ -6,6 +6,7 @@ using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; +using MediaBrowser.Model.System; using MediaBrowser.Model.Text; using SocketHttpListener.Primitives; @@ -41,8 +42,9 @@ namespace SocketHttpListener.Net private readonly ITextEncoding _textEncoding; private readonly IStreamFactory _streamFactory; private readonly IFileSystem _fileSystem; + private readonly IEnvironmentInfo _environment; - private HttpConnection(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem) + private HttpConnection(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment) { _logger = logger; this.sock = sock; @@ -53,6 +55,7 @@ namespace SocketHttpListener.Net _memoryStreamFactory = memoryStreamFactory; _textEncoding = textEncoding; _fileSystem = fileSystem; + _environment = environment; _streamFactory = streamFactory; } @@ -84,9 +87,9 @@ namespace SocketHttpListener.Net Init(); } - public static async Task<HttpConnection> Create(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem) + public static async Task<HttpConnection> Create(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment) { - var connection = new HttpConnection(logger, sock, epl, secure, cert, cryptoProvider, streamFactory, memoryStreamFactory, textEncoding, fileSystem); + var connection = new HttpConnection(logger, sock, epl, secure, cert, cryptoProvider, streamFactory, memoryStreamFactory, textEncoding, fileSystem, environment); await connection.InitStream().ConfigureAwait(false); @@ -217,7 +220,7 @@ namespace SocketHttpListener.Net { var supportsDirectSocketAccess = !context.Response.SendChunked && !isExpect100Continue && !secure; - o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding, _fileSystem, sock, supportsDirectSocketAccess, _logger); + o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding, _fileSystem, sock, supportsDirectSocketAccess, _logger, _environment); } else { diff --git a/SocketHttpListener.Portable/Net/HttpListener.cs b/SocketHttpListener.Portable/Net/HttpListener.cs index c2e7acd8e..b3e01425c 100644 --- a/SocketHttpListener.Portable/Net/HttpListener.cs +++ b/SocketHttpListener.Portable/Net/HttpListener.cs @@ -8,6 +8,7 @@ using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; +using MediaBrowser.Model.System; using MediaBrowser.Model.Text; using SocketHttpListener.Primitives; @@ -22,6 +23,7 @@ namespace SocketHttpListener.Net internal ITextEncoding TextEncoding { get; private set; } internal IMemoryStreamFactory MemoryStreamFactory { get; private set; } internal INetworkManager NetworkManager { get; private set; } + internal IEnvironmentInfo EnvironmentInfo { get; private set; } public bool EnableDualMode { get; set; } @@ -40,7 +42,7 @@ namespace SocketHttpListener.Net public Action<HttpListenerContext> OnContext { get; set; } - public HttpListener(ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem) + public HttpListener(ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo) { _logger = logger; CryptoProvider = cryptoProvider; @@ -50,19 +52,20 @@ namespace SocketHttpListener.Net TextEncoding = textEncoding; MemoryStreamFactory = memoryStreamFactory; FileSystem = fileSystem; + EnvironmentInfo = environmentInfo; prefixes = new HttpListenerPrefixCollection(logger, this); registry = new Dictionary<HttpListenerContext, HttpListenerContext>(); connections = new Dictionary<HttpConnection, HttpConnection>(); auth_schemes = AuthenticationSchemes.Anonymous; } - public HttpListener(ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem) - :this(new NullLogger(), certificate, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem) + public HttpListener(ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo) + :this(new NullLogger(), certificate, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem, environmentInfo) { } - public HttpListener(ILogger logger, ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem) - : this(logger, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem) + public HttpListener(ILogger logger, ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo) + : this(logger, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem, environmentInfo) { _certificate = certificate; } diff --git a/SocketHttpListener.Portable/Net/ResponseStream.cs b/SocketHttpListener.Portable/Net/ResponseStream.cs index dea4049d5..9552fe8ca 100644 --- a/SocketHttpListener.Portable/Net/ResponseStream.cs +++ b/SocketHttpListener.Portable/Net/ResponseStream.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using MediaBrowser.Model.IO; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Net; +using MediaBrowser.Model.System; using MediaBrowser.Model.Text; using SocketHttpListener.Primitives; @@ -28,8 +29,9 @@ namespace SocketHttpListener.Net private readonly IAcceptSocket _socket; private readonly bool _supportsDirectSocketAccess; private readonly ILogger _logger; + private readonly IEnvironmentInfo _environment; - internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IAcceptSocket socket, bool supportsDirectSocketAccess, ILogger logger) + internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IAcceptSocket socket, bool supportsDirectSocketAccess, ILogger logger, IEnvironmentInfo environment) { this.response = response; _memoryStreamFactory = memoryStreamFactory; @@ -38,6 +40,7 @@ namespace SocketHttpListener.Net _socket = socket; _supportsDirectSocketAccess = supportsDirectSocketAccess; _logger = logger; + _environment = environment; this.stream = stream; } @@ -344,7 +347,20 @@ namespace SocketHttpListener.Net private async Task TransmitFileManaged(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken) { - using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShareMode, true)) + var allowAsync = _environment.OperatingSystem != OperatingSystem.Windows; + + var fileOpenOptions = offset > 0 + ? FileOpenOptions.RandomAccess + : FileOpenOptions.SequentialScan; + + if (allowAsync) + { + fileOpenOptions |= FileOpenOptions.Asynchronous; + } + + // use non-async filestream along with read due to https://github.com/dotnet/corefx/issues/6039 + + using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShareMode, fileOpenOptions)) { if (offset > 0) { @@ -355,11 +371,53 @@ namespace SocketHttpListener.Net if (count > 0) { - await CopyToInternalAsync(fs, targetStream, count, cancellationToken).ConfigureAwait(false); + if (allowAsync) + { + await CopyToInternalAsync(fs, targetStream, count, cancellationToken).ConfigureAwait(false); + } + else + { + await CopyToInternalAsyncWithSyncRead(fs, targetStream, count, cancellationToken).ConfigureAwait(false); + } } else { - await fs.CopyToAsync(targetStream, 81920, cancellationToken).ConfigureAwait(false); + if (allowAsync) + { + await fs.CopyToAsync(targetStream, 81920, cancellationToken).ConfigureAwait(false); + } + else + { + fs.CopyTo(targetStream, 81920); + } + } + } + } + + private static async Task CopyToInternalAsyncWithSyncRead(Stream source, Stream destination, long copyLength, CancellationToken cancellationToken) + { + var array = new byte[81920]; + int bytesRead; + + while ((bytesRead = source.Read(array, 0, array.Length)) != 0) + { + if (bytesRead == 0) + { + break; + } + + var bytesToWrite = Math.Min(bytesRead, copyLength); + + if (bytesToWrite > 0) + { + await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToWrite), cancellationToken).ConfigureAwait(false); + } + + copyLength -= bytesToWrite; + + if (copyLength <= 0) + { + break; } } } @@ -368,7 +426,7 @@ namespace SocketHttpListener.Net { var array = new byte[81920]; int bytesRead; - + while ((bytesRead = await source.ReadAsync(array, 0, array.Length, cancellationToken).ConfigureAwait(false)) != 0) { if (bytesRead == 0) |
