aboutsummaryrefslogtreecommitdiff
path: root/SocketHttpListener.Portable/Net
diff options
context:
space:
mode:
authorLuke <luke.pulverenti@gmail.com>2017-03-29 02:25:37 -0400
committerGitHub <noreply@github.com>2017-03-29 02:25:37 -0400
commit88e3fcfdc78fcab201fad72466bf2aa50b453210 (patch)
tree1e40408a0167aa2dca47ac07b16afa26e94d18d1 /SocketHttpListener.Portable/Net
parent75f58d5665322a5045649aed89aecfef011b315c (diff)
parent9f9e81089f5606e958bc8c3f0e4d73475d02372a (diff)
Merge pull request #2554 from MediaBrowser/beta
Beta
Diffstat (limited to 'SocketHttpListener.Portable/Net')
-rw-r--r--SocketHttpListener.Portable/Net/EndPointListener.cs6
-rw-r--r--SocketHttpListener.Portable/Net/EndPointManager.cs3
-rw-r--r--SocketHttpListener.Portable/Net/HttpConnection.cs16
-rw-r--r--SocketHttpListener.Portable/Net/HttpListener.cs12
-rw-r--r--SocketHttpListener.Portable/Net/HttpListenerContext.cs6
-rw-r--r--SocketHttpListener.Portable/Net/HttpListenerRequest.cs2
-rw-r--r--SocketHttpListener.Portable/Net/HttpListenerResponse.cs14
-rw-r--r--SocketHttpListener.Portable/Net/ResponseStream.cs84
8 files changed, 121 insertions, 22 deletions
diff --git a/SocketHttpListener.Portable/Net/EndPointListener.cs b/SocketHttpListener.Portable/Net/EndPointListener.cs
index c7642d5d1..4f1a17fc0 100644
--- a/SocketHttpListener.Portable/Net/EndPointListener.cs
+++ b/SocketHttpListener.Portable/Net/EndPointListener.cs
@@ -32,8 +32,9 @@ namespace SocketHttpListener.Net
private readonly ISocketFactory _socketFactory;
private readonly ITextEncoding _textEncoding;
private readonly IMemoryStreamFactory _memoryStreamFactory;
+ private readonly 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)
+ 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)
{
this.listener = listener;
_logger = logger;
@@ -42,6 +43,7 @@ namespace SocketHttpListener.Net
_socketFactory = socketFactory;
_memoryStreamFactory = memoryStreamFactory;
_textEncoding = textEncoding;
+ _fileSystem = fileSystem;
this.secure = secure;
this.cert = cert;
@@ -107,7 +109,7 @@ namespace SocketHttpListener.Net
return;
}
- HttpConnection conn = await HttpConnection.Create(_logger, accepted, listener, listener.secure, listener.cert, _cryptoProvider, _streamFactory, _memoryStreamFactory, _textEncoding).ConfigureAwait(false);
+ HttpConnection conn = await HttpConnection.Create(_logger, accepted, listener, listener.secure, listener.cert, _cryptoProvider, _streamFactory, _memoryStreamFactory, _textEncoding, _fileSystem).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 797684b3e..11f774915 100644
--- a/SocketHttpListener.Portable/Net/EndPointManager.cs
+++ b/SocketHttpListener.Portable/Net/EndPointManager.cs
@@ -5,6 +5,7 @@ using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading.Tasks;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
using SocketHttpListener.Primitives;
@@ -105,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);
+ epl = new EndPointListener(listener, addr, port, secure, listener.Certificate, logger, listener.CryptoProvider, listener.StreamFactory, listener.SocketFactory, listener.MemoryStreamFactory, listener.TextEncoding, listener.FileSystem);
p[port] = epl;
}
diff --git a/SocketHttpListener.Portable/Net/HttpConnection.cs b/SocketHttpListener.Portable/Net/HttpConnection.cs
index 4a2cf3f5b..5fe47fc63 100644
--- a/SocketHttpListener.Portable/Net/HttpConnection.cs
+++ b/SocketHttpListener.Portable/Net/HttpConnection.cs
@@ -35,13 +35,14 @@ namespace SocketHttpListener.Net
ICertificate cert;
Stream ssl_stream;
- private ILogger _logger;
+ private readonly ILogger _logger;
private readonly ICryptoProvider _cryptoProvider;
private readonly IMemoryStreamFactory _memoryStreamFactory;
private readonly ITextEncoding _textEncoding;
private readonly IStreamFactory _streamFactory;
+ private readonly IFileSystem _fileSystem;
- private HttpConnection(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding)
+ private HttpConnection(ILogger logger, IAcceptSocket sock, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem)
{
_logger = logger;
this.sock = sock;
@@ -51,6 +52,7 @@ namespace SocketHttpListener.Net
_cryptoProvider = cryptoProvider;
_memoryStreamFactory = memoryStreamFactory;
_textEncoding = textEncoding;
+ _fileSystem = fileSystem;
_streamFactory = streamFactory;
}
@@ -82,9 +84,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)
+ 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)
{
- var connection = new HttpConnection(logger, sock, epl, secure, cert, cryptoProvider, streamFactory, memoryStreamFactory, textEncoding);
+ var connection = new HttpConnection(logger, sock, epl, secure, cert, cryptoProvider, streamFactory, memoryStreamFactory, textEncoding, fileSystem);
await connection.InitStream().ConfigureAwait(false);
@@ -121,7 +123,7 @@ namespace SocketHttpListener.Net
position = 0;
input_state = InputState.RequestLine;
line_state = LineState.None;
- context = new HttpListenerContext(this, _logger, _cryptoProvider, _memoryStreamFactory, _textEncoding);
+ context = new HttpListenerContext(this, _logger, _cryptoProvider, _memoryStreamFactory, _textEncoding, _fileSystem);
}
public bool IsClosed
@@ -213,7 +215,9 @@ namespace SocketHttpListener.Net
if (context.Response.SendChunked || isExpect100Continue || context.Request.IsWebSocketRequest || true)
{
- o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding);
+ var supportsDirectSocketAccess = !context.Response.SendChunked && !isExpect100Continue && !secure;
+
+ o_stream = new ResponseStream(stream, context.Response, _memoryStreamFactory, _textEncoding, _fileSystem, sock, supportsDirectSocketAccess);
}
else
{
diff --git a/SocketHttpListener.Portable/Net/HttpListener.cs b/SocketHttpListener.Portable/Net/HttpListener.cs
index 2b0f75d01..c2e7acd8e 100644
--- a/SocketHttpListener.Portable/Net/HttpListener.cs
+++ b/SocketHttpListener.Portable/Net/HttpListener.cs
@@ -18,6 +18,7 @@ namespace SocketHttpListener.Net
internal ICryptoProvider CryptoProvider { get; private set; }
internal IStreamFactory StreamFactory { get; private set; }
internal ISocketFactory SocketFactory { get; private set; }
+ internal IFileSystem FileSystem { get; private set; }
internal ITextEncoding TextEncoding { get; private set; }
internal IMemoryStreamFactory MemoryStreamFactory { get; private set; }
internal INetworkManager NetworkManager { get; private set; }
@@ -39,7 +40,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)
+ public HttpListener(ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem)
{
_logger = logger;
CryptoProvider = cryptoProvider;
@@ -48,19 +49,20 @@ namespace SocketHttpListener.Net
NetworkManager = networkManager;
TextEncoding = textEncoding;
MemoryStreamFactory = memoryStreamFactory;
+ FileSystem = fileSystem;
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)
- :this(new NullLogger(), certificate, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory)
+ 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(ILogger logger, ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory)
- : this(logger, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory)
+ 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)
{
_certificate = certificate;
}
diff --git a/SocketHttpListener.Portable/Net/HttpListenerContext.cs b/SocketHttpListener.Portable/Net/HttpListenerContext.cs
index 182fd2d2a..58d769f22 100644
--- a/SocketHttpListener.Portable/Net/HttpListenerContext.cs
+++ b/SocketHttpListener.Portable/Net/HttpListenerContext.cs
@@ -18,20 +18,18 @@ namespace SocketHttpListener.Net
HttpConnection cnc;
string error;
int err_status = 400;
- private readonly ILogger _logger;
private readonly ICryptoProvider _cryptoProvider;
private readonly IMemoryStreamFactory _memoryStreamFactory;
private readonly ITextEncoding _textEncoding;
- internal HttpListenerContext(HttpConnection cnc, ILogger logger, ICryptoProvider cryptoProvider, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding)
+ internal HttpListenerContext(HttpConnection cnc, ILogger logger, ICryptoProvider cryptoProvider, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem)
{
this.cnc = cnc;
- _logger = logger;
_cryptoProvider = cryptoProvider;
_memoryStreamFactory = memoryStreamFactory;
_textEncoding = textEncoding;
request = new HttpListenerRequest(this, _textEncoding);
- response = new HttpListenerResponse(this, _logger, _textEncoding);
+ response = new HttpListenerResponse(this, logger, _textEncoding, fileSystem);
}
internal int ErrorStatus
diff --git a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs
index 811cc6ddb..cfbd49203 100644
--- a/SocketHttpListener.Portable/Net/HttpListenerRequest.cs
+++ b/SocketHttpListener.Portable/Net/HttpListenerRequest.cs
@@ -456,7 +456,7 @@ namespace SocketHttpListener.Net
public long ContentLength64
{
- get { return content_length; }
+ get { return is_chunked ? -1 : content_length; }
}
public string ContentType
diff --git a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs
index 9a5862cb9..d9f91c0cc 100644
--- a/SocketHttpListener.Portable/Net/HttpListenerResponse.cs
+++ b/SocketHttpListener.Portable/Net/HttpListenerResponse.cs
@@ -3,6 +3,9 @@ using System.Globalization;
using System.IO;
using System.Net;
using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
@@ -32,12 +35,14 @@ namespace SocketHttpListener.Net
private readonly ILogger _logger;
private readonly ITextEncoding _textEncoding;
+ private readonly IFileSystem _fileSystem;
- internal HttpListenerResponse(HttpListenerContext context, ILogger logger, ITextEncoding textEncoding)
+ internal HttpListenerResponse(HttpListenerContext context, ILogger logger, ITextEncoding textEncoding, IFileSystem fileSystem)
{
this.context = context;
_logger = logger;
_textEncoding = textEncoding;
+ _fileSystem = fileSystem;
}
internal bool CloseConnection
@@ -366,7 +371,7 @@ namespace SocketHttpListener.Net
{
if (chunked)
{
- return ;
+ return;
}
Version v = context.Request.ProtocolVersion;
@@ -509,5 +514,10 @@ namespace SocketHttpListener.Net
cookies.Add(cookie);
}
+
+ public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
+ {
+ return ((ResponseStream)OutputStream).TransmitFile(path, offset, count, fileShareMode, cancellationToken);
+ }
}
} \ No newline at end of file
diff --git a/SocketHttpListener.Portable/Net/ResponseStream.cs b/SocketHttpListener.Portable/Net/ResponseStream.cs
index a79a18791..3c79f47c2 100644
--- a/SocketHttpListener.Portable/Net/ResponseStream.cs
+++ b/SocketHttpListener.Portable/Net/ResponseStream.cs
@@ -5,6 +5,7 @@ using System.Text;
using System.Threading;
using System.Threading.Tasks;
using MediaBrowser.Model.IO;
+using MediaBrowser.Model.Net;
using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives;
@@ -22,12 +23,18 @@ namespace SocketHttpListener.Net
Stream stream;
private readonly IMemoryStreamFactory _memoryStreamFactory;
private readonly ITextEncoding _textEncoding;
+ private readonly IFileSystem _fileSystem;
+ private readonly IAcceptSocket _socket;
+ private readonly bool _supportsDirectSocketAccess;
- internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding)
+ internal ResponseStream(Stream stream, HttpListenerResponse response, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IAcceptSocket socket, bool supportsDirectSocketAccess)
{
this.response = response;
_memoryStreamFactory = memoryStreamFactory;
_textEncoding = textEncoding;
+ _fileSystem = fileSystem;
+ _socket = socket;
+ _supportsDirectSocketAccess = supportsDirectSocketAccess;
this.stream = stream;
}
@@ -299,5 +306,80 @@ namespace SocketHttpListener.Net
{
throw new NotSupportedException();
}
+
+ public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
+ {
+ //if (_supportsDirectSocketAccess && offset == 0 && count == 0 && !response.SendChunked)
+ //{
+ // return TransmitFileOverSocket(path, offset, count, cancellationToken);
+ //}
+ return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken);
+ }
+
+ private readonly byte[] _emptyBuffer = new byte[] { };
+ private async Task TransmitFileOverSocket(string path, long offset, long count, CancellationToken cancellationToken)
+ {
+ MemoryStream ms = GetHeaders(response, _memoryStreamFactory, false);
+
+ var buffer = new byte[] {};
+ if (ms != null)
+ {
+ ms.Position = 0;
+
+ byte[] msBuffer;
+ _memoryStreamFactory.TryGetBuffer(ms, out msBuffer);
+ buffer = msBuffer;
+ }
+
+ await _socket.SendFile(path, buffer, _emptyBuffer, cancellationToken).ConfigureAwait(false);
+ }
+
+ private async Task TransmitFileManaged(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
+ {
+ var chunked = response.SendChunked;
+
+ if (!chunked)
+ {
+ await WriteAsync(_emptyBuffer, 0, 0, cancellationToken).ConfigureAwait(false);
+ }
+
+ using (var fs = _fileSystem.GetFileStream(path, FileOpenMode.Open, FileAccessMode.Read, fileShareMode, true))
+ {
+ if (offset > 0)
+ {
+ fs.Position = offset;
+ }
+
+ var targetStream = chunked ? this : stream;
+
+ if (count > 0)
+ {
+ await CopyToInternalAsync(fs, targetStream, count, cancellationToken).ConfigureAwait(false);
+ }
+ else
+ {
+ await fs.CopyToAsync(targetStream, 81920, cancellationToken).ConfigureAwait(false);
+ }
+ }
+ }
+
+ private static async Task CopyToInternalAsync(Stream source, Stream destination, long copyLength, CancellationToken cancellationToken)
+ {
+ var array = new byte[81920];
+ int count;
+ while ((count = await source.ReadAsync(array, 0, array.Length, cancellationToken).ConfigureAwait(false)) != 0)
+ {
+ var bytesToCopy = Math.Min(count, copyLength);
+
+ await destination.WriteAsync(array, 0, Convert.ToInt32(bytesToCopy), cancellationToken).ConfigureAwait(false);
+
+ copyLength -= bytesToCopy;
+
+ if (copyLength <= 0)
+ {
+ break;
+ }
+ }
+ }
}
}