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

View File

@ -128,6 +128,7 @@ using MediaBrowser.Model.Events;
using MediaBrowser.Model.Tasks; using MediaBrowser.Model.Tasks;
using MediaBrowser.Model.Threading; using MediaBrowser.Model.Threading;
using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions; using StringExtensions = MediaBrowser.Controller.Extensions.StringExtensions;
using X509Certificate = System.Security.Cryptography.X509Certificates.X509Certificate;
namespace Emby.Server.Implementations 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; var certificateLocation = info == null ? null : info.Path;
@ -1195,7 +1196,7 @@ namespace Emby.Server.Implementations
return null; return null;
} }
return new Certificate(localCert); return localCert;
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -1584,7 +1585,7 @@ namespace Emby.Server.Implementations
} }
private CertificateInfo CertificateInfo { get; set; } private CertificateInfo CertificateInfo { get; set; }
private ICertificate Certificate { get; set; } private X509Certificate Certificate { get; set; }
private IEnumerable<string> GetUrlPrefixes() private IEnumerable<string> GetUrlPrefixes()
{ {

View File

@ -440,7 +440,6 @@
<Compile Include="Networking\NetworkManager.cs" /> <Compile Include="Networking\NetworkManager.cs" />
<Compile Include="Net\DisposableManagedObjectBase.cs" /> <Compile Include="Net\DisposableManagedObjectBase.cs" />
<Compile Include="Net\NetAcceptSocket.cs" /> <Compile Include="Net\NetAcceptSocket.cs" />
<Compile Include="Net\SocketAcceptor.cs" />
<Compile Include="Net\SocketFactory.cs" /> <Compile Include="Net\SocketFactory.cs" />
<Compile Include="Net\UdpSocket.cs" /> <Compile Include="Net\UdpSocket.cs" />
<Compile Include="News\NewsEntryPoint.cs" /> <Compile Include="News\NewsEntryPoint.cs" />

View File

@ -7,6 +7,7 @@ using System.Collections.Generic;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -55,9 +56,8 @@ namespace Emby.Server.Implementations.HttpServer
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IJsonSerializer _jsonSerializer; private readonly IJsonSerializer _jsonSerializer;
private readonly IXmlSerializer _xmlSerializer; private readonly IXmlSerializer _xmlSerializer;
private readonly ICertificate _certificate; private readonly X509Certificate _certificate;
private readonly IEnvironmentInfo _environment; private readonly IEnvironmentInfo _environment;
private readonly IStreamFactory _streamFactory;
private readonly Func<Type, Func<string, object>> _funcParseFn; private readonly Func<Type, Func<string, object>> _funcParseFn;
private readonly bool _enableDualModeSockets; private readonly bool _enableDualModeSockets;
@ -71,7 +71,7 @@ namespace Emby.Server.Implementations.HttpServer
ILogger logger, ILogger logger,
IServerConfigurationManager config, IServerConfigurationManager config,
string serviceName, 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; Instance = this;
@ -86,7 +86,6 @@ namespace Emby.Server.Implementations.HttpServer
_xmlSerializer = xmlSerializer; _xmlSerializer = xmlSerializer;
_environment = environment; _environment = environment;
_certificate = certificate; _certificate = certificate;
_streamFactory = streamFactory;
_funcParseFn = funcParseFn; _funcParseFn = funcParseFn;
_enableDualModeSockets = enableDualModeSockets; _enableDualModeSockets = enableDualModeSockets;
_fileSystem = fileSystem; _fileSystem = fileSystem;
@ -204,7 +203,6 @@ namespace Emby.Server.Implementations.HttpServer
_networkManager, _networkManager,
_socketFactory, _socketFactory,
_cryptoProvider, _cryptoProvider,
_streamFactory,
_enableDualModeSockets, _enableDualModeSockets,
GetRequest, GetRequest,
_fileSystem, _fileSystem,

View File

@ -4,6 +4,7 @@ using SocketHttpListener.Net;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
@ -22,13 +23,12 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
private HttpListener _listener; private HttpListener _listener;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ICertificate _certificate; private readonly X509Certificate _certificate;
private readonly IMemoryStreamFactory _memoryStreamProvider; private readonly IMemoryStreamFactory _memoryStreamProvider;
private readonly ITextEncoding _textEncoding; private readonly ITextEncoding _textEncoding;
private readonly INetworkManager _networkManager; private readonly INetworkManager _networkManager;
private readonly ISocketFactory _socketFactory; private readonly ISocketFactory _socketFactory;
private readonly ICryptoProvider _cryptoProvider; private readonly ICryptoProvider _cryptoProvider;
private readonly IStreamFactory _streamFactory;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly Func<HttpListenerContext, IHttpRequest> _httpRequestFactory; private readonly Func<HttpListenerContext, IHttpRequest> _httpRequestFactory;
private readonly bool _enableDualMode; private readonly bool _enableDualMode;
@ -37,7 +37,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource(); private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
private CancellationToken _disposeCancellationToken; 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; _logger = logger;
_certificate = certificate; _certificate = certificate;
@ -46,7 +46,6 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
_networkManager = networkManager; _networkManager = networkManager;
_socketFactory = socketFactory; _socketFactory = socketFactory;
_cryptoProvider = cryptoProvider; _cryptoProvider = cryptoProvider;
_streamFactory = streamFactory;
_enableDualMode = enableDualMode; _enableDualMode = enableDualMode;
_httpRequestFactory = httpRequestFactory; _httpRequestFactory = httpRequestFactory;
_fileSystem = fileSystem; _fileSystem = fileSystem;
@ -65,7 +64,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
public void Start(IEnumerable<string> urlPrefixes) public void Start(IEnumerable<string> urlPrefixes)
{ {
if (_listener == null) 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; _listener.EnableDualMode = _enableDualMode;

View File

@ -108,7 +108,7 @@ namespace Emby.Server.Implementations.HttpServer.SocketSharp
return remoteIp ?? return remoteIp ??
(remoteIp = (CheckBadChars(XForwardedFor)) ?? (remoteIp = (CheckBadChars(XForwardedFor)) ??
(NormalizeIp(CheckBadChars(XRealIp)) ?? (NormalizeIp(CheckBadChars(XRealIp)) ??
(request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.IpAddress.ToString()) : null))); (request.RemoteEndPoint != null ? NormalizeIp(request.RemoteEndPoint.Address.ToString()) : null)));
} }
} }

View File

@ -43,7 +43,7 @@ namespace Emby.Server.Implementations
IJsonSerializer json, IJsonSerializer json,
IXmlSerializer xml, IXmlSerializer xml,
IEnvironmentInfo environment, IEnvironmentInfo environment,
ICertificate certificate, X509Certificate certificate,
IFileSystem fileSystem, IFileSystem fileSystem,
bool enableDualModeSockets) bool enableDualModeSockets)
{ {
@ -63,7 +63,6 @@ namespace Emby.Server.Implementations
xml, xml,
environment, environment,
certificate, certificate,
new StreamFactory(),
GetParseFn, GetParseFn,
enableDualModeSockets, enableDualModeSockets,
fileSystem); fileSystem);
@ -74,37 +73,4 @@ namespace Emby.Server.Implementations
return s => JsvReader.GetParseFn(propertyType)(s); 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; }
}
} }

View File

@ -89,63 +89,6 @@ namespace Emby.Server.Implementations.Net
Socket.Bind(nativeEndpoint); 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() public void Dispose()
{ {
Socket.Dispose(); Socket.Dispose();

View File

@ -12,9 +12,6 @@ namespace MediaBrowser.Model.Net
void Listen(int backlog); void Listen(int backlog);
void Bind(IpEndPointInfo endpoint); void Bind(IpEndPointInfo endpoint);
void Connect(IpEndPointInfo endPoint); void Connect(IpEndPointInfo endPoint);
void StartAccept(Action<IAcceptSocket> onAccept, Func<bool> isClosed);
IAsyncResult BeginSendFile(string path, byte[] preBuffer, byte[] postBuffer, AsyncCallback callback, object state);
void EndSendFile(IAsyncResult result);
} }
public class SocketCreateException : Exception public class SocketCreateException : Exception

View File

@ -3,6 +3,8 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Threading; using System.Threading;
using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
@ -11,37 +13,37 @@ using MediaBrowser.Model.Net;
using MediaBrowser.Model.System; using MediaBrowser.Model.System;
using MediaBrowser.Model.Text; using MediaBrowser.Model.Text;
using SocketHttpListener.Primitives; using SocketHttpListener.Primitives;
using ProtocolType = MediaBrowser.Model.Net.ProtocolType;
using SocketType = MediaBrowser.Model.Net.SocketType;
namespace SocketHttpListener.Net namespace SocketHttpListener.Net
{ {
sealed class EndPointListener sealed class EndPointListener
{ {
HttpListener listener; HttpListener listener;
IpEndPointInfo endpoint; IPEndPoint endpoint;
IAcceptSocket sock; Socket sock;
Dictionary<ListenerPrefix,HttpListener> prefixes; // Dictionary <ListenerPrefix, HttpListener> Dictionary<ListenerPrefix, HttpListener> prefixes; // Dictionary <ListenerPrefix, HttpListener>
List<ListenerPrefix> unhandled; // List<ListenerPrefix> unhandled; host = '*' List<ListenerPrefix> unhandled; // List<ListenerPrefix> unhandled; host = '*'
List<ListenerPrefix> all; // List<ListenerPrefix> all; host = '+' List<ListenerPrefix> all; // List<ListenerPrefix> all; host = '+'
ICertificate cert; X509Certificate cert;
bool secure; bool secure;
Dictionary<HttpConnection, HttpConnection> unregistered; Dictionary<HttpConnection, HttpConnection> unregistered;
private readonly ILogger _logger; private readonly ILogger _logger;
private bool _closed; private bool _closed;
private bool _enableDualMode; private bool _enableDualMode;
private readonly ICryptoProvider _cryptoProvider; private readonly ICryptoProvider _cryptoProvider;
private readonly IStreamFactory _streamFactory;
private readonly ISocketFactory _socketFactory; private readonly ISocketFactory _socketFactory;
private readonly ITextEncoding _textEncoding; private readonly ITextEncoding _textEncoding;
private readonly IMemoryStreamFactory _memoryStreamFactory; private readonly IMemoryStreamFactory _memoryStreamFactory;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IEnvironmentInfo _environment; 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, IEnvironmentInfo environment) public EndPointListener(HttpListener listener, IPAddress addr, int port, bool secure, X509Certificate cert, ILogger logger, ICryptoProvider cryptoProvider, ISocketFactory socketFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment)
{ {
this.listener = listener; this.listener = listener;
_logger = logger; _logger = logger;
_cryptoProvider = cryptoProvider; _cryptoProvider = cryptoProvider;
_streamFactory = streamFactory;
_socketFactory = socketFactory; _socketFactory = socketFactory;
_memoryStreamFactory = memoryStreamFactory; _memoryStreamFactory = memoryStreamFactory;
_textEncoding = textEncoding; _textEncoding = textEncoding;
@ -51,8 +53,8 @@ namespace SocketHttpListener.Net
this.secure = secure; this.secure = secure;
this.cert = cert; this.cert = cert;
_enableDualMode = addr.Equals(IpAddressInfo.IPv6Any); _enableDualMode = addr.Equals(IPAddress.IPv6Any);
endpoint = new IpEndPointInfo(addr, port); endpoint = new IPEndPoint(addr, port);
prefixes = new Dictionary<ListenerPrefix, HttpListener>(); prefixes = new Dictionary<ListenerPrefix, HttpListener>();
unregistered = new Dictionary<HttpConnection, HttpConnection>(); unregistered = new Dictionary<HttpConnection, HttpConnection>();
@ -72,18 +74,18 @@ namespace SocketHttpListener.Net
{ {
try try
{ {
sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode); sock = CreateSocket(endpoint.Address.AddressFamily, _enableDualMode);
} }
catch (SocketCreateException ex) catch (SocketCreateException ex)
{ {
if (_enableDualMode && endpoint.IpAddress.Equals(IpAddressInfo.IPv6Any) && if (_enableDualMode && endpoint.Address.Equals(IPAddress.IPv6Any) &&
(string.Equals(ex.ErrorCode, "AddressFamilyNotSupported", StringComparison.OrdinalIgnoreCase) || (string.Equals(ex.ErrorCode, "AddressFamilyNotSupported", StringComparison.OrdinalIgnoreCase) ||
// mono on bsd is throwing this // mono on bsd is throwing this
string.Equals(ex.ErrorCode, "ProtocolNotSupported", StringComparison.OrdinalIgnoreCase))) string.Equals(ex.ErrorCode, "ProtocolNotSupported", StringComparison.OrdinalIgnoreCase)))
{ {
endpoint = new IpEndPointInfo(IpAddressInfo.Any, endpoint.Port); endpoint = new IPEndPoint(IPAddress.Any, endpoint.Port);
_enableDualMode = false; _enableDualMode = false;
sock = _socketFactory.CreateSocket(endpoint.IpAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp, _enableDualMode); sock = CreateSocket(endpoint.Address.AddressFamily, _enableDualMode);
} }
else else
{ {
@ -96,11 +98,42 @@ namespace SocketHttpListener.Net
// This is the number TcpListener uses. // This is the number TcpListener uses.
sock.Listen(2147483647); sock.Listen(2147483647);
sock.StartAccept(ProcessAccept, () => _closed); new SocketAcceptor(_logger, sock, ProcessAccept, () => _closed).StartAccept();
_closed = false; _closed = false;
} }
private async void ProcessAccept(IAcceptSocket accepted) private Socket CreateSocket(AddressFamily addressFamily, bool dualMode)
{
try
{
var socket = new Socket(addressFamily, System.Net.Sockets.SocketType.Stream, System.Net.Sockets.ProtocolType.Tcp);
if (dualMode)
{
socket.DualMode = true;
}
return socket;
}
catch (SocketException ex)
{
throw new SocketCreateException(ex.SocketErrorCode.ToString(), ex);
}
catch (ArgumentException ex)
{
if (dualMode)
{
// Mono for BSD incorrectly throws ArgumentException instead of SocketException
throw new SocketCreateException("AddressFamilyNotSupported", ex);
}
else
{
throw;
}
}
}
private async void ProcessAccept(Socket accepted)
{ {
try try
{ {
@ -112,7 +145,7 @@ namespace SocketHttpListener.Net
return; return;
} }
HttpConnection conn = await HttpConnection.Create(_logger, accepted, listener, listener.secure, listener.cert, _cryptoProvider, _streamFactory, _memoryStreamFactory, _textEncoding, _fileSystem, _environment).ConfigureAwait(false); HttpConnection conn = await HttpConnection.Create(_logger, accepted, listener, listener.secure, listener.cert, _cryptoProvider, _memoryStreamFactory, _textEncoding, _fileSystem, _environment).ConfigureAwait(false);
//_logger.Debug("Adding unregistered connection to {0}. Id: {1}", accepted.RemoteEndPoint, connectionId); //_logger.Debug("Adding unregistered connection to {0}. Id: {1}", accepted.RemoteEndPoint, connectionId);
lock (listener.unregistered) lock (listener.unregistered)

View File

@ -66,25 +66,25 @@ namespace SocketHttpListener.Net
epl.AddPrefix(lp, listener); epl.AddPrefix(lp, listener);
} }
private static IpAddressInfo GetIpAnyAddress(HttpListener listener) private static IPAddress GetIpAnyAddress(HttpListener listener)
{ {
return listener.EnableDualMode ? IpAddressInfo.IPv6Any : IpAddressInfo.Any; return listener.EnableDualMode ? IPAddress.IPv6Any : IPAddress.Any;
} }
static async Task<EndPointListener> GetEPListener(ILogger logger, string host, int port, HttpListener listener, bool secure) static async Task<EndPointListener> GetEPListener(ILogger logger, string host, int port, HttpListener listener, bool secure)
{ {
var networkManager = listener.NetworkManager; var networkManager = listener.NetworkManager;
IpAddressInfo addr; IPAddress addr;
if (host == "*" || host == "+") if (host == "*" || host == "+")
addr = GetIpAnyAddress(listener); addr = GetIpAnyAddress(listener);
else if (networkManager.TryParseIpAddress(host, out addr) == false) else if (IPAddress.TryParse(host, out addr) == false)
{ {
try try
{ {
var all = (await networkManager.GetHostAddressesAsync(host).ConfigureAwait(false)); var all = (await networkManager.GetHostAddressesAsync(host).ConfigureAwait(false));
addr = (all.Length == 0 ? null : all[0]) ?? addr = (all.Length == 0 ? null : IPAddress.Parse(all[0].Address)) ??
GetIpAnyAddress(listener); GetIpAnyAddress(listener);
} }
catch catch
@ -94,10 +94,10 @@ namespace SocketHttpListener.Net
} }
Dictionary<int, EndPointListener> p = null; // Dictionary<int, EndPointListener> Dictionary<int, EndPointListener> p = null; // Dictionary<int, EndPointListener>
if (!ip_to_endpoints.TryGetValue(addr.Address, out p)) if (!ip_to_endpoints.TryGetValue(addr.ToString(), out p))
{ {
p = new Dictionary<int, EndPointListener>(); p = new Dictionary<int, EndPointListener>();
ip_to_endpoints[addr.Address] = p; ip_to_endpoints[addr.ToString()] = p;
} }
EndPointListener epl = null; EndPointListener epl = null;
@ -107,25 +107,25 @@ namespace SocketHttpListener.Net
} }
else else
{ {
epl = new EndPointListener(listener, addr, port, secure, listener.Certificate, logger, listener.CryptoProvider, listener.StreamFactory, listener.SocketFactory, listener.MemoryStreamFactory, listener.TextEncoding, listener.FileSystem, listener.EnvironmentInfo); epl = new EndPointListener(listener, addr, port, secure, listener.Certificate, logger, listener.CryptoProvider, listener.SocketFactory, listener.MemoryStreamFactory, listener.TextEncoding, listener.FileSystem, listener.EnvironmentInfo);
p[port] = epl; p[port] = epl;
} }
return epl; return epl;
} }
public static void RemoveEndPoint(EndPointListener epl, IpEndPointInfo ep) public static void RemoveEndPoint(EndPointListener epl, IPEndPoint ep)
{ {
lock (ip_to_endpoints) lock (ip_to_endpoints)
{ {
// Dictionary<int, EndPointListener> p // Dictionary<int, EndPointListener> p
Dictionary<int, EndPointListener> p; Dictionary<int, EndPointListener> p;
if (ip_to_endpoints.TryGetValue(ep.IpAddress.Address, out p)) if (ip_to_endpoints.TryGetValue(ep.Address.ToString(), out p))
{ {
p.Remove(ep.Port); p.Remove(ep.Port);
if (p.Count == 0) if (p.Count == 0)
{ {
ip_to_endpoints.Remove(ep.IpAddress.Address); ip_to_endpoints.Remove(ep.Address.ToString());
} }
} }
epl.Close(); epl.Close();

View File

@ -1,5 +1,9 @@
using System; using System;
using System.IO; using System.IO;
using System.Net;
using System.Net.Security;
using System.Net.Sockets;
using System.Security.Cryptography.X509Certificates;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Cryptography;
@ -16,7 +20,7 @@ namespace SocketHttpListener.Net
{ {
private static AsyncCallback s_onreadCallback = new AsyncCallback(OnRead); private static AsyncCallback s_onreadCallback = new AsyncCallback(OnRead);
const int BufferSize = 8192; const int BufferSize = 8192;
IAcceptSocket _socket; Socket _socket;
Stream _stream; Stream _stream;
EndPointListener _epl; EndPointListener _epl;
MemoryStream _memoryStream; MemoryStream _memoryStream;
@ -31,21 +35,20 @@ namespace SocketHttpListener.Net
bool _contextBound; bool _contextBound;
bool secure; bool secure;
int _timeout = 300000; // 90k ms for first request, 15k ms from then on int _timeout = 300000; // 90k ms for first request, 15k ms from then on
IpEndPointInfo local_ep; IPEndPoint local_ep;
HttpListener _lastListener; HttpListener _lastListener;
int[] client_cert_errors; int[] client_cert_errors;
ICertificate cert; X509Certificate cert;
Stream ssl_stream; SslStream ssl_stream;
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly ICryptoProvider _cryptoProvider; private readonly ICryptoProvider _cryptoProvider;
private readonly IMemoryStreamFactory _memoryStreamFactory; private readonly IMemoryStreamFactory _memoryStreamFactory;
private readonly ITextEncoding _textEncoding; private readonly ITextEncoding _textEncoding;
private readonly IStreamFactory _streamFactory;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly IEnvironmentInfo _environment; private readonly IEnvironmentInfo _environment;
private HttpConnection(ILogger logger, IAcceptSocket socket, EndPointListener epl, bool secure, ICertificate cert, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment) private HttpConnection(ILogger logger, Socket socket, EndPointListener epl, bool secure, X509Certificate cert, ICryptoProvider cryptoProvider, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment)
{ {
_logger = logger; _logger = logger;
this._socket = socket; this._socket = socket;
@ -57,14 +60,13 @@ namespace SocketHttpListener.Net
_textEncoding = textEncoding; _textEncoding = textEncoding;
_fileSystem = fileSystem; _fileSystem = fileSystem;
_environment = environment; _environment = environment;
_streamFactory = streamFactory;
} }
private async Task InitStream() private async Task InitStream()
{ {
if (secure == false) if (secure == false)
{ {
_stream = _streamFactory.CreateNetworkStream(_socket, false); _stream = new SocketStream(_socket, false);
} }
else else
{ {
@ -81,16 +83,16 @@ namespace SocketHttpListener.Net
//}); //});
//_stream = ssl_stream.AuthenticatedStream; //_stream = ssl_stream.AuthenticatedStream;
ssl_stream = _streamFactory.CreateSslStream(_streamFactory.CreateNetworkStream(_socket, false), false); ssl_stream = new SslStream(new SocketStream(_socket, false), false);
await _streamFactory.AuthenticateSslStreamAsServer(ssl_stream, cert).ConfigureAwait(false); await ssl_stream.AuthenticateAsServerAsync(cert).ConfigureAwait(false);
_stream = ssl_stream; _stream = ssl_stream;
} }
Init(); 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, IEnvironmentInfo environment) public static async Task<HttpConnection> Create(ILogger logger, Socket sock, EndPointListener epl, bool secure, X509Certificate cert, ICryptoProvider cryptoProvider, IMemoryStreamFactory memoryStreamFactory, ITextEncoding textEncoding, IFileSystem fileSystem, IEnvironmentInfo environment)
{ {
var connection = new HttpConnection(logger, sock, epl, secure, cert, cryptoProvider, streamFactory, memoryStreamFactory, textEncoding, fileSystem, environment); var connection = new HttpConnection(logger, sock, epl, secure, cert, cryptoProvider, memoryStreamFactory, textEncoding, fileSystem, environment);
await connection.InitStream().ConfigureAwait(false); await connection.InitStream().ConfigureAwait(false);
@ -134,21 +136,21 @@ namespace SocketHttpListener.Net
get { return _reuses; } get { return _reuses; }
} }
public IpEndPointInfo LocalEndPoint public IPEndPoint LocalEndPoint
{ {
get get
{ {
if (local_ep != null) if (local_ep != null)
return local_ep; return local_ep;
local_ep = (IpEndPointInfo)_socket.LocalEndPoint; local_ep = (IPEndPoint)_socket.LocalEndPoint;
return local_ep; return local_ep;
} }
} }
public IpEndPointInfo RemoteEndPoint public IPEndPoint RemoteEndPoint
{ {
get { return (IpEndPointInfo)_socket.RemoteEndPoint; } get { return _socket.RemoteEndPoint as IPEndPoint; }
} }
public bool IsSecure public bool IsSecure
@ -513,12 +515,12 @@ namespace SocketHttpListener.Net
return; return;
} }
IAcceptSocket s = _socket; Socket s = _socket;
_socket = null; _socket = null;
try try
{ {
if (s != null) if (s != null)
s.Shutdown(true); s.Shutdown(SocketShutdown.Both);
} }
catch catch
{ {

View File

@ -3,6 +3,7 @@ using System.Collections;
using System.Collections.Generic; using System.Collections.Generic;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Security.Cryptography.X509Certificates;
using MediaBrowser.Common.Net; using MediaBrowser.Common.Net;
using MediaBrowser.Model.Cryptography; using MediaBrowser.Model.Cryptography;
using MediaBrowser.Model.IO; using MediaBrowser.Model.IO;
@ -17,7 +18,6 @@ namespace SocketHttpListener.Net
public sealed class HttpListener : IDisposable public sealed class HttpListener : IDisposable
{ {
internal ICryptoProvider CryptoProvider { get; private set; } internal ICryptoProvider CryptoProvider { get; private set; }
internal IStreamFactory StreamFactory { get; private set; }
internal ISocketFactory SocketFactory { get; private set; } internal ISocketFactory SocketFactory { get; private set; }
internal IFileSystem FileSystem { get; private set; } internal IFileSystem FileSystem { get; private set; }
internal ITextEncoding TextEncoding { get; private set; } internal ITextEncoding TextEncoding { get; private set; }
@ -38,15 +38,14 @@ namespace SocketHttpListener.Net
Dictionary<HttpListenerContext, HttpListenerContext> registry; // Dictionary<HttpListenerContext,HttpListenerContext> Dictionary<HttpListenerContext, HttpListenerContext> registry; // Dictionary<HttpListenerContext,HttpListenerContext>
Dictionary<HttpConnection, HttpConnection> connections; Dictionary<HttpConnection, HttpConnection> connections;
private ILogger _logger; private ILogger _logger;
private ICertificate _certificate; private X509Certificate _certificate;
public Action<HttpListenerContext> OnContext { get; set; } public Action<HttpListenerContext> OnContext { get; set; }
public HttpListener(ILogger logger, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo) public HttpListener(ILogger logger, ICryptoProvider cryptoProvider, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo)
{ {
_logger = logger; _logger = logger;
CryptoProvider = cryptoProvider; CryptoProvider = cryptoProvider;
StreamFactory = streamFactory;
SocketFactory = socketFactory; SocketFactory = socketFactory;
NetworkManager = networkManager; NetworkManager = networkManager;
TextEncoding = textEncoding; TextEncoding = textEncoding;
@ -59,18 +58,18 @@ namespace SocketHttpListener.Net
auth_schemes = AuthenticationSchemes.Anonymous; auth_schemes = AuthenticationSchemes.Anonymous;
} }
public HttpListener(ICertificate certificate, ICryptoProvider cryptoProvider, IStreamFactory streamFactory, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo) public HttpListener(X509Certificate certificate, ICryptoProvider cryptoProvider, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo)
:this(new NullLogger(), certificate, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem, environmentInfo) :this(new NullLogger(), certificate, cryptoProvider, 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, IEnvironmentInfo environmentInfo) public HttpListener(ILogger logger, X509Certificate certificate, ICryptoProvider cryptoProvider, ISocketFactory socketFactory, INetworkManager networkManager, ITextEncoding textEncoding, IMemoryStreamFactory memoryStreamFactory, IFileSystem fileSystem, IEnvironmentInfo environmentInfo)
: this(logger, cryptoProvider, streamFactory, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem, environmentInfo) : this(logger, cryptoProvider, socketFactory, networkManager, textEncoding, memoryStreamFactory, fileSystem, environmentInfo)
{ {
_certificate = certificate; _certificate = certificate;
} }
public void LoadCert(ICertificate cert) public void LoadCert(X509Certificate cert)
{ {
_certificate = cert; _certificate = cert;
} }
@ -150,7 +149,7 @@ namespace SocketHttpListener.Net
// } // }
//} //}
internal ICertificate Certificate internal X509Certificate Certificate
{ {
get { return _certificate; } get { return _certificate; }
} }

View File

@ -3,6 +3,7 @@ using System.Collections.Specialized;
using System.Globalization; using System.Globalization;
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using MediaBrowser.Model.Net; using MediaBrowser.Model.Net;
@ -513,7 +514,14 @@ namespace SocketHttpListener.Net
public bool IsLocal public bool IsLocal
{ {
get { return RemoteEndPoint.IpAddress.Equals(IpAddressInfo.Loopback) || RemoteEndPoint.IpAddress.Equals(IpAddressInfo.IPv6Loopback) || LocalEndPoint.IpAddress.Equals(RemoteEndPoint.IpAddress); } get
{
var remoteEndPoint = RemoteEndPoint;
return remoteEndPoint.Address.Equals(IPAddress.Loopback) ||
remoteEndPoint.Address.Equals(IPAddress.IPv6Loopback) ||
LocalEndPoint.Address.Equals(remoteEndPoint.Address);
}
} }
public bool IsSecureConnection public bool IsSecureConnection
@ -557,7 +565,7 @@ namespace SocketHttpListener.Net
} }
} }
public IpEndPointInfo LocalEndPoint public IPEndPoint LocalEndPoint
{ {
get { return context.Connection.LocalEndPoint; } get { return context.Connection.LocalEndPoint; }
} }
@ -577,7 +585,7 @@ namespace SocketHttpListener.Net
get { return raw_url; } get { return raw_url; }
} }
public IpEndPointInfo RemoteEndPoint public IPEndPoint RemoteEndPoint
{ {
get { return context.Connection.RemoteEndPoint; } get { return context.Connection.RemoteEndPoint; }
} }
@ -651,10 +659,5 @@ namespace SocketHttpListener.Net
return _websocketRequest; return _websocketRequest;
} }
} }
public Task<ICertificate> GetClientCertificateAsync()
{
return Task.FromResult<ICertificate>(null);
}
} }
} }

View File

@ -51,13 +51,13 @@ namespace SocketHttpListener.Net
private bool _trailer_sent; private bool _trailer_sent;
private Stream _stream; private Stream _stream;
private readonly IMemoryStreamFactory _memoryStreamFactory; private readonly IMemoryStreamFactory _memoryStreamFactory;
private readonly IAcceptSocket _socket; private readonly Socket _socket;
private readonly bool _supportsDirectSocketAccess; private readonly bool _supportsDirectSocketAccess;
private readonly IEnvironmentInfo _environment; private readonly IEnvironmentInfo _environment;
private readonly IFileSystem _fileSystem; private readonly IFileSystem _fileSystem;
private readonly ILogger _logger; private readonly ILogger _logger;
internal HttpResponseStream(Stream stream, HttpListenerResponse response, bool ignore_errors, IMemoryStreamFactory memoryStreamFactory, IAcceptSocket socket, bool supportsDirectSocketAccess, IEnvironmentInfo environment, IFileSystem fileSystem, ILogger logger) internal HttpResponseStream(Stream stream, HttpListenerResponse response, bool ignore_errors, IMemoryStreamFactory memoryStreamFactory, Socket socket, bool supportsDirectSocketAccess, IEnvironmentInfo environment, IFileSystem fileSystem, ILogger logger)
{ {
_response = response; _response = response;
_ignore_errors = ignore_errors; _ignore_errors = ignore_errors;
@ -289,64 +289,9 @@ namespace SocketHttpListener.Net
public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken) public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
{ {
if (_supportsDirectSocketAccess && offset == 0 && count == 0 && !_response.SendChunked && _response.ContentLength64 > 8192)
{
if (EnableSendFileWithSocket)
{
return TransmitFileOverSocket(path, offset, count, fileShareMode, cancellationToken);
}
}
return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken); return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken);
} }
private readonly byte[] _emptyBuffer = new byte[] { };
private Task TransmitFileOverSocket(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
{
var ms = GetHeaders(false);
byte[] preBuffer;
if (ms != null)
{
using (var msCopy = new MemoryStream())
{
ms.CopyTo(msCopy);
preBuffer = msCopy.ToArray();
}
}
else
{
return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken);
}
//_logger.Info("Socket sending file {0} {1}", path, response.ContentLength64);
var taskCompletion = new TaskCompletionSource<bool>();
Action<IAsyncResult> callback = callbackResult =>
{
try
{
_socket.EndSendFile(callbackResult);
taskCompletion.TrySetResult(true);
}
catch (Exception ex)
{
taskCompletion.TrySetException(ex);
}
};
var result = _socket.BeginSendFile(path, preBuffer, _emptyBuffer, new AsyncCallback(callback), null);
if (result.CompletedSynchronously)
{
callback(result);
}
cancellationToken.Register(() => taskCompletion.TrySetCanceled());
return taskCompletion.Task;
}
const int StreamCopyToBufferSize = 81920; const int StreamCopyToBufferSize = 81920;
private async Task TransmitFileManaged(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken) private async Task TransmitFileManaged(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
{ {

View File

@ -11,7 +11,7 @@ namespace SocketHttpListener.Net
ushort port; ushort port;
string path; string path;
bool secure; bool secure;
IpAddressInfo[] addresses; IPAddress[] addresses;
public HttpListener Listener; public HttpListener Listener;
public ListenerPrefix(string prefix) public ListenerPrefix(string prefix)
@ -25,7 +25,7 @@ namespace SocketHttpListener.Net
return original; return original;
} }
public IpAddressInfo[] Addresses public IPAddress[] Addresses
{ {
get { return addresses; } get { return addresses; }
set { addresses = value; } set { addresses = value; }

View File

@ -1,19 +1,17 @@
using System; using System;
using System.Net.Sockets; using System.Net.Sockets;
using MediaBrowser.Model.Logging; using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Net;
namespace Emby.Server.Implementations.Net namespace SocketHttpListener.Net
{ {
public class SocketAcceptor public class SocketAcceptor
{ {
private readonly ILogger _logger; private readonly ILogger _logger;
private readonly Socket _originalSocket; private readonly Socket _originalSocket;
private readonly Func<bool> _isClosed; private readonly Func<bool> _isClosed;
private readonly Action<IAcceptSocket> _onAccept; private readonly Action<Socket> _onAccept;
private readonly bool _isDualMode;
public SocketAcceptor(ILogger logger, Socket originalSocket, Action<IAcceptSocket> onAccept, Func<bool> isClosed, bool isDualMode) public SocketAcceptor(ILogger logger, Socket originalSocket, Action<Socket> onAccept, Func<bool> isClosed)
{ {
if (logger == null) if (logger == null)
{ {
@ -35,7 +33,6 @@ namespace Emby.Server.Implementations.Net
_logger = logger; _logger = logger;
_originalSocket = originalSocket; _originalSocket = originalSocket;
_isClosed = isClosed; _isClosed = isClosed;
_isDualMode = isDualMode;
_onAccept = onAccept; _onAccept = onAccept;
} }
@ -117,7 +114,7 @@ namespace Emby.Server.Implementations.Net
if (acceptSocket != null) if (acceptSocket != null)
{ {
//ProcessAccept(acceptSocket); //ProcessAccept(acceptSocket);
_onAccept(new NetAcceptSocket(acceptSocket, _logger, _isDualMode)); _onAccept(acceptSocket);
} }
// Accept the next connection request // Accept the next connection request

View File

@ -254,7 +254,7 @@ namespace SocketHttpListener.Net.WebSockets
/// </summary> /// </summary>
/// <value> /// <value>
/// </value> /// </value>
public override IpEndPointInfo ServerEndPoint public override IPEndPoint ServerEndPoint
{ {
get get
{ {
@ -281,7 +281,7 @@ namespace SocketHttpListener.Net.WebSockets
/// </summary> /// </summary>
/// <value> /// <value>
/// </value> /// </value>
public override IpEndPointInfo UserEndPoint public override IPEndPoint UserEndPoint
{ {
get get
{ {

View File

@ -151,7 +151,7 @@ namespace SocketHttpListener.Net.WebSockets
/// <value> /// <value>
/// A <see cref="System.Net.IPEndPoint"/> that represents the server endpoint. /// A <see cref="System.Net.IPEndPoint"/> that represents the server endpoint.
/// </value> /// </value>
public abstract IpEndPointInfo ServerEndPoint { get; } public abstract IPEndPoint ServerEndPoint { get; }
/// <summary> /// <summary>
/// Gets the client information (identity, authentication, and security roles). /// Gets the client information (identity, authentication, and security roles).
@ -167,7 +167,7 @@ namespace SocketHttpListener.Net.WebSockets
/// <value> /// <value>
/// A <see cref="System.Net.IPEndPoint"/> that represents the client endpoint. /// A <see cref="System.Net.IPEndPoint"/> that represents the client endpoint.
/// </value> /// </value>
public abstract IpEndPointInfo UserEndPoint { get; } public abstract IPEndPoint UserEndPoint { get; }
/// <summary> /// <summary>
/// Gets the <see cref="SocketHttpListener.WebSocket"/> instance used for two-way communication /// Gets the <see cref="SocketHttpListener.WebSocket"/> instance used for two-way communication

View File

@ -1,11 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
namespace SocketHttpListener.Primitives
{
public interface ICertificate
{
}
}

View File

@ -1,17 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using MediaBrowser.Model.Net;
namespace SocketHttpListener.Primitives
{
public interface IStreamFactory
{
Stream CreateNetworkStream(IAcceptSocket acceptSocket, bool ownsSocket);
Stream CreateSslStream(Stream innerStream, bool leaveInnerStreamOpen);
Task AuthenticateSslStreamAsServer(Stream stream, ICertificate certificate);
}
}

View File

@ -82,6 +82,7 @@
<Compile Include="Net\HttpStreamAsyncResult.cs" /> <Compile Include="Net\HttpStreamAsyncResult.cs" />
<Compile Include="Net\HttpVersion.cs" /> <Compile Include="Net\HttpVersion.cs" />
<Compile Include="Net\ListenerPrefix.cs" /> <Compile Include="Net\ListenerPrefix.cs" />
<Compile Include="Net\SocketAcceptor.cs" />
<Compile Include="Net\UriScheme.cs" /> <Compile Include="Net\UriScheme.cs" />
<Compile Include="Net\WebHeaderCollection.cs" /> <Compile Include="Net\WebHeaderCollection.cs" />
<Compile Include="Net\WebHeaderEncoding.cs" /> <Compile Include="Net\WebHeaderEncoding.cs" />
@ -89,11 +90,10 @@
<Compile Include="Net\WebSockets\WebSocketContext.cs" /> <Compile Include="Net\WebSockets\WebSocketContext.cs" />
<Compile Include="Opcode.cs" /> <Compile Include="Opcode.cs" />
<Compile Include="PayloadData.cs" /> <Compile Include="PayloadData.cs" />
<Compile Include="Primitives\ICertificate.cs" />
<Compile Include="Primitives\IStreamFactory.cs" />
<Compile Include="Primitives\ITextEncoding.cs" /> <Compile Include="Primitives\ITextEncoding.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Rsv.cs" /> <Compile Include="Rsv.cs" />
<Compile Include="SocketStream.cs" />
<Compile Include="WebSocket.cs" /> <Compile Include="WebSocket.cs" />
<Compile Include="WebSocketException.cs" /> <Compile Include="WebSocketException.cs" />
<Compile Include="WebSocketFrame.cs" /> <Compile Include="WebSocketFrame.cs" />

View File

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
namespace SocketHttpListener
{
public class SocketStream : Stream
{
private readonly Socket _socket;
public SocketStream(Socket socket, bool ownsSocket)
{
_socket = socket;
}
public override void Flush()
{
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return false; }
}
public override bool CanWrite
{
get { return true; }
}
public override long Length
{
get { throw new NotImplementedException(); }
}
public override long Position
{
get { throw new NotImplementedException(); }
set { throw new NotImplementedException(); }
}
public override void Write(byte[] buffer, int offset, int count)
{
_socket.Send(buffer, offset, count, SocketFlags.None);
}
public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
return _socket.BeginSend(buffer, offset, count, SocketFlags.None, callback, state);
}
public override void EndWrite(IAsyncResult asyncResult)
{
_socket.EndSend(asyncResult);
}
public override void SetLength(long value)
{
throw new NotImplementedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotImplementedException();
}
public override int Read(byte[] buffer, int offset, int count)
{
return _socket.Receive(buffer, offset, count, SocketFlags.None);
}
public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
{
return _socket.BeginReceive(buffer, offset, count, SocketFlags.None, callback, state);
}
public override int EndRead(IAsyncResult asyncResult)
{
return _socket.EndReceive(asyncResult);
}
}
}