Browse Source

Begin removing System.Net sources

Claus Vium 6 years ago
parent
commit
4db31acff9
54 changed files with 263 additions and 7012 deletions
  1. 1 1
      Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs
  2. 10 6
      Emby.Server.Implementations/HttpServer/FileWriter.cs
  3. 3 0
      Emby.Server.Implementations/HttpServer/HttpListenerHost.cs
  4. 1 1
      Emby.Server.Implementations/HttpServer/HttpResultFactory.cs
  5. 1 1
      Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs
  6. 1 1
      Emby.Server.Implementations/HttpServer/ResponseFilter.cs
  7. 2 2
      Emby.Server.Implementations/HttpServer/StreamWriter.cs
  8. 38 16
      Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs
  9. 2 1
      Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs
  10. 40 6
      Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs
  11. 10 8
      MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs
  12. 1 1
      MediaBrowser.Model/Services/IRequest.cs
  13. 31 0
      MediaBrowser.Model/Services/QueryParamCollection.cs
  14. 0 1
      SocketHttpListener/Ext.cs
  15. 121 122
      SocketHttpListener/HttpResponse.cs
  16. 0 6
      SocketHttpListener/Net/AuthenticationSchemeSelector.cs
  17. 0 9
      SocketHttpListener/Net/AuthenticationTypes.cs
  18. 0 11
      SocketHttpListener/Net/BoundaryType.cs
  19. 0 385
      SocketHttpListener/Net/ChunkStream.cs
  20. 0 178
      SocketHttpListener/Net/ChunkedInputStream.cs
  21. 0 8
      SocketHttpListener/Net/EntitySendFormat.cs
  22. 0 528
      SocketHttpListener/Net/HttpConnection.cs
  23. 0 526
      SocketHttpListener/Net/HttpEndPointListener.cs
  24. 0 192
      SocketHttpListener/Net/HttpEndPointManager.cs
  25. 0 91
      SocketHttpListener/Net/HttpKnownHeaderNames.cs
  26. 0 284
      SocketHttpListener/Net/HttpListener.cs
  27. 0 49
      SocketHttpListener/Net/HttpListenerBasicIdentity.cs
  28. 0 99
      SocketHttpListener/Net/HttpListenerContext.Managed.cs
  29. 0 74
      SocketHttpListener/Net/HttpListenerContext.cs
  30. 0 117
      SocketHttpListener/Net/HttpListenerPrefixCollection.cs
  31. 0 325
      SocketHttpListener/Net/HttpListenerRequest.Managed.cs
  32. 0 537
      SocketHttpListener/Net/HttpListenerRequest.cs
  33. 0 443
      SocketHttpListener/Net/HttpListenerRequestUriBuilder.cs
  34. 0 333
      SocketHttpListener/Net/HttpListenerResponse.Managed.cs
  35. 0 294
      SocketHttpListener/Net/HttpListenerResponse.cs
  36. 0 210
      SocketHttpListener/Net/HttpRequestStream.Managed.cs
  37. 0 129
      SocketHttpListener/Net/HttpRequestStream.cs
  38. 0 329
      SocketHttpListener/Net/HttpResponseStream.Managed.cs
  39. 0 124
      SocketHttpListener/Net/HttpResponseStream.cs
  40. 0 321
      SocketHttpListener/Net/HttpStatusCode.cs
  41. 0 69
      SocketHttpListener/Net/HttpStatusDescription.cs
  42. 0 79
      SocketHttpListener/Net/HttpStreamAsyncResult.cs
  43. 0 16
      SocketHttpListener/Net/HttpVersion.cs
  44. 0 89
      SocketHttpListener/Net/ListenerPrefix.cs
  45. 0 20
      SocketHttpListener/Net/UriScheme.cs
  46. 0 360
      SocketHttpListener/Net/WebHeaderCollection.cs
  47. 0 84
      SocketHttpListener/Net/WebHeaderEncoding.cs
  48. 0 92
      SocketHttpListener/Net/WebSockets/HttpListenerWebSocketContext.cs
  49. 0 81
      SocketHttpListener/Net/WebSockets/HttpWebSocket.Managed.cs
  50. 0 159
      SocketHttpListener/Net/WebSockets/HttpWebSocket.cs
  51. 0 27
      SocketHttpListener/Net/WebSockets/WebSocketCloseStatus.cs
  52. 0 24
      SocketHttpListener/Net/WebSockets/WebSocketContext.cs
  53. 0 141
      SocketHttpListener/Net/WebSockets/WebSocketValidate.cs
  54. 1 2
      SocketHttpListener/WebSocket.cs

+ 1 - 1
Emby.Server.Implementations/HttpClientManager/HttpClientManager.cs

@@ -327,7 +327,7 @@ namespace Emby.Server.Implementations.HttpClientManager
                     }
                     }
 
 
                     httpWebRequest.ContentType = contentType;
                     httpWebRequest.ContentType = contentType;
-                    httpWebRequest.ContentLength = bytes.Length;
+                    // httpWebRequest.ContentLength = bytes.Length;
                     (await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)).Write(bytes, 0, bytes.Length);
                     (await httpWebRequest.GetRequestStreamAsync().ConfigureAwait(false)).Write(bytes, 0, bytes.Length);
                 }
                 }
                 catch (Exception ex)
                 catch (Exception ex)

+ 10 - 6
Emby.Server.Implementations/HttpServer/FileWriter.cs

@@ -5,6 +5,7 @@ using System.Linq;
 using System.Net;
 using System.Net;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using Emby.Server.Implementations.IO;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
@@ -14,6 +15,7 @@ namespace Emby.Server.Implementations.HttpServer
     public class FileWriter : IHttpResult
     public class FileWriter : IHttpResult
     {
     {
         private ILogger Logger { get; set; }
         private ILogger Logger { get; set; }
+        public IFileSystem FileSystem { get; }
 
 
         private string RangeHeader { get; set; }
         private string RangeHeader { get; set; }
         private bool IsHeadRequest { get; set; }
         private bool IsHeadRequest { get; set; }
@@ -51,6 +53,7 @@ namespace Emby.Server.Implementations.HttpServer
 
 
             Path = path;
             Path = path;
             Logger = logger;
             Logger = logger;
+            FileSystem = fileSystem;
             RangeHeader = rangeHeader;
             RangeHeader = rangeHeader;
 
 
             Headers["Content-Type"] = contentType;
             Headers["Content-Type"] = contentType;
@@ -60,7 +63,8 @@ namespace Emby.Server.Implementations.HttpServer
 
 
             if (string.IsNullOrWhiteSpace(rangeHeader))
             if (string.IsNullOrWhiteSpace(rangeHeader))
             {
             {
-                Headers["Content-Length"] = TotalContentLength.ToString(UsCulture);
+                // TODO
+                //Headers["Content-Length"] = TotalContentLength.ToString(UsCulture);
                 StatusCode = HttpStatusCode.OK;
                 StatusCode = HttpStatusCode.OK;
             }
             }
             else
             else
@@ -95,7 +99,7 @@ namespace Emby.Server.Implementations.HttpServer
 
 
             // Content-Length is the length of what we're serving, not the original content
             // Content-Length is the length of what we're serving, not the original content
             var lengthString = RangeLength.ToString(UsCulture);
             var lengthString = RangeLength.ToString(UsCulture);
-            Headers["Content-Length"] = lengthString;
+            // TODO Headers["Content-Length"] = lengthString;
             var rangeString = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
             var rangeString = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
             Headers["Content-Range"] = rangeString;
             Headers["Content-Range"] = rangeString;
 
 
@@ -174,12 +178,12 @@ namespace Emby.Server.Implementations.HttpServer
                     }
                     }
 
 
                     //var count = FileShare == FileShareMode.ReadWrite ? TotalContentLength : 0;
                     //var count = FileShare == FileShareMode.ReadWrite ? TotalContentLength : 0;
-
-                    await response.TransmitFile(path, 0, 0, FileShare, cancellationToken).ConfigureAwait(false);
+                    // TODO not DI friendly lol
+                    await response.TransmitFile(path, 0, 0, FileShare, FileSystem, new StreamHelper(), cancellationToken).ConfigureAwait(false);
                     return;
                     return;
                 }
                 }
-
-                await response.TransmitFile(path, RangeStart, RangeLength, FileShare, cancellationToken).ConfigureAwait(false);
+                // TODO not DI friendly lol
+                await response.TransmitFile(path, RangeStart, RangeLength, FileShare, FileSystem, new StreamHelper(), cancellationToken).ConfigureAwait(false);
             }
             }
             finally
             finally
             {
             {

+ 3 - 0
Emby.Server.Implementations/HttpServer/HttpListenerHost.cs

@@ -644,6 +644,9 @@ namespace Emby.Server.Implementations.HttpServer
         {
         {
             var bOutput = Encoding.UTF8.GetBytes(text);
             var bOutput = Encoding.UTF8.GetBytes(text);
             response.SetContentLength(bOutput.Length);
             response.SetContentLength(bOutput.Length);
+            // TODO
+            response.Headers.Remove("Content-Length"); // DO NOT SET THIS, IT'S DONE AUTOMATICALLY BECAUSE MS ARE NOT STUPID
+            response.SendChunked = true;
 
 
             return response.OutputStream.WriteAsync(bOutput, 0, bOutput.Length);
             return response.OutputStream.WriteAsync(bOutput, 0, bOutput.Length);
         }
         }

+ 1 - 1
Emby.Server.Implementations/HttpServer/HttpResultFactory.cs

@@ -592,7 +592,7 @@ namespace Emby.Server.Implementations.HttpServer
             {
             {
                 if (totalContentLength.HasValue)
                 if (totalContentLength.HasValue)
                 {
                 {
-                    responseHeaders["Content-Length"] = totalContentLength.Value.ToString(UsCulture);
+                    // TODO responseHeaders["Content-Length"] = totalContentLength.Value.ToString(UsCulture);
                 }
                 }
 
 
                 if (isHeadRequest)
                 if (isHeadRequest)

+ 1 - 1
Emby.Server.Implementations/HttpServer/RangeRequestWriter.cs

@@ -96,7 +96,7 @@ namespace Emby.Server.Implementations.HttpServer
             RangeLength = 1 + RangeEnd - RangeStart;
             RangeLength = 1 + RangeEnd - RangeStart;
 
 
             // Content-Length is the length of what we're serving, not the original content
             // Content-Length is the length of what we're serving, not the original content
-            Headers["Content-Length"] = RangeLength.ToString(UsCulture);
+            // TODO Headers["Content-Length"] = RangeLength.ToString(UsCulture);
             Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
             Headers["Content-Range"] = string.Format("bytes {0}-{1}/{2}", RangeStart, RangeEnd, TotalContentLength);
 
 
             if (RangeStart > 0 && SourceStream.CanSeek)
             if (RangeStart > 0 && SourceStream.CanSeek)

+ 1 - 1
Emby.Server.Implementations/HttpServer/ResponseFilter.cs

@@ -25,7 +25,7 @@ namespace Emby.Server.Implementations.HttpServer
         public void FilterResponse(IRequest req, IResponse res, object dto)
         public void FilterResponse(IRequest req, IResponse res, object dto)
         {
         {
             // Try to prevent compatibility view
             // Try to prevent compatibility view
-            res.AddHeader("Access-Control-Allow-Headers", "Accept, Accept-Language, Authorization, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-Length, Content-MD5, Content-Range, Content-Type, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, X-Emby-Authorization");
+            res.AddHeader("Access-Control-Allow-Headers", "Accept, Accept-Language, Authorization, Cache-Control, Content-Disposition, Content-Encoding, Content-Language, Content-MD5, Content-Range, Content-Type, Date, Host, If-Match, If-Modified-Since, If-None-Match, If-Unmodified-Since, Origin, OriginToken, Pragma, Range, Slug, Transfer-Encoding, Want-Digest, X-MediaBrowser-Token, X-Emby-Authorization");
             res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
             res.AddHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, PATCH, OPTIONS");
             res.AddHeader("Access-Control-Allow-Origin", "*");
             res.AddHeader("Access-Control-Allow-Origin", "*");
 
 

+ 2 - 2
Emby.Server.Implementations/HttpServer/StreamWriter.cs

@@ -56,7 +56,7 @@ namespace Emby.Server.Implementations.HttpServer
 
 
             if (source.CanSeek)
             if (source.CanSeek)
             {
             {
-                Headers["Content-Length"] = source.Length.ToString(UsCulture);
+                // TODO Headers["Content-Length"] = source.Length.ToString(UsCulture);
             }
             }
         }
         }
 
 
@@ -77,7 +77,7 @@ namespace Emby.Server.Implementations.HttpServer
 
 
             Headers["Content-Type"] = contentType;
             Headers["Content-Type"] = contentType;
 
 
-            Headers["Content-Length"] = contentLength.ToString(UsCulture);
+            // TODO Headers["Content-Length"] = contentLength.ToString(UsCulture);
         }
         }
 
 
         public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken)
         public async Task WriteToAsync(Stream responseStream, CancellationToken cancellationToken)

+ 38 - 16
Jellyfin.Server/SocketSharp/WebSocketSharpListener.cs

@@ -1,6 +1,7 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
-using System.Security.Cryptography.X509Certificates;
+ using System.Net;
+ using System.Security.Cryptography.X509Certificates;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using Emby.Server.Implementations.HttpServer;
 using Emby.Server.Implementations.HttpServer;
@@ -13,9 +14,8 @@ using MediaBrowser.Model.Net;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.System;
 using MediaBrowser.Model.System;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
-using SocketHttpListener.Net;
 
 
-namespace Jellyfin.Server.SocketSharp
+ namespace Jellyfin.Server.SocketSharp
 {
 {
     public class WebSocketSharpListener : IHttpListener
     public class WebSocketSharpListener : IHttpListener
     {
     {
@@ -67,24 +67,44 @@ namespace Jellyfin.Server.SocketSharp
 
 
         public void Start(IEnumerable<string> urlPrefixes)
         public void Start(IEnumerable<string> urlPrefixes)
         {
         {
-            if (_listener == null)
-            {
-                _listener = new HttpListener(_logger, _cryptoProvider, _socketFactory, _streamHelper, _fileSystem, _environment);
-            }
+            // TODO
+            //if (_listener == null)
+            //{
+            //    _listener = new HttpListener(_logger, _cryptoProvider, _socketFactory, _streamHelper, _fileSystem, _environment);
+            //}
+
+            //_listener.EnableDualMode = _enableDualMode;
+
+            //if (_certificate != null)
+            //{
+            //    _listener.LoadCert(_certificate);
+            //}
 
 
-            _listener.EnableDualMode = _enableDualMode;
+            //_logger.LogInformation("Adding HttpListener prefixes {Prefixes}", urlPrefixes);
+            //_listener.Prefixes.AddRange(urlPrefixes);
 
 
-            if (_certificate != null)
+            //_listener.OnContext = async c => await InitTask(c, _disposeCancellationToken).ConfigureAwait(false);
+
+            //_listener.Start();
+
+            if (_listener == null)
             {
             {
-                _listener.LoadCert(_certificate);
+                _listener = new HttpListener();
             }
             }
-
+            
             _logger.LogInformation("Adding HttpListener prefixes {Prefixes}", urlPrefixes);
             _logger.LogInformation("Adding HttpListener prefixes {Prefixes}", urlPrefixes);
-            _listener.Prefixes.AddRange(urlPrefixes);
 
 
-            _listener.OnContext = async c => await InitTask(c, _disposeCancellationToken).ConfigureAwait(false);
+            //foreach (var urlPrefix in urlPrefixes)
+            //{
+            //    _listener.Prefixes.Add(urlPrefix);
+            //}
+            _listener.Prefixes.Add("http://localhost:8096/");
 
 
             _listener.Start();
             _listener.Start();
+
+            // TODO how to do this in netcore?
+            _listener.BeginGetContext(async c => await InitTask(c, _disposeCancellationToken).ConfigureAwait(false),
+                null);
         }
         }
 
 
         private static void LogRequest(ILogger logger, HttpListenerRequest request)
         private static void LogRequest(ILogger logger, HttpListenerRequest request)
@@ -98,8 +118,10 @@ namespace Jellyfin.Server.SocketSharp
                 request.UserAgent ?? string.Empty);
                 request.UserAgent ?? string.Empty);
         }
         }
 
 
-        private Task InitTask(HttpListenerContext context, CancellationToken cancellationToken)
+        private Task InitTask(IAsyncResult asyncResult, CancellationToken cancellationToken)
         {
         {
+            var context = _listener.EndGetContext(asyncResult);
+            _listener.BeginGetContext(async c => await InitTask(c, _disposeCancellationToken).ConfigureAwait(false), null);
             IHttpRequest httpReq = null;
             IHttpRequest httpReq = null;
             var request = context.Request;
             var request = context.Request;
 
 
@@ -134,7 +156,7 @@ namespace Jellyfin.Server.SocketSharp
                 var endpoint = ctx.Request.RemoteEndPoint.ToString();
                 var endpoint = ctx.Request.RemoteEndPoint.ToString();
                 var url = ctx.Request.RawUrl;
                 var url = ctx.Request.RawUrl;
 
 
-                var queryString = ctx.Request.QueryString;
+                var queryString = new QueryParamCollection(ctx.Request.QueryString);
 
 
                 var connectingArgs = new WebSocketConnectingEventArgs
                 var connectingArgs = new WebSocketConnectingEventArgs
                 {
                 {
@@ -153,7 +175,7 @@ namespace Jellyfin.Server.SocketSharp
 
 
                     if (WebSocketConnected != null)
                     if (WebSocketConnected != null)
                     {
                     {
-                        var socket = new SharpWebSocket(webSocketContext.WebSocket, _logger);
+                        SharpWebSocket socket = null; //new SharpWebSocket(webSocketContext.WebSocket, _logger);
                         await socket.ConnectAsServerAsync().ConfigureAwait(false);
                         await socket.ConnectAsServerAsync().ConfigureAwait(false);
 
 
                         WebSocketConnected(new WebSocketConnectEventArgs
                         WebSocketConnected(new WebSocketConnectEventArgs

+ 2 - 1
Jellyfin.Server/SocketSharp/WebSocketSharpRequest.cs

@@ -2,6 +2,7 @@ using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Globalization;
 using System.Globalization;
 using System.IO;
 using System.IO;
+using System.Net;
 using System.Text;
 using System.Text;
 using Emby.Server.Implementations.HttpServer;
 using Emby.Server.Implementations.HttpServer;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
@@ -438,7 +439,7 @@ namespace Jellyfin.Server.SocketSharp
 
 
         public string UserAgent => request.UserAgent;
         public string UserAgent => request.UserAgent;
 
 
-        public QueryParamCollection Headers => request.Headers;
+        public QueryParamCollection Headers => new QueryParamCollection(request.Headers);
 
 
         private QueryParamCollection queryString;
         private QueryParamCollection queryString;
         public QueryParamCollection QueryString => queryString ?? (queryString = MyHttpUtility.ParseQueryString(request.Url.Query));
         public QueryParamCollection QueryString => queryString ?? (queryString = MyHttpUtility.ParseQueryString(request.Url.Query));

+ 40 - 6
Jellyfin.Server/SocketSharp/WebSocketSharpResponse.cs

@@ -3,13 +3,14 @@ using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Net;
 using System.Net;
 using System.Net.Sockets;
 using System.Net.Sockets;
+using System.Runtime.InteropServices;
 using System.Text;
 using System.Text;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using Emby.Server.Implementations;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.IO;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
 using Microsoft.Extensions.Logging;
 using Microsoft.Extensions.Logging;
-using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse;
 using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
 using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
 using IRequest = MediaBrowser.Model.Services.IRequest;
 using IRequest = MediaBrowser.Model.Services.IRequest;
 
 
@@ -53,7 +54,7 @@ namespace Jellyfin.Server.SocketSharp
             set => _response.ContentType = value;
             set => _response.ContentType = value;
         }
         }
 
 
-        public QueryParamCollection Headers => _response.Headers;
+        public QueryParamCollection Headers => new QueryParamCollection(_response.Headers);
 
 
         private static string AsHeaderValue(Cookie cookie)
         private static string AsHeaderValue(Cookie cookie)
         {
         {
@@ -152,7 +153,7 @@ namespace Jellyfin.Server.SocketSharp
             // you can happily set the Content-Length header in Asp.Net
             // you can happily set the Content-Length header in Asp.Net
             // but HttpListener will complain if you do - you have to set ContentLength64 on the response.
             // but HttpListener will complain if you do - you have to set ContentLength64 on the response.
             // workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header
             // workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header
-            _response.ContentLength64 = contentLength;
+            //_response.ContentLength64 = contentLength;
         }
         }
 
 
         public void SetCookie(Cookie cookie)
         public void SetCookie(Cookie cookie)
@@ -172,10 +173,43 @@ namespace Jellyfin.Server.SocketSharp
         public void ClearCookies()
         public void ClearCookies()
         {
         {
         }
         }
-
-        public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
+        const int StreamCopyToBufferSize = 81920;
+        public async Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, IFileSystem fileSystem, IStreamHelper streamHelper, CancellationToken cancellationToken)
         {
         {
-            return _response.TransmitFile(path, offset, count, fileShareMode, cancellationToken);
+            // TODO
+            // return _response.TransmitFile(path, offset, count, fileShareMode, cancellationToken);
+            var allowAsync = !RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
+
+            //if (count <= 0)
+            //{
+            //    allowAsync = true;
+            //}
+
+            var fileOpenOptions = 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)
+                {
+                    fs.Position = offset;
+                }
+                
+                if (count > 0)
+                {
+                    await streamHelper.CopyToAsync(fs, OutputStream, count, cancellationToken).ConfigureAwait(false);
+                }
+                else
+                {
+                    await fs.CopyToAsync(OutputStream, StreamCopyToBufferSize, cancellationToken).ConfigureAwait(false);
+                }
+            }
         }
         }
     }
     }
 }
 }

+ 10 - 8
MediaBrowser.Api/Playback/Progressive/BaseProgressiveStreamingService.cs

@@ -324,7 +324,8 @@ namespace MediaBrowser.Api.Playback.Progressive
             // Seeing cases of -1 here
             // Seeing cases of -1 here
             if (response.ContentLength.HasValue && response.ContentLength.Value >= 0)
             if (response.ContentLength.HasValue && response.ContentLength.Value >= 0)
             {
             {
-                responseHeaders["Content-Length"] = response.ContentLength.Value.ToString(UsCulture);
+                // TODO
+                //responseHeaders["Content-Length"] = response.ContentLength.Value.ToString(UsCulture);
             }
             }
 
 
             if (isHeadRequest)
             if (isHeadRequest)
@@ -382,17 +383,18 @@ namespace MediaBrowser.Api.Playback.Progressive
                 var hasHeaders = streamResult as IHasHeaders;
                 var hasHeaders = streamResult as IHasHeaders;
                 if (hasHeaders != null)
                 if (hasHeaders != null)
                 {
                 {
-                    if (contentLength.HasValue)
-                    {
-                        hasHeaders.Headers["Content-Length"] = contentLength.Value.ToString(CultureInfo.InvariantCulture);
-                    }
-                    else
-                    {
+                    // TODO
+                    //if (contentLength.HasValue)
+                    //{
+                    //    hasHeaders.Headers["Content-Length"] = contentLength.Value.ToString(CultureInfo.InvariantCulture);
+                    //}
+                    //else
+                    //{
                         if (hasHeaders.Headers.ContainsKey("Content-Length"))
                         if (hasHeaders.Headers.ContainsKey("Content-Length"))
                         {
                         {
                             hasHeaders.Headers.Remove("Content-Length");
                             hasHeaders.Headers.Remove("Content-Length");
                         }
                         }
-                    }
+                    //}
                 }
                 }
 
 
                 return streamResult;
                 return streamResult;

+ 1 - 1
MediaBrowser.Model/Services/IRequest.cs

@@ -152,7 +152,7 @@ namespace MediaBrowser.Model.Services
 
 
         QueryParamCollection Headers { get; }
         QueryParamCollection Headers { get; }
 
 
-        Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken);
+        Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, IFileSystem fileSystem, IStreamHelper streamHelper, CancellationToken cancellationToken);
 
 
         bool SendChunked { get; set; }
         bool SendChunked { get; set; }
     }
     }

+ 31 - 0
MediaBrowser.Model/Services/QueryParamCollection.cs

@@ -1,10 +1,13 @@
 using System;
 using System;
 using System.Collections.Generic;
 using System.Collections.Generic;
+using System.Collections.Specialized;
 using System.Linq;
 using System.Linq;
+using System.Net;
 using MediaBrowser.Model.Dto;
 using MediaBrowser.Model.Dto;
 
 
 namespace MediaBrowser.Model.Services
 namespace MediaBrowser.Model.Services
 {
 {
+    // Remove this garbage class, it's just a bastard copy of NameValueCollection
     public class QueryParamCollection : List<NameValuePair>
     public class QueryParamCollection : List<NameValuePair>
     {
     {
         public QueryParamCollection()
         public QueryParamCollection()
@@ -20,6 +23,30 @@ namespace MediaBrowser.Model.Services
             }
             }
         }
         }
 
 
+        // TODO remove this shit
+        public QueryParamCollection(WebHeaderCollection webHeaderCollection)
+        {
+            foreach (var key in webHeaderCollection.AllKeys)
+            {
+                foreach (var value in webHeaderCollection.GetValues(key) ?? Array.Empty<string>())
+                {
+                    Add(key, value);
+                }
+            }
+        }
+
+        // TODO remove this shit
+        public QueryParamCollection(NameValueCollection nameValueCollection)
+        {
+            foreach (var key in nameValueCollection.AllKeys)
+            {
+                foreach (var value in nameValueCollection.GetValues(key) ?? Array.Empty<string>())
+                {
+                    Add(key, value);
+                }
+            }
+        }
+
         private static StringComparison GetStringComparison()
         private static StringComparison GetStringComparison()
         {
         {
             return StringComparison.OrdinalIgnoreCase;
             return StringComparison.OrdinalIgnoreCase;
@@ -50,6 +77,10 @@ namespace MediaBrowser.Model.Services
         /// </summary>
         /// </summary>
         public virtual void Add(string key, string value)
         public virtual void Add(string key, string value)
         {
         {
+            if (string.Equals(key, "content-length", StringComparison.OrdinalIgnoreCase))
+            {
+                return;
+            }
             Add(new NameValuePair(key, value));
             Add(new NameValuePair(key, value));
         }
         }
 
 

+ 0 - 1
SocketHttpListener/Ext.cs

@@ -6,7 +6,6 @@ using System.Net;
 using System.Text;
 using System.Text;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
 using MediaBrowser.Model.Services;
 using MediaBrowser.Model.Services;
-using HttpStatusCode = SocketHttpListener.Net.HttpStatusCode;
 using WebSocketState = System.Net.WebSockets.WebSocketState;
 using WebSocketState = System.Net.WebSockets.WebSocketState;
 
 
 namespace SocketHttpListener
 namespace SocketHttpListener

+ 121 - 122
SocketHttpListener/HttpResponse.cs

@@ -1,123 +1,122 @@
-using System;
-using System.Linq;
-using System.Net;
-using System.Text;
-using MediaBrowser.Model.Services;
-using SocketHttpListener.Net;
-using HttpStatusCode = SocketHttpListener.Net.HttpStatusCode;
-using HttpVersion = SocketHttpListener.Net.HttpVersion;
-
-namespace SocketHttpListener
+using System;
+using System.Linq;
+using System.Net;
+using System.Text;
+using MediaBrowser.Model.Services;
+using SocketHttpListener.Net;
+
+namespace SocketHttpListener
 {
 {
-    internal class HttpResponse : HttpBase
-    {
-        #region Private Fields
-
-        private string _code;
-        private string _reason;
-
-        #endregion
-
-        #region Private Constructors
-
-        private HttpResponse(string code, string reason, Version version, QueryParamCollection headers)
-            : base(version, headers)
-        {
-            _code = code;
-            _reason = reason;
-        }
-
-        #endregion
-
-        #region Internal Constructors
-
-        internal HttpResponse(HttpStatusCode code)
-            : this(code, code.GetDescription())
-        {
-        }
-
-        internal HttpResponse(HttpStatusCode code, string reason)
-            : this(((int)code).ToString(), reason, HttpVersion.Version11, new QueryParamCollection())
-        {
-            Headers["Server"] = "websocket-sharp/1.0";
-        }
-
-        #endregion
-
-        #region Public Properties
-
-        public CookieCollection Cookies => GetCookies(Headers, true);
-
-        private static CookieCollection GetCookies(QueryParamCollection headers, bool response)
-        {
-            var name = response ? "Set-Cookie" : "Cookie";
-            return headers == null || !headers.Contains(name)
-                   ? new CookieCollection()
-                   : CookieHelper.Parse(headers[name], response);
-        }
-
-        public bool IsProxyAuthenticationRequired => _code == "407";
-
-        public bool IsUnauthorized => _code == "401";
-
-        public bool IsWebSocketResponse
-        {
-            get
-            {
-                var headers = Headers;
-                return ProtocolVersion > HttpVersion.Version10 &&
-                       _code == "101" &&
-                       headers.Contains("Upgrade", "websocket") &&
-                       headers.Contains("Connection", "Upgrade");
-            }
-        }
-
-        public string Reason => _reason;
-
-        public string StatusCode => _code;
-
-        #endregion
-
-        #region Internal Methods
-
-        internal static HttpResponse CreateCloseResponse(HttpStatusCode code)
-        {
-            var res = new HttpResponse(code);
-            res.Headers["Connection"] = "close";
-
-            return res;
-        }
-
-        #endregion
-
-        #region Public Methods
-
-        public void SetCookies(CookieCollection cookies)
-        {
-            if (cookies == null || cookies.Count == 0)
-                return;
-
-            var headers = Headers;
-            var sorted = cookies.OfType<Cookie>().OrderBy(i => i.Name).ToList();
-
-            foreach (var cookie in sorted)
-                headers.Add("Set-Cookie", cookie.ToString());
-        }
-
-        public override string ToString()
-        {
-            var output = new StringBuilder(64);
-            output.AppendFormat("HTTP/{0} {1} {2}{3}", ProtocolVersion, _code, _reason, CrLf);
-
-            var headers = Headers;
-            foreach (var key in headers.Keys)
-                output.AppendFormat("{0}: {1}{2}", key, headers[key], CrLf);
-
-            output.Append(CrLf);
-
-            return output.ToString();
-        }
-
-        #endregion
-    }
-}
+    // TODO what is the point of this class?
+    internal class HttpResponse : HttpBase
+    {
+        #region Private Fields
+
+        private string _code;
+        private string _reason;
+
+        #endregion
+
+        #region Private Constructors
+
+        private HttpResponse(string code, string reason, Version version, QueryParamCollection headers)
+            : base(version, headers)
+        {
+            _code = code;
+            _reason = reason;
+        }
+
+        #endregion
+
+        #region Internal Constructors
+
+        internal HttpResponse(HttpStatusCode code)
+            : this(code, code.GetDescription())
+        {
+        }
+
+        internal HttpResponse(HttpStatusCode code, string reason)
+            : this(((int)code).ToString(), reason, HttpVersion.Version11, new QueryParamCollection())
+        {
+            Headers["Server"] = "websocket-sharp/1.0";
+        }
+
+        #endregion
+
+        #region Public Properties
+
+        public CookieCollection Cookies => GetCookies(Headers, true);
+
+        private static CookieCollection GetCookies(QueryParamCollection headers, bool response)
+        {
+            var name = response ? "Set-Cookie" : "Cookie";
+            return headers == null || !headers.Contains(name)
+                   ? new CookieCollection()
+                   : CookieHelper.Parse(headers[name], response);
+        }
+
+        public bool IsProxyAuthenticationRequired => _code == "407";
+
+        public bool IsUnauthorized => _code == "401";
+
+        public bool IsWebSocketResponse
+        {
+            get
+            {
+                var headers = Headers;
+                return ProtocolVersion > HttpVersion.Version10 &&
+                       _code == "101" &&
+                       headers.Contains("Upgrade", "websocket") &&
+                       headers.Contains("Connection", "Upgrade");
+            }
+        }
+
+        public string Reason => _reason;
+
+        public string StatusCode => _code;
+
+        #endregion
+
+        #region Internal Methods
+
+        internal static HttpResponse CreateCloseResponse(HttpStatusCode code)
+        {
+            var res = new HttpResponse(code);
+            res.Headers["Connection"] = "close";
+
+            return res;
+        }
+
+        #endregion
+
+        #region Public Methods
+
+        public void SetCookies(CookieCollection cookies)
+        {
+            if (cookies == null || cookies.Count == 0)
+                return;
+
+            var headers = Headers;
+            var sorted = cookies.OfType<Cookie>().OrderBy(i => i.Name).ToList();
+
+            foreach (var cookie in sorted)
+                headers.Add("Set-Cookie", cookie.ToString());
+        }
+
+        public override string ToString()
+        {
+            var output = new StringBuilder(64);
+            output.AppendFormat("HTTP/{0} {1} {2}{3}", ProtocolVersion, _code, _reason, CrLf);
+
+            var headers = Headers;
+            foreach (var key in headers.Keys)
+                output.AppendFormat("{0}: {1}{2}", key, headers[key], CrLf);
+
+            output.Append(CrLf);
+
+            return output.ToString();
+        }
+
+        #endregion
+    }
+}

+ 0 - 6
SocketHttpListener/Net/AuthenticationSchemeSelector.cs

@@ -1,6 +0,0 @@
-using System.Net;
-
-namespace SocketHttpListener.Net
-{
-    public delegate AuthenticationSchemes AuthenticationSchemeSelector(HttpListenerRequest httpRequest);
-}

+ 0 - 9
SocketHttpListener/Net/AuthenticationTypes.cs

@@ -1,9 +0,0 @@
-namespace SocketHttpListener.Net
-{
-    internal class AuthenticationTypes
-    {
-        internal const string NTLM = "NTLM";
-        internal const string Negotiate = "Negotiate";
-        internal const string Basic = "Basic";
-    }
-}

+ 0 - 11
SocketHttpListener/Net/BoundaryType.cs

@@ -1,11 +0,0 @@
-namespace SocketHttpListener.Net
-{
-    internal enum BoundaryType
-    {
-        ContentLength = 0, // Content-Length: XXX
-        Chunked = 1, // Transfer-Encoding: chunked
-        Multipart = 3,
-        None = 4,
-        Invalid = 5,
-    }
-}

+ 0 - 385
SocketHttpListener/Net/ChunkStream.cs

@@ -1,385 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Net;
-using System.Text;
-
-namespace SocketHttpListener.Net
-{
-    // Licensed to the .NET Foundation under one or more agreements.
-    // See the LICENSE file in the project root for more information.
-    //
-    // System.Net.ResponseStream
-    //
-    // Author:
-    //  Gonzalo Paniagua Javier (gonzalo@novell.com)
-    //
-    // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
-    //
-    // Permission is hereby granted, free of charge, to any person obtaining
-    // a copy of this software and associated documentation files (the
-    // "Software"), to deal in the Software without restriction, including
-    // without limitation the rights to use, copy, modify, merge, publish,
-    // distribute, sublicense, and/or sell copies of the Software, and to
-    // permit persons to whom the Software is furnished to do so, subject to
-    // the following conditions:
-    //
-    // The above copyright notice and this permission notice shall be
-    // included in all copies or substantial portions of the Software.
-    //
-    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-    // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-    // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-    //
-
-    internal sealed class ChunkStream
-    {
-        private enum State
-        {
-            None,
-            PartialSize,
-            Body,
-            BodyFinished,
-            Trailer
-        }
-
-        private class Chunk
-        {
-            public byte[] Bytes;
-            public int Offset;
-
-            public Chunk(byte[] chunk)
-            {
-                Bytes = chunk;
-            }
-
-            public int Read(byte[] buffer, int offset, int size)
-            {
-                int nread = (size > Bytes.Length - Offset) ? Bytes.Length - Offset : size;
-                Buffer.BlockCopy(Bytes, Offset, buffer, offset, nread);
-                Offset += nread;
-                return nread;
-            }
-        }
-
-        internal WebHeaderCollection _headers;
-        private int _chunkSize;
-        private int _chunkRead;
-        private int _totalWritten;
-        private State _state;
-        private StringBuilder _saved;
-        private bool _sawCR;
-        private bool _gotit;
-        private int _trailerState;
-        private List<Chunk> _chunks;
-
-        public ChunkStream(WebHeaderCollection headers)
-        {
-            _headers = headers;
-            _saved = new StringBuilder();
-            _chunks = new List<Chunk>();
-            _chunkSize = -1;
-            _totalWritten = 0;
-        }
-
-        public void ResetBuffer()
-        {
-            _chunkSize = -1;
-            _chunkRead = 0;
-            _totalWritten = 0;
-            _chunks.Clear();
-        }
-
-        public int Read(byte[] buffer, int offset, int size)
-        {
-            return ReadFromChunks(buffer, offset, size);
-        }
-
-        private int ReadFromChunks(byte[] buffer, int offset, int size)
-        {
-            int count = _chunks.Count;
-            int nread = 0;
-
-            var chunksForRemoving = new List<Chunk>(count);
-            for (int i = 0; i < count; i++)
-            {
-                var chunk = _chunks[i];
-
-                if (chunk.Offset == chunk.Bytes.Length)
-                {
-                    chunksForRemoving.Add(chunk);
-                    continue;
-                }
-
-                nread += chunk.Read(buffer, offset + nread, size - nread);
-                if (nread == size)
-                    break;
-            }
-
-            foreach (var chunk in chunksForRemoving)
-                _chunks.Remove(chunk);
-
-            return nread;
-        }
-
-        public void Write(byte[] buffer, int offset, int size)
-        {
-            // Note, the logic here only works when offset is 0 here.
-            // Otherwise, it would treat "size" as the end offset instead of an actual byte count from offset.
-
-            if (offset < size)
-                InternalWrite(buffer, ref offset, size);
-        }
-
-        private void InternalWrite(byte[] buffer, ref int offset, int size)
-        {
-            if (_state == State.None || _state == State.PartialSize)
-            {
-                _state = GetChunkSize(buffer, ref offset, size);
-                if (_state == State.PartialSize)
-                    return;
-
-                _saved.Length = 0;
-                _sawCR = false;
-                _gotit = false;
-            }
-
-            if (_state == State.Body && offset < size)
-            {
-                _state = ReadBody(buffer, ref offset, size);
-                if (_state == State.Body)
-                    return;
-            }
-
-            if (_state == State.BodyFinished && offset < size)
-            {
-                _state = ReadCRLF(buffer, ref offset, size);
-                if (_state == State.BodyFinished)
-                    return;
-
-                _sawCR = false;
-            }
-
-            if (_state == State.Trailer && offset < size)
-            {
-                _state = ReadTrailer(buffer, ref offset, size);
-                if (_state == State.Trailer)
-                    return;
-
-                _saved.Length = 0;
-                _sawCR = false;
-                _gotit = false;
-            }
-
-            if (offset < size)
-                InternalWrite(buffer, ref offset, size);
-        }
-
-        public bool WantMore => (_chunkRead != _chunkSize || _chunkSize != 0 || _state != State.None);
-
-        public bool DataAvailable
-        {
-            get
-            {
-                int count = _chunks.Count;
-                for (int i = 0; i < count; i++)
-                {
-                    var ch = _chunks[i];
-                    if (ch == null || ch.Bytes == null)
-                        continue;
-                    if (ch.Bytes.Length > 0 && ch.Offset < ch.Bytes.Length)
-                        return (_state != State.Body);
-                }
-                return false;
-            }
-        }
-
-        public int TotalDataSize => _totalWritten;
-
-        public int ChunkLeft => _chunkSize - _chunkRead;
-
-        private State ReadBody(byte[] buffer, ref int offset, int size)
-        {
-            if (_chunkSize == 0)
-                return State.BodyFinished;
-
-            int diff = size - offset;
-            if (diff + _chunkRead > _chunkSize)
-                diff = _chunkSize - _chunkRead;
-
-            byte[] chunk = new byte[diff];
-            Buffer.BlockCopy(buffer, offset, chunk, 0, diff);
-            _chunks.Add(new Chunk(chunk));
-            offset += diff;
-            _chunkRead += diff;
-            _totalWritten += diff;
-
-            return (_chunkRead == _chunkSize) ? State.BodyFinished : State.Body;
-        }
-
-        private State GetChunkSize(byte[] buffer, ref int offset, int size)
-        {
-            _chunkRead = 0;
-            _chunkSize = 0;
-            char c = '\0';
-            while (offset < size)
-            {
-                c = (char)buffer[offset++];
-                if (c == '\r')
-                {
-                    if (_sawCR)
-                        ThrowProtocolViolation("2 CR found");
-
-                    _sawCR = true;
-                    continue;
-                }
-
-                if (_sawCR && c == '\n')
-                    break;
-
-                if (c == ' ')
-                    _gotit = true;
-
-                if (!_gotit)
-                    _saved.Append(c);
-
-                if (_saved.Length > 20)
-                    ThrowProtocolViolation("chunk size too long.");
-            }
-
-            if (!_sawCR || c != '\n')
-            {
-                if (offset < size)
-                    ThrowProtocolViolation("Missing \\n");
-
-                try
-                {
-                    if (_saved.Length > 0)
-                    {
-                        _chunkSize = int.Parse(RemoveChunkExtension(_saved.ToString()), NumberStyles.HexNumber);
-                    }
-                }
-                catch (Exception)
-                {
-                    ThrowProtocolViolation("Cannot parse chunk size.");
-                }
-
-                return State.PartialSize;
-            }
-
-            _chunkRead = 0;
-            try
-            {
-                _chunkSize = int.Parse(RemoveChunkExtension(_saved.ToString()), NumberStyles.HexNumber);
-            }
-            catch (Exception)
-            {
-                ThrowProtocolViolation("Cannot parse chunk size.");
-            }
-
-            if (_chunkSize == 0)
-            {
-                _trailerState = 2;
-                return State.Trailer;
-            }
-
-            return State.Body;
-        }
-
-        private static string RemoveChunkExtension(string input)
-        {
-            int idx = input.IndexOf(';');
-            if (idx == -1)
-                return input;
-            return input.Substring(0, idx);
-        }
-
-        private State ReadCRLF(byte[] buffer, ref int offset, int size)
-        {
-            if (!_sawCR)
-            {
-                if ((char)buffer[offset++] != '\r')
-                    ThrowProtocolViolation("Expecting \\r");
-
-                _sawCR = true;
-                if (offset == size)
-                    return State.BodyFinished;
-            }
-
-            if (_sawCR && (char)buffer[offset++] != '\n')
-                ThrowProtocolViolation("Expecting \\n");
-
-            return State.None;
-        }
-
-        private State ReadTrailer(byte[] buffer, ref int offset, int size)
-        {
-            char c = '\0';
-
-            // short path
-            if (_trailerState == 2 && (char)buffer[offset] == '\r' && _saved.Length == 0)
-            {
-                offset++;
-                if (offset < size && (char)buffer[offset] == '\n')
-                {
-                    offset++;
-                    return State.None;
-                }
-                offset--;
-            }
-
-            int st = _trailerState;
-            string stString = "\r\n\r";
-            while (offset < size && st < 4)
-            {
-                c = (char)buffer[offset++];
-                if ((st == 0 || st == 2) && c == '\r')
-                {
-                    st++;
-                    continue;
-                }
-
-                if ((st == 1 || st == 3) && c == '\n')
-                {
-                    st++;
-                    continue;
-                }
-
-                if (st > 0)
-                {
-                    _saved.Append(stString.Substring(0, _saved.Length == 0 ? st - 2 : st));
-                    st = 0;
-                    if (_saved.Length > 4196)
-                        ThrowProtocolViolation("Error reading trailer (too long).");
-                }
-            }
-
-            if (st < 4)
-            {
-                _trailerState = st;
-                if (offset < size)
-                    ThrowProtocolViolation("Error reading trailer.");
-
-                return State.Trailer;
-            }
-
-            var reader = new StringReader(_saved.ToString());
-            string line;
-            while ((line = reader.ReadLine()) != null && line != "")
-                _headers.Add(line);
-
-            return State.None;
-        }
-
-        private static void ThrowProtocolViolation(string message)
-        {
-            var we = new WebException(message, null, WebExceptionStatus.ServerProtocolViolation, null);
-            throw we;
-        }
-    }
-}

+ 0 - 178
SocketHttpListener/Net/ChunkedInputStream.cs

@@ -1,178 +0,0 @@
-using System;
-using System.IO;
-using System.Net;
-
-namespace SocketHttpListener.Net
-{
-    // Licensed to the .NET Foundation under one or more agreements.
-    // See the LICENSE file in the project root for more information.
-    //
-    // System.Net.ResponseStream
-    //
-    // Author:
-    //  Gonzalo Paniagua Javier (gonzalo@novell.com)
-    //
-    // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
-    //
-    // Permission is hereby granted, free of charge, to any person obtaining
-    // a copy of this software and associated documentation files (the
-    // "Software"), to deal in the Software without restriction, including
-    // without limitation the rights to use, copy, modify, merge, publish,
-    // distribute, sublicense, and/or sell copies of the Software, and to
-    // permit persons to whom the Software is furnished to do so, subject to
-    // the following conditions:
-    //
-    // The above copyright notice and this permission notice shall be
-    // included in all copies or substantial portions of the Software.
-    //
-    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-    // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-    // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-    //
-
-    internal sealed class ChunkedInputStream : HttpRequestStream
-    {
-        private ChunkStream _decoder;
-        private readonly HttpListenerContext _context;
-        private bool _no_more_data;
-
-        private class ReadBufferState
-        {
-            public byte[] Buffer;
-            public int Offset;
-            public int Count;
-            public int InitialCount;
-            public HttpStreamAsyncResult Ares;
-            public ReadBufferState(byte[] buffer, int offset, int count, HttpStreamAsyncResult ares)
-            {
-                Buffer = buffer;
-                Offset = offset;
-                Count = count;
-                InitialCount = count;
-                Ares = ares;
-            }
-        }
-
-        public ChunkedInputStream(HttpListenerContext context, Stream stream, byte[] buffer, int offset, int length)
-                    : base(stream, buffer, offset, length)
-        {
-            _context = context;
-            var coll = (WebHeaderCollection)context.Request.Headers;
-            _decoder = new ChunkStream(coll);
-        }
-
-        public ChunkStream Decoder
-        {
-            get => _decoder;
-            set => _decoder = value;
-        }
-
-        protected override int ReadCore(byte[] buffer, int offset, int count)
-        {
-            IAsyncResult ares = BeginReadCore(buffer, offset, count, null, null);
-            return EndRead(ares);
-        }
-
-        protected override IAsyncResult BeginReadCore(byte[] buffer, int offset, int size, AsyncCallback cback, object state)
-        {
-            var ares = new HttpStreamAsyncResult(this);
-            ares._callback = cback;
-            ares._state = state;
-            if (_no_more_data || size == 0 || _closed)
-            {
-                ares.Complete();
-                return ares;
-            }
-            int nread = _decoder.Read(buffer, offset, size);
-            offset += nread;
-            size -= nread;
-            if (size == 0)
-            {
-                // got all we wanted, no need to bother the decoder yet
-                ares._count = nread;
-                ares.Complete();
-                return ares;
-            }
-            if (!_decoder.WantMore)
-            {
-                _no_more_data = nread == 0;
-                ares._count = nread;
-                ares.Complete();
-                return ares;
-            }
-            ares._buffer = new byte[8192];
-            ares._offset = 0;
-            ares._count = 8192;
-            var rb = new ReadBufferState(buffer, offset, size, ares);
-            rb.InitialCount += nread;
-            base.BeginReadCore(ares._buffer, ares._offset, ares._count, OnRead, rb);
-            return ares;
-        }
-
-        private void OnRead(IAsyncResult base_ares)
-        {
-            ReadBufferState rb = (ReadBufferState)base_ares.AsyncState;
-            var ares = rb.Ares;
-            try
-            {
-                int nread = base.EndRead(base_ares);
-                if (nread == 0)
-                {
-                    _no_more_data = true;
-                    ares._count = rb.InitialCount - rb.Count;
-                    ares.Complete();
-                    return;
-                }
-
-                _decoder.Write(ares._buffer, ares._offset, nread);
-                nread = _decoder.Read(rb.Buffer, rb.Offset, rb.Count);
-                rb.Offset += nread;
-                rb.Count -= nread;
-                if (rb.Count == 0 || !_decoder.WantMore)
-                {
-                    _no_more_data = !_decoder.WantMore && nread == 0;
-                    ares._count = rb.InitialCount - rb.Count;
-                    ares.Complete();
-                    return;
-                }
-                ares._offset = 0;
-                ares._count = Math.Min(8192, _decoder.ChunkLeft + 6);
-                base.BeginReadCore(ares._buffer, ares._offset, ares._count, OnRead, rb);
-            }
-            catch (Exception e)
-            {
-                _context.Connection.SendError(e.Message, 400);
-                ares.Complete(e);
-            }
-        }
-
-        public override int EndRead(IAsyncResult asyncResult)
-        {
-            if (asyncResult == null)
-                throw new ArgumentNullException(nameof(asyncResult));
-
-            var ares = asyncResult as HttpStreamAsyncResult;
-            if (ares == null || !ReferenceEquals(this, ares._parent))
-            {
-                throw new ArgumentException("Invalid async result");
-            }
-            if (ares._endCalled)
-            {
-                throw new InvalidOperationException("Invalid end call");
-            }
-            ares._endCalled = true;
-
-            if (!asyncResult.IsCompleted)
-                asyncResult.AsyncWaitHandle.WaitOne();
-
-            if (ares._error != null)
-                throw new HttpListenerException((int)HttpStatusCode.BadRequest, "Operation aborted");
-
-            return ares._count;
-        }
-    }
-}

+ 0 - 8
SocketHttpListener/Net/EntitySendFormat.cs

@@ -1,8 +0,0 @@
-namespace SocketHttpListener.Net
-{
-    internal enum EntitySendFormat
-    {
-        ContentLength = 0, // Content-Length: XXX
-        Chunked = 1, // Transfer-Encoding: chunked
-    }
-}

+ 0 - 528
SocketHttpListener/Net/HttpConnection.cs

@@ -1,528 +0,0 @@
-using System;
-using System.IO;
-using System.Net;
-using System.Net.Security;
-using System.Net.Sockets;
-using System.Security.Authentication;
-using System.Security.Cryptography.X509Certificates;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Cryptography;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.System;
-using Microsoft.Extensions.Logging;
-namespace SocketHttpListener.Net
-{
-    sealed class HttpConnection
-    {
-        private static AsyncCallback s_onreadCallback = new AsyncCallback(OnRead);
-        const int BufferSize = 8192;
-        Socket _socket;
-        Stream _stream;
-        HttpEndPointListener _epl;
-        MemoryStream _memoryStream;
-        byte[] _buffer;
-        HttpListenerContext _context;
-        StringBuilder _currentLine;
-        ListenerPrefix _prefix;
-        HttpRequestStream _requestStream;
-        HttpResponseStream _responseStream;
-        bool _chunked;
-        int _reuses;
-        bool _contextBound;
-        bool secure;
-        IPEndPoint local_ep;
-        HttpListener _lastListener;
-        X509Certificate cert;
-        SslStream ssl_stream;
-
-        private readonly ILogger _logger;
-        private readonly ICryptoProvider _cryptoProvider;
-        private readonly IStreamHelper _streamHelper;
-        private readonly IFileSystem _fileSystem;
-        private readonly IEnvironmentInfo _environment;
-
-        public HttpConnection(ILogger logger, Socket socket, HttpEndPointListener epl, bool secure,
-            X509Certificate cert, ICryptoProvider cryptoProvider, IStreamHelper streamHelper, IFileSystem fileSystem,
-            IEnvironmentInfo environment)
-        {
-            _logger = logger;
-            this._socket = socket;
-            this._epl = epl;
-            this.secure = secure;
-            this.cert = cert;
-            _cryptoProvider = cryptoProvider;
-            _streamHelper = streamHelper;
-            _fileSystem = fileSystem;
-            _environment = environment;
-
-            if (secure == false)
-            {
-                _stream = new SocketStream(_socket, false);
-            }
-            else
-            {
-                ssl_stream = new SslStream(new SocketStream(_socket, false), false, (t, c, ch, e) =>
-                {
-                    if (c == null)
-                    {
-                        return true;
-                    }
-
-                    //var c2 = c as X509Certificate2;
-                    //if (c2 == null)
-                    //{
-                    //    c2 = new X509Certificate2(c.GetRawCertData());
-                    //}
-
-                    //_clientCert = c2;
-                    //_clientCertErrors = new int[] { (int)e };
-                    return true;
-                });
-
-                _stream = ssl_stream;
-            }
-        }
-
-        public Stream Stream => _stream;
-
-        public async Task Init()
-        {
-            if (ssl_stream != null)
-            {
-                var enableAsync = true;
-                if (enableAsync)
-                {
-                    await ssl_stream.AuthenticateAsServerAsync(cert, false, (SslProtocols)ServicePointManager.SecurityProtocol, false).ConfigureAwait(false);
-                }
-                else
-                {
-                    ssl_stream.AuthenticateAsServer(cert, false, (SslProtocols)ServicePointManager.SecurityProtocol, false);
-                }
-            }
-
-            InitInternal();
-        }
-
-        private void InitInternal()
-        {
-            _contextBound = false;
-            _requestStream = null;
-            _responseStream = null;
-            _prefix = null;
-            _chunked = false;
-            _memoryStream = new MemoryStream();
-            _position = 0;
-            _inputState = InputState.RequestLine;
-            _lineState = LineState.None;
-            _context = new HttpListenerContext(this);
-        }
-
-        public bool IsClosed => (_socket == null);
-
-        public int Reuses => _reuses;
-
-        public IPEndPoint LocalEndPoint
-        {
-            get
-            {
-                if (local_ep != null)
-                    return local_ep;
-
-                local_ep = (IPEndPoint)_socket.LocalEndPoint;
-                return local_ep;
-            }
-        }
-
-        public IPEndPoint RemoteEndPoint => _socket.RemoteEndPoint as IPEndPoint;
-
-        public bool IsSecure => secure;
-
-        public ListenerPrefix Prefix
-        {
-            get => _prefix;
-            set => _prefix = value;
-        }
-
-        private void OnTimeout(object unused)
-        {
-            //_logger.LogInformation("HttpConnection timer fired");
-            CloseSocket();
-            Unbind();
-        }
-
-        public void BeginReadRequest()
-        {
-            if (_buffer == null)
-                _buffer = new byte[BufferSize];
-            try
-            {
-                _stream.BeginRead(_buffer, 0, BufferSize, s_onreadCallback, this);
-            }
-            catch
-            {
-                CloseSocket();
-                Unbind();
-            }
-        }
-
-        public HttpRequestStream GetRequestStream(bool chunked, long contentlength)
-        {
-            if (_requestStream == null)
-            {
-                byte[] buffer = _memoryStream.GetBuffer();
-                int length = (int)_memoryStream.Length;
-                _memoryStream = null;
-                if (chunked)
-                {
-                    _chunked = true;
-                    //_context.Response.SendChunked = true;
-                    _requestStream = new ChunkedInputStream(_context, _stream, buffer, _position, length - _position);
-                }
-                else
-                {
-                    _requestStream = new HttpRequestStream(_stream, buffer, _position, length - _position, contentlength);
-                }
-            }
-            return _requestStream;
-        }
-
-        public HttpResponseStream GetResponseStream(bool isExpect100Continue = false)
-        {
-            // TODO: can we get this _stream before reading the input?
-            if (_responseStream == null)
-            {
-                var supportsDirectSocketAccess = !_context.Response.SendChunked && !isExpect100Continue && !secure;
-
-                _responseStream = new HttpResponseStream(_stream, _context.Response, false, _streamHelper, _socket, supportsDirectSocketAccess, _environment, _fileSystem, _logger);
-            }
-            return _responseStream;
-        }
-
-        private static void OnRead(IAsyncResult ares)
-        {
-            var cnc = (HttpConnection)ares.AsyncState;
-            cnc.OnReadInternal(ares);
-        }
-
-        private void OnReadInternal(IAsyncResult ares)
-        {
-            int nread = -1;
-            try
-            {
-                nread = _stream.EndRead(ares);
-                _memoryStream.Write(_buffer, 0, nread);
-                if (_memoryStream.Length > 32768)
-                {
-                    SendError("Bad Request", 400);
-                    Close(true);
-                    return;
-                }
-            }
-            catch
-            {
-                if (_memoryStream != null && _memoryStream.Length > 0)
-                    SendError();
-                if (_socket != null)
-                {
-                    CloseSocket();
-                    Unbind();
-                }
-                return;
-            }
-
-            if (nread == 0)
-            {
-                CloseSocket();
-                Unbind();
-                return;
-            }
-
-            if (ProcessInput(_memoryStream))
-            {
-                if (!_context.HaveError)
-                    _context.Request.FinishInitialization();
-
-                if (_context.HaveError)
-                {
-                    SendError();
-                    Close(true);
-                    return;
-                }
-
-                if (!_epl.BindContext(_context))
-                {
-                    const int NotFoundErrorCode = 404;
-                    SendError(HttpStatusDescription.Get(NotFoundErrorCode), NotFoundErrorCode);
-                    Close(true);
-                    return;
-                }
-                HttpListener listener = _epl.Listener;
-                if (_lastListener != listener)
-                {
-                    RemoveConnection();
-                    listener.AddConnection(this);
-                    _lastListener = listener;
-                }
-
-                _contextBound = true;
-                listener.RegisterContext(_context);
-                return;
-            }
-            _stream.BeginRead(_buffer, 0, BufferSize, s_onreadCallback, this);
-        }
-
-        private void RemoveConnection()
-        {
-            if (_lastListener == null)
-                _epl.RemoveConnection(this);
-            else
-                _lastListener.RemoveConnection(this);
-        }
-
-        private enum InputState
-        {
-            RequestLine,
-            Headers
-        }
-
-        private enum LineState
-        {
-            None,
-            CR,
-            LF
-        }
-
-        InputState _inputState = InputState.RequestLine;
-        LineState _lineState = LineState.None;
-        int _position;
-
-        // true -> done processing
-        // false -> need more input
-        private bool ProcessInput(MemoryStream ms)
-        {
-            byte[] buffer = ms.GetBuffer();
-            int len = (int)ms.Length;
-            int used = 0;
-            string line;
-
-            while (true)
-            {
-                if (_context.HaveError)
-                    return true;
-
-                if (_position >= len)
-                    break;
-
-                try
-                {
-                    line = ReadLine(buffer, _position, len - _position, ref used);
-                    _position += used;
-                }
-                catch
-                {
-                    _context.ErrorMessage = "Bad request";
-                    _context.ErrorStatus = 400;
-                    return true;
-                }
-
-                if (line == null)
-                    break;
-
-                if (line == "")
-                {
-                    if (_inputState == InputState.RequestLine)
-                        continue;
-                    _currentLine = null;
-                    ms = null;
-                    return true;
-                }
-
-                if (_inputState == InputState.RequestLine)
-                {
-                    _context.Request.SetRequestLine(line);
-                    _inputState = InputState.Headers;
-                }
-                else
-                {
-                    try
-                    {
-                        _context.Request.AddHeader(line);
-                    }
-                    catch (Exception e)
-                    {
-                        _context.ErrorMessage = e.Message;
-                        _context.ErrorStatus = 400;
-                        return true;
-                    }
-                }
-            }
-
-            if (used == len)
-            {
-                ms.SetLength(0);
-                _position = 0;
-            }
-            return false;
-        }
-
-        private string ReadLine(byte[] buffer, int offset, int len, ref int used)
-        {
-            if (_currentLine == null)
-                _currentLine = new StringBuilder(128);
-            int last = offset + len;
-            used = 0;
-            for (int i = offset; i < last && _lineState != LineState.LF; i++)
-            {
-                used++;
-                byte b = buffer[i];
-                if (b == 13)
-                {
-                    _lineState = LineState.CR;
-                }
-                else if (b == 10)
-                {
-                    _lineState = LineState.LF;
-                }
-                else
-                {
-                    _currentLine.Append((char)b);
-                }
-            }
-
-            string result = null;
-            if (_lineState == LineState.LF)
-            {
-                _lineState = LineState.None;
-                result = _currentLine.ToString();
-                _currentLine.Length = 0;
-            }
-
-            return result;
-        }
-
-        public void SendError(string msg, int status)
-        {
-            try
-            {
-                HttpListenerResponse response = _context.Response;
-                response.StatusCode = status;
-                response.ContentType = "text/html";
-                string description = HttpStatusDescription.Get(status);
-                string str;
-                if (msg != null)
-                    str = string.Format("<h1>{0} ({1})</h1>", description, msg);
-                else
-                    str = string.Format("<h1>{0}</h1>", description);
-
-                byte[] error = Encoding.UTF8.GetBytes(str);
-                response.Close(error, false);
-            }
-            catch
-            {
-                // response was already closed
-            }
-        }
-
-        public void SendError()
-        {
-            SendError(_context.ErrorMessage, _context.ErrorStatus);
-        }
-
-        private void Unbind()
-        {
-            if (_contextBound)
-            {
-                _epl.UnbindContext(_context);
-                _contextBound = false;
-            }
-        }
-
-        public void Close()
-        {
-            Close(false);
-        }
-
-        private void CloseSocket()
-        {
-            if (_socket == null)
-                return;
-
-            try
-            {
-                _socket.Close();
-            }
-            catch { }
-            finally
-            {
-                _socket = null;
-            }
-
-            RemoveConnection();
-        }
-
-        internal void Close(bool force)
-        {
-            if (_socket != null)
-            {
-                Stream st = GetResponseStream();
-                if (st != null)
-                    st.Close();
-
-                _responseStream = null;
-            }
-
-            if (_socket != null)
-            {
-                force |= !_context.Request.KeepAlive;
-                if (!force)
-                    force = (string.Equals(_context.Response.Headers["connection"], "close", StringComparison.OrdinalIgnoreCase));
-
-                if (!force && _context.Request.FlushInput())
-                {
-                    if (_chunked && _context.Response.ForceCloseChunked == false)
-                    {
-                        // Don't close. Keep working.
-                        _reuses++;
-                        Unbind();
-                        InitInternal();
-                        BeginReadRequest();
-                        return;
-                    }
-
-                    _reuses++;
-                    Unbind();
-                    InitInternal();
-                    BeginReadRequest();
-                    return;
-                }
-
-                Socket s = _socket;
-                _socket = null;
-                try
-                {
-                    if (s != null)
-                        s.Shutdown(SocketShutdown.Both);
-                }
-                catch
-                {
-                }
-                finally
-                {
-                    if (s != null)
-                    {
-                        try
-                        {
-                            s.Close();
-                        }
-                        catch { }
-                    }
-                }
-                Unbind();
-                RemoveConnection();
-                return;
-            }
-        }
-    }
-}

+ 0 - 526
SocketHttpListener/Net/HttpEndPointListener.cs

@@ -1,526 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Net.Sockets;
-using System.Security.Cryptography.X509Certificates;
-using System.Threading;
-using MediaBrowser.Model.Cryptography;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Net;
-using MediaBrowser.Model.System;
-using Microsoft.Extensions.Logging;
-
-namespace SocketHttpListener.Net
-{
-    internal sealed class HttpEndPointListener
-    {
-        private HttpListener _listener;
-        private IPEndPoint _endpoint;
-        private Socket _socket;
-        private Dictionary<ListenerPrefix, HttpListener> _prefixes;
-        private List<ListenerPrefix> _unhandledPrefixes; // host = '*'
-        private List<ListenerPrefix> _allPrefixes;       // host = '+'
-        private X509Certificate _cert;
-        private bool _secure;
-        private Dictionary<HttpConnection, HttpConnection> _unregisteredConnections;
-
-        private readonly ILogger _logger;
-        private bool _closed;
-        private bool _enableDualMode;
-        private readonly ICryptoProvider _cryptoProvider;
-        private readonly ISocketFactory _socketFactory;
-        private readonly IStreamHelper _streamHelper;
-        private readonly IFileSystem _fileSystem;
-        private readonly IEnvironmentInfo _environment;
-
-        public HttpEndPointListener(HttpListener listener, IPAddress addr, int port, bool secure, X509Certificate cert,
-            ILogger logger, ICryptoProvider cryptoProvider, ISocketFactory socketFactory, IStreamHelper streamHelper,
-            IFileSystem fileSystem, IEnvironmentInfo environment)
-        {
-            this._listener = listener;
-            _logger = logger;
-            _cryptoProvider = cryptoProvider;
-            _socketFactory = socketFactory;
-            _streamHelper = streamHelper;
-            _fileSystem = fileSystem;
-            _environment = environment;
-
-            this._secure = secure;
-            this._cert = cert;
-
-            _enableDualMode = addr.Equals(IPAddress.IPv6Any);
-            _endpoint = new IPEndPoint(addr, port);
-
-            _prefixes = new Dictionary<ListenerPrefix, HttpListener>();
-            _unregisteredConnections = new Dictionary<HttpConnection, HttpConnection>();
-
-            CreateSocket();
-        }
-
-        internal HttpListener Listener => _listener;
-
-        private void CreateSocket()
-        {
-            try
-            {
-                _socket = CreateSocket(_endpoint.Address.AddressFamily, _enableDualMode);
-            }
-            catch (SocketCreateException ex)
-            {
-                if (_enableDualMode && _endpoint.Address.Equals(IPAddress.IPv6Any) &&
-                    (string.Equals(ex.ErrorCode, "AddressFamilyNotSupported", StringComparison.OrdinalIgnoreCase) ||
-                    // mono 4.8.1 and lower on bsd is throwing this
-                    string.Equals(ex.ErrorCode, "ProtocolNotSupported", StringComparison.OrdinalIgnoreCase) ||
-                    // mono 5.2 on bsd is throwing this
-                    string.Equals(ex.ErrorCode, "OperationNotSupported", StringComparison.OrdinalIgnoreCase)))
-                {
-                    _endpoint = new IPEndPoint(IPAddress.Any, _endpoint.Port);
-                    _enableDualMode = false;
-                    _socket = CreateSocket(_endpoint.Address.AddressFamily, _enableDualMode);
-                }
-                else
-                {
-                    throw;
-                }
-            }
-
-            try
-            {
-                _socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
-            }
-            catch (SocketException)
-            {
-                // This is not supported on all operating systems (qnap)
-            }
-
-            _socket.Bind(_endpoint);
-
-            // This is the number TcpListener uses.
-            _socket.Listen(2147483647);
-
-            Accept();
-
-            _closed = false;
-        }
-
-        private void Accept()
-        {
-            var acceptEventArg = new SocketAsyncEventArgs();
-            acceptEventArg.UserToken = this;
-            acceptEventArg.Completed += new EventHandler<SocketAsyncEventArgs>(OnAccept);
-
-            Accept(acceptEventArg);
-        }
-
-        private static void TryCloseAndDispose(Socket socket)
-        {
-            try
-            {
-                using (socket)
-                {
-                    socket.Close();
-                }
-            }
-            catch
-            {
-
-            }
-        }
-
-        private static void TryClose(Socket socket)
-        {
-            try
-            {
-                socket.Close();
-            }
-            catch
-            {
-
-            }
-        }
-
-        private void Accept(SocketAsyncEventArgs acceptEventArg)
-        {
-            // acceptSocket must be cleared since the context object is being reused
-            acceptEventArg.AcceptSocket = null;
-
-            try
-            {
-                bool willRaiseEvent = _socket.AcceptAsync(acceptEventArg);
-
-                if (!willRaiseEvent)
-                {
-                    ProcessAccept(acceptEventArg);
-                }
-            }
-            catch (ObjectDisposedException)
-            {
-                // TODO Investigate or properly fix.
-            }
-            catch (Exception ex)
-            {
-                var epl = (HttpEndPointListener)acceptEventArg.UserToken;
-
-                epl._logger.LogError(ex, "Error in socket.AcceptAsync");
-            }
-        }
-
-        // This method is the callback method associated with Socket.AcceptAsync
-        // operations and is invoked when an accept operation is complete
-        //
-        private static void OnAccept(object sender, SocketAsyncEventArgs e)
-        {
-            ProcessAccept(e);
-        }
-
-        private static async void ProcessAccept(SocketAsyncEventArgs args)
-        {
-            var epl = (HttpEndPointListener)args.UserToken;
-
-            if (epl._closed)
-            {
-                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
-            var socketError = args.SocketError;
-            var accepted = args.AcceptSocket;
-
-            epl.Accept(args);
-
-            if (socketError == SocketError.ConnectionReset)
-            {
-                epl._logger.LogError("SocketError.ConnectionReset reported. Attempting to re-accept.");
-                return;
-            }
-
-            if (accepted == null)
-            {
-                return;
-            }
-
-            if (epl._secure && epl._cert == null)
-            {
-                TryClose(accepted);
-                return;
-            }
-
-            try
-            {
-                var remoteEndPointString = accepted.RemoteEndPoint == null ? string.Empty : accepted.RemoteEndPoint.ToString();
-                var localEndPointString = accepted.LocalEndPoint == null ? string.Empty : accepted.LocalEndPoint.ToString();
-                //_logger.LogInformation("HttpEndPointListener Accepting connection from {0} to {1} secure connection requested: {2}", remoteEndPointString, localEndPointString, _secure);
-
-                var conn = new HttpConnection(epl._logger, accepted, epl, epl._secure, epl._cert, epl._cryptoProvider, epl._streamHelper, epl._fileSystem, epl._environment);
-
-                await conn.Init().ConfigureAwait(false);
-
-                //_logger.LogDebug("Adding unregistered connection to {0}. Id: {1}", accepted.RemoteEndPoint, connectionId);
-                lock (epl._unregisteredConnections)
-                {
-                    epl._unregisteredConnections[conn] = conn;
-                }
-                conn.BeginReadRequest();
-            }
-            catch (Exception ex)
-            {
-                epl._logger.LogError(ex, "Error in ProcessAccept");
-
-                TryClose(accepted);
-                epl.Accept();
-                return;
-            }
-        }
-
-        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;
-                }
-            }
-        }
-
-        internal void RemoveConnection(HttpConnection conn)
-        {
-            lock (_unregisteredConnections)
-            {
-                _unregisteredConnections.Remove(conn);
-            }
-        }
-
-        public bool BindContext(HttpListenerContext context)
-        {
-            var req = context.Request;
-            HttpListener listener = SearchListener(req.Url, out var prefix);
-            if (listener == null)
-                return false;
-
-            context.Connection.Prefix = prefix;
-            return true;
-        }
-
-        public void UnbindContext(HttpListenerContext context)
-        {
-            if (context == null || context.Request == null)
-                return;
-
-            _listener.UnregisterContext(context);
-        }
-
-        private HttpListener SearchListener(Uri uri, out ListenerPrefix prefix)
-        {
-            prefix = null;
-            if (uri == null)
-                return null;
-
-            string host = uri.Host;
-            int port = uri.Port;
-            string path = WebUtility.UrlDecode(uri.AbsolutePath);
-            string pathSlash = path[path.Length - 1] == '/' ? path : path + "/";
-
-            HttpListener bestMatch = null;
-            int bestLength = -1;
-
-            if (host != null && host != "")
-            {
-                Dictionary<ListenerPrefix, HttpListener> localPrefixes = _prefixes;
-                foreach (var p in localPrefixes.Keys)
-                {
-                    string ppath = p.Path;
-                    if (ppath.Length < bestLength)
-                        continue;
-
-                    if (p.Host != host || p.Port != port)
-                        continue;
-
-                    if (path.StartsWith(ppath) || pathSlash.StartsWith(ppath))
-                    {
-                        bestLength = ppath.Length;
-                        bestMatch = localPrefixes[p];
-                        prefix = p;
-                    }
-                }
-                if (bestLength != -1)
-                    return bestMatch;
-            }
-
-            List<ListenerPrefix> list = _unhandledPrefixes;
-            bestMatch = MatchFromList(host, path, list, out prefix);
-
-            if (path != pathSlash && bestMatch == null)
-                bestMatch = MatchFromList(host, pathSlash, list, out prefix);
-
-            if (bestMatch != null)
-                return bestMatch;
-
-            list = _allPrefixes;
-            bestMatch = MatchFromList(host, path, list, out prefix);
-
-            if (path != pathSlash && bestMatch == null)
-                bestMatch = MatchFromList(host, pathSlash, list, out prefix);
-
-            if (bestMatch != null)
-                return bestMatch;
-
-            return null;
-        }
-
-        private HttpListener MatchFromList(string host, string path, List<ListenerPrefix> list, out ListenerPrefix prefix)
-        {
-            prefix = null;
-            if (list == null)
-                return null;
-
-            HttpListener bestMatch = null;
-            int bestLength = -1;
-
-            foreach (ListenerPrefix p in list)
-            {
-                string ppath = p.Path;
-                if (ppath.Length < bestLength)
-                    continue;
-
-                if (path.StartsWith(ppath))
-                {
-                    bestLength = ppath.Length;
-                    bestMatch = p._listener;
-                    prefix = p;
-                }
-            }
-
-            return bestMatch;
-        }
-
-        private void AddSpecial(List<ListenerPrefix> list, ListenerPrefix prefix)
-        {
-            if (list == null)
-                return;
-
-            foreach (ListenerPrefix p in list)
-            {
-                if (p.Path == prefix.Path)
-                    throw new Exception("net_listener_already");
-            }
-            list.Add(prefix);
-        }
-
-        private bool RemoveSpecial(List<ListenerPrefix> list, ListenerPrefix prefix)
-        {
-            if (list == null)
-                return false;
-
-            int c = list.Count;
-            for (int i = 0; i < c; i++)
-            {
-                ListenerPrefix p = list[i];
-                if (p.Path == prefix.Path)
-                {
-                    list.RemoveAt(i);
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        private void CheckIfRemove()
-        {
-            if (_prefixes.Count > 0)
-                return;
-
-            List<ListenerPrefix> list = _unhandledPrefixes;
-            if (list != null && list.Count > 0)
-                return;
-
-            list = _allPrefixes;
-            if (list != null && list.Count > 0)
-                return;
-
-            HttpEndPointManager.RemoveEndPoint(this, _endpoint);
-        }
-
-        public void Close()
-        {
-            _closed = true;
-            _socket.Close();
-            lock (_unregisteredConnections)
-            {
-                // Clone the list because RemoveConnection can be called from Close
-                var connections = new List<HttpConnection>(_unregisteredConnections.Keys);
-
-                foreach (HttpConnection c in connections)
-                    c.Close(true);
-                _unregisteredConnections.Clear();
-            }
-        }
-
-        public void AddPrefix(ListenerPrefix prefix, HttpListener listener)
-        {
-            List<ListenerPrefix> current;
-            List<ListenerPrefix> future;
-            if (prefix.Host == "*")
-            {
-                do
-                {
-                    current = _unhandledPrefixes;
-                    future = current != null ? new List<ListenerPrefix>(current) : new List<ListenerPrefix>();
-                    prefix._listener = listener;
-                    AddSpecial(future, prefix);
-                } while (Interlocked.CompareExchange(ref _unhandledPrefixes, future, current) != current);
-                return;
-            }
-
-            if (prefix.Host == "+")
-            {
-                do
-                {
-                    current = _allPrefixes;
-                    future = current != null ? new List<ListenerPrefix>(current) : new List<ListenerPrefix>();
-                    prefix._listener = listener;
-                    AddSpecial(future, prefix);
-                } while (Interlocked.CompareExchange(ref _allPrefixes, future, current) != current);
-                return;
-            }
-
-            Dictionary<ListenerPrefix, HttpListener> prefs, p2;
-            do
-            {
-                prefs = _prefixes;
-                if (prefs.ContainsKey(prefix))
-                {
-                    throw new Exception("net_listener_already");
-                }
-                p2 = new Dictionary<ListenerPrefix, HttpListener>(prefs);
-                p2[prefix] = listener;
-            } while (Interlocked.CompareExchange(ref _prefixes, p2, prefs) != prefs);
-        }
-
-        public void RemovePrefix(ListenerPrefix prefix, HttpListener listener)
-        {
-            List<ListenerPrefix> current;
-            List<ListenerPrefix> future;
-            if (prefix.Host == "*")
-            {
-                do
-                {
-                    current = _unhandledPrefixes;
-                    future = current != null ? new List<ListenerPrefix>(current) : new List<ListenerPrefix>();
-                    if (!RemoveSpecial(future, prefix))
-                        break; // Prefix not found
-                } while (Interlocked.CompareExchange(ref _unhandledPrefixes, future, current) != current);
-
-                CheckIfRemove();
-                return;
-            }
-
-            if (prefix.Host == "+")
-            {
-                do
-                {
-                    current = _allPrefixes;
-                    future = current != null ? new List<ListenerPrefix>(current) : new List<ListenerPrefix>();
-                    if (!RemoveSpecial(future, prefix))
-                        break; // Prefix not found
-                } while (Interlocked.CompareExchange(ref _allPrefixes, future, current) != current);
-                CheckIfRemove();
-                return;
-            }
-
-            Dictionary<ListenerPrefix, HttpListener> prefs, p2;
-            do
-            {
-                prefs = _prefixes;
-                if (!prefs.ContainsKey(prefix))
-                    break;
-
-                p2 = new Dictionary<ListenerPrefix, HttpListener>(prefs);
-                p2.Remove(prefix);
-            } while (Interlocked.CompareExchange(ref _prefixes, p2, prefs) != prefs);
-            CheckIfRemove();
-        }
-    }
-}

+ 0 - 192
SocketHttpListener/Net/HttpEndPointManager.cs

@@ -1,192 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Net;
-using System.Net.Sockets;
-using Microsoft.Extensions.Logging;
-
-namespace SocketHttpListener.Net
-{
-    internal sealed class HttpEndPointManager
-    {
-        private static Dictionary<IPAddress, Dictionary<int, HttpEndPointListener>> s_ipEndPoints = new Dictionary<IPAddress, Dictionary<int, HttpEndPointListener>>();
-
-        private HttpEndPointManager()
-        {
-        }
-
-        public static void AddListener(ILogger logger, HttpListener listener)
-        {
-            var added = new List<string>();
-            try
-            {
-                lock ((s_ipEndPoints as ICollection).SyncRoot)
-                {
-                    foreach (string prefix in listener.Prefixes)
-                    {
-                        AddPrefixInternal(logger, prefix, listener);
-                        added.Add(prefix);
-                    }
-                }
-            }
-            catch
-            {
-                foreach (string prefix in added)
-                {
-                    RemovePrefix(logger, prefix, listener);
-                }
-                throw;
-            }
-        }
-
-        public static void AddPrefix(ILogger logger, string prefix, HttpListener listener)
-        {
-            lock ((s_ipEndPoints as ICollection).SyncRoot)
-            {
-                AddPrefixInternal(logger, prefix, listener);
-            }
-        }
-
-        private static void AddPrefixInternal(ILogger logger, string p, HttpListener listener)
-        {
-            int start = p.IndexOf(':') + 3;
-            int colon = p.IndexOf(':', start);
-            if (colon != -1)
-            {
-                // root can't be -1 here, since we've already checked for ending '/' in ListenerPrefix.
-                int root = p.IndexOf('/', colon, p.Length - colon);
-                string portString = p.Substring(colon + 1, root - colon - 1);
-
-                if (!int.TryParse(portString, out var port) || port <= 0 || port >= 65536)
-                {
-                    throw new HttpListenerException((int)HttpStatusCode.BadRequest, "net_invalid_port");
-                }
-            }
-
-            var lp = new ListenerPrefix(p);
-            if (lp.Host != "*" && lp.Host != "+" && Uri.CheckHostName(lp.Host) == UriHostNameType.Unknown)
-                throw new HttpListenerException((int)HttpStatusCode.BadRequest, "net_listener_host");
-
-            if (lp.Path.IndexOf('%') != -1)
-                throw new HttpListenerException((int)HttpStatusCode.BadRequest, "net_invalid_path");
-
-            if (lp.Path.IndexOf("//", StringComparison.Ordinal) != -1)
-                throw new HttpListenerException((int)HttpStatusCode.BadRequest, "net_invalid_path");
-
-            // listens on all the interfaces if host name cannot be parsed by IPAddress.
-            HttpEndPointListener epl = GetEPListener(logger, lp.Host, lp.Port, listener, lp.Secure);
-            epl.AddPrefix(lp, listener);
-        }
-
-        private static IPAddress GetIpAnyAddress(HttpListener listener)
-        {
-            return listener.EnableDualMode ? IPAddress.IPv6Any : IPAddress.Any;
-        }
-
-        private static HttpEndPointListener GetEPListener(ILogger logger, string host, int port, HttpListener listener, bool secure)
-        {
-            IPAddress addr;
-            if (host == "*" || host == "+")
-            {
-                addr = GetIpAnyAddress(listener);
-            }
-            else
-            {
-                const int NotSupportedErrorCode = 50;
-                try
-                {
-                    addr = Dns.GetHostAddresses(host)[0];
-                }
-                catch
-                {
-                    // Throw same error code as windows, request is not supported.
-                    throw new HttpListenerException(NotSupportedErrorCode, "net_listener_not_supported");
-                }
-
-                if (IPAddress.Any.Equals(addr))
-                {
-                    // Don't support listening to 0.0.0.0, match windows behavior.
-                    throw new HttpListenerException(NotSupportedErrorCode, "net_listener_not_supported");
-                }
-            }
-
-            Dictionary<int, HttpEndPointListener> p = null;
-            if (s_ipEndPoints.ContainsKey(addr))
-            {
-                p = s_ipEndPoints[addr];
-            }
-            else
-            {
-                p = new Dictionary<int, HttpEndPointListener>();
-                s_ipEndPoints[addr] = p;
-            }
-
-            HttpEndPointListener epl = null;
-            if (p.ContainsKey(port))
-            {
-                epl = p[port];
-            }
-            else
-            {
-                try
-                {
-                    epl = new HttpEndPointListener(listener, addr, port, secure, listener.Certificate, logger, listener.CryptoProvider, listener.SocketFactory, listener.StreamHelper, listener.FileSystem, listener.EnvironmentInfo);
-                }
-                catch (SocketException ex)
-                {
-                    throw new HttpListenerException(ex.ErrorCode, ex.Message);
-                }
-                p[port] = epl;
-            }
-
-            return epl;
-        }
-
-        public static void RemoveEndPoint(HttpEndPointListener epl, IPEndPoint ep)
-        {
-            lock ((s_ipEndPoints as ICollection).SyncRoot)
-            {
-                Dictionary<int, HttpEndPointListener> p = null;
-                p = s_ipEndPoints[ep.Address];
-                p.Remove(ep.Port);
-                if (p.Count == 0)
-                {
-                    s_ipEndPoints.Remove(ep.Address);
-                }
-                epl.Close();
-            }
-        }
-
-        public static void RemoveListener(ILogger logger, HttpListener listener)
-        {
-            lock ((s_ipEndPoints as ICollection).SyncRoot)
-            {
-                foreach (string prefix in listener.Prefixes)
-                {
-                    RemovePrefixInternal(logger, prefix, listener);
-                }
-            }
-        }
-
-        public static void RemovePrefix(ILogger logger, string prefix, HttpListener listener)
-        {
-            lock ((s_ipEndPoints as ICollection).SyncRoot)
-            {
-                RemovePrefixInternal(logger, prefix, listener);
-            }
-        }
-
-        private static void RemovePrefixInternal(ILogger logger, string prefix, HttpListener listener)
-        {
-            var lp = new ListenerPrefix(prefix);
-            if (lp.Path.IndexOf('%') != -1)
-                return;
-
-            if (lp.Path.IndexOf("//", StringComparison.Ordinal) != -1)
-                return;
-
-            HttpEndPointListener epl = GetEPListener(logger, lp.Host, lp.Port, listener, lp.Secure);
-            epl.RemovePrefix(lp, listener);
-        }
-    }
-}

+ 0 - 91
SocketHttpListener/Net/HttpKnownHeaderNames.cs

@@ -1,91 +0,0 @@
-namespace SocketHttpListener.Net
-{
-    internal static partial class HttpKnownHeaderNames
-    {
-        // When adding a new constant, add it to HttpKnownHeaderNames.TryGetHeaderName.cs as well.
-
-        public const string Accept = "Accept";
-        public const string AcceptCharset = "Accept-Charset";
-        public const string AcceptEncoding = "Accept-Encoding";
-        public const string AcceptLanguage = "Accept-Language";
-        public const string AcceptPatch = "Accept-Patch";
-        public const string AcceptRanges = "Accept-Ranges";
-        public const string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
-        public const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
-        public const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
-        public const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
-        public const string AccessControlExposeHeaders = "Access-Control-Expose-Headers";
-        public const string AccessControlMaxAge = "Access-Control-Max-Age";
-        public const string Age = "Age";
-        public const string Allow = "Allow";
-        public const string AltSvc = "Alt-Svc";
-        public const string Authorization = "Authorization";
-        public const string CacheControl = "Cache-Control";
-        public const string Connection = "Connection";
-        public const string ContentDisposition = "Content-Disposition";
-        public const string ContentEncoding = "Content-Encoding";
-        public const string ContentLanguage = "Content-Language";
-        public const string ContentLength = "Content-Length";
-        public const string ContentLocation = "Content-Location";
-        public const string ContentMD5 = "Content-MD5";
-        public const string ContentRange = "Content-Range";
-        public const string ContentSecurityPolicy = "Content-Security-Policy";
-        public const string ContentType = "Content-Type";
-        public const string Cookie = "Cookie";
-        public const string Cookie2 = "Cookie2";
-        public const string Date = "Date";
-        public const string ETag = "ETag";
-        public const string Expect = "Expect";
-        public const string Expires = "Expires";
-        public const string From = "From";
-        public const string Host = "Host";
-        public const string IfMatch = "If-Match";
-        public const string IfModifiedSince = "If-Modified-Since";
-        public const string IfNoneMatch = "If-None-Match";
-        public const string IfRange = "If-Range";
-        public const string IfUnmodifiedSince = "If-Unmodified-Since";
-        public const string KeepAlive = "Keep-Alive";
-        public const string LastModified = "Last-Modified";
-        public const string Link = "Link";
-        public const string Location = "Location";
-        public const string MaxForwards = "Max-Forwards";
-        public const string Origin = "Origin";
-        public const string P3P = "P3P";
-        public const string Pragma = "Pragma";
-        public const string ProxyAuthenticate = "Proxy-Authenticate";
-        public const string ProxyAuthorization = "Proxy-Authorization";
-        public const string ProxyConnection = "Proxy-Connection";
-        public const string PublicKeyPins = "Public-Key-Pins";
-        public const string Range = "Range";
-        public const string Referer = "Referer"; // NB: The spelling-mistake "Referer" for "Referrer" must be matched.
-        public const string RetryAfter = "Retry-After";
-        public const string SecWebSocketAccept = "Sec-WebSocket-Accept";
-        public const string SecWebSocketExtensions = "Sec-WebSocket-Extensions";
-        public const string SecWebSocketKey = "Sec-WebSocket-Key";
-        public const string SecWebSocketProtocol = "Sec-WebSocket-Protocol";
-        public const string SecWebSocketVersion = "Sec-WebSocket-Version";
-        public const string Server = "Server";
-        public const string SetCookie = "Set-Cookie";
-        public const string SetCookie2 = "Set-Cookie2";
-        public const string StrictTransportSecurity = "Strict-Transport-Security";
-        public const string TE = "TE";
-        public const string TSV = "TSV";
-        public const string Trailer = "Trailer";
-        public const string TransferEncoding = "Transfer-Encoding";
-        public const string Upgrade = "Upgrade";
-        public const string UpgradeInsecureRequests = "Upgrade-Insecure-Requests";
-        public const string UserAgent = "User-Agent";
-        public const string Vary = "Vary";
-        public const string Via = "Via";
-        public const string WWWAuthenticate = "WWW-Authenticate";
-        public const string Warning = "Warning";
-        public const string XAspNetVersion = "X-AspNet-Version";
-        public const string XContentDuration = "X-Content-Duration";
-        public const string XContentTypeOptions = "X-Content-Type-Options";
-        public const string XFrameOptions = "X-Frame-Options";
-        public const string XMSEdgeRef = "X-MSEdge-Ref";
-        public const string XPoweredBy = "X-Powered-By";
-        public const string XRequestID = "X-Request-ID";
-        public const string XUACompatible = "X-UA-Compatible";
-    }
-}

+ 0 - 284
SocketHttpListener/Net/HttpListener.cs

@@ -1,284 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Net;
-using System.Security.Cryptography.X509Certificates;
-using MediaBrowser.Model.Cryptography;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.Net;
-using MediaBrowser.Model.System;
-using Microsoft.Extensions.Logging;
-
-namespace SocketHttpListener.Net
-{
-    public sealed class HttpListener : IDisposable
-    {
-        internal ICryptoProvider CryptoProvider { get; private set; }
-        internal ISocketFactory SocketFactory { get; private set; }
-        internal IFileSystem FileSystem { get; private set; }
-        internal IStreamHelper StreamHelper { get; private set; }
-        internal IEnvironmentInfo EnvironmentInfo { get; private set; }
-
-        public bool EnableDualMode { get; set; }
-
-        private AuthenticationSchemes auth_schemes;
-        private HttpListenerPrefixCollection prefixes;
-        private AuthenticationSchemeSelector auth_selector;
-        private string realm;
-        private bool unsafe_ntlm_auth;
-        private bool listening;
-        private bool disposed;
-
-        private Dictionary<HttpListenerContext, HttpListenerContext> registry;
-        private Dictionary<HttpConnection, HttpConnection> connections;
-        private ILogger _logger;
-        private X509Certificate _certificate;
-
-        public Action<HttpListenerContext> OnContext { get; set; }
-
-        public HttpListener(
-            ILogger logger,
-            ICryptoProvider cryptoProvider,
-            ISocketFactory socketFactory,
-            IStreamHelper streamHelper,
-            IFileSystem fileSystem,
-            IEnvironmentInfo environmentInfo)
-        {
-            _logger = logger;
-            CryptoProvider = cryptoProvider;
-            SocketFactory = socketFactory;
-            StreamHelper = streamHelper;
-            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(
-            ILogger logger,
-            X509Certificate certificate,
-            ICryptoProvider cryptoProvider,
-            ISocketFactory socketFactory,
-            IStreamHelper streamHelper,
-            IFileSystem fileSystem,
-            IEnvironmentInfo environmentInfo)
-            : this(logger, cryptoProvider, socketFactory, streamHelper, fileSystem, environmentInfo)
-        {
-            _certificate = certificate;
-        }
-
-        public void LoadCert(X509Certificate cert)
-        {
-            _certificate = cert;
-        }
-
-        // TODO: Digest, NTLM and Negotiate require ControlPrincipal
-        public AuthenticationSchemes AuthenticationSchemes
-        {
-            get => auth_schemes;
-            set
-            {
-                CheckDisposed();
-                auth_schemes = value;
-            }
-        }
-
-        public AuthenticationSchemeSelector AuthenticationSchemeSelectorDelegate
-        {
-            get => auth_selector;
-            set
-            {
-                CheckDisposed();
-                auth_selector = value;
-            }
-        }
-
-        public bool IsListening => listening;
-
-        public static bool IsSupported => true;
-
-        public HttpListenerPrefixCollection Prefixes
-        {
-            get
-            {
-                CheckDisposed();
-                return prefixes;
-            }
-        }
-
-        // TODO: use this
-        public string Realm
-        {
-            get => realm;
-            set
-            {
-                CheckDisposed();
-                realm = value;
-            }
-        }
-
-        public bool UnsafeConnectionNtlmAuthentication
-        {
-            get => unsafe_ntlm_auth;
-            set
-            {
-                CheckDisposed();
-                unsafe_ntlm_auth = value;
-            }
-        }
-
-        //internal IMonoSslStream CreateSslStream(Stream innerStream, bool ownsStream, MSI.MonoRemoteCertificateValidationCallback callback)
-        //{
-        //    lock (registry)
-        //    {
-        //        if (tlsProvider == null)
-        //            tlsProvider = MonoTlsProviderFactory.GetProviderInternal();
-        //        if (tlsSettings == null)
-        //            tlsSettings = MSI.MonoTlsSettings.CopyDefaultSettings();
-        //        if (tlsSettings.RemoteCertificateValidationCallback == null)
-        //            tlsSettings.RemoteCertificateValidationCallback = callback;
-        //        return tlsProvider.CreateSslStream(innerStream, ownsStream, tlsSettings);
-        //    }
-        //}
-
-        internal X509Certificate Certificate => _certificate;
-
-        public void Abort()
-        {
-            if (disposed)
-                return;
-
-            if (!listening)
-            {
-                return;
-            }
-
-            Close(true);
-        }
-
-        public void Close()
-        {
-            if (disposed)
-                return;
-
-            if (!listening)
-            {
-                disposed = true;
-                return;
-            }
-
-            Close(true);
-            disposed = true;
-        }
-
-        void Close(bool force)
-        {
-            CheckDisposed();
-            HttpEndPointManager.RemoveListener(_logger, this);
-            Cleanup(force);
-        }
-
-        void Cleanup(bool close_existing)
-        {
-            lock (registry)
-            {
-                if (close_existing)
-                {
-                    // Need to copy this since closing will call UnregisterContext
-                    ICollection keys = registry.Keys;
-                    var all = new HttpListenerContext[keys.Count];
-                    keys.CopyTo(all, 0);
-                    registry.Clear();
-                    for (int i = all.Length - 1; i >= 0; i--)
-                        all[i].Connection.Close(true);
-                }
-
-                lock (connections)
-                {
-                    ICollection keys = connections.Keys;
-                    var conns = new HttpConnection[keys.Count];
-                    keys.CopyTo(conns, 0);
-                    connections.Clear();
-                    for (int i = conns.Length - 1; i >= 0; i--)
-                        conns[i].Close(true);
-                }
-            }
-        }
-
-        internal AuthenticationSchemes SelectAuthenticationScheme(HttpListenerContext context)
-        {
-            if (AuthenticationSchemeSelectorDelegate != null)
-                return AuthenticationSchemeSelectorDelegate(context.Request);
-            else
-                return auth_schemes;
-        }
-
-        public void Start()
-        {
-            CheckDisposed();
-            if (listening)
-                return;
-
-            HttpEndPointManager.AddListener(_logger, this);
-            listening = true;
-        }
-
-        public void Stop()
-        {
-            CheckDisposed();
-            listening = false;
-            Close(false);
-        }
-
-        void IDisposable.Dispose()
-        {
-            if (disposed)
-                return;
-
-            Close(true); //TODO: Should we force here or not?
-            disposed = true;
-        }
-
-        internal void CheckDisposed()
-        {
-            if (disposed)
-                throw new ObjectDisposedException(GetType().Name);
-        }
-
-        internal void RegisterContext(HttpListenerContext context)
-        {
-            if (OnContext != null && IsListening)
-            {
-                OnContext(context);
-            }
-
-            lock (registry)
-                registry[context] = context;
-        }
-
-        internal void UnregisterContext(HttpListenerContext context)
-        {
-            lock (registry)
-                registry.Remove(context);
-        }
-
-        internal void AddConnection(HttpConnection cnc)
-        {
-            lock (connections)
-            {
-                connections[cnc] = cnc;
-            }
-        }
-
-        internal void RemoveConnection(HttpConnection cnc)
-        {
-            lock (connections)
-            {
-                connections.Remove(cnc);
-            }
-        }
-    }
-}

+ 0 - 49
SocketHttpListener/Net/HttpListenerBasicIdentity.cs

@@ -1,49 +0,0 @@
-using System.Security.Principal;
-
-namespace SocketHttpListener.Net
-{
-    public class HttpListenerBasicIdentity : GenericIdentity
-    {
-        string password;
-
-        public HttpListenerBasicIdentity(string username, string password)
-            : base(username, "Basic")
-        {
-            this.password = password;
-        }
-
-        public virtual string Password => password;
-    }
-
-    public class GenericIdentity : IIdentity
-    {
-        private string m_name;
-        private string m_type;
-
-        public GenericIdentity(string name)
-        {
-            if (name == null)
-                throw new System.ArgumentNullException(nameof(name));
-
-            m_name = name;
-            m_type = "";
-        }
-
-        public GenericIdentity(string name, string type)
-        {
-            if (name == null)
-                throw new System.ArgumentNullException(nameof(name));
-            if (type == null)
-                throw new System.ArgumentNullException(nameof(type));
-
-            m_name = name;
-            m_type = type;
-        }
-
-        public virtual string Name => m_name;
-
-        public virtual string AuthenticationType => m_type;
-
-        public virtual bool IsAuthenticated => !m_name.Equals("");
-    }
-}

+ 0 - 99
SocketHttpListener/Net/HttpListenerContext.Managed.cs

@@ -1,99 +0,0 @@
-using System;
-using System.ComponentModel;
-using System.Security.Principal;
-using System.Text;
-using System.Threading.Tasks;
-using SocketHttpListener.Net.WebSockets;
-
-namespace SocketHttpListener.Net
-{
-    public sealed partial class HttpListenerContext
-    {
-        private HttpConnection _connection;
-
-        internal HttpListenerContext(HttpConnection connection)
-        {
-            _connection = connection;
-            _response = new HttpListenerResponse(this);
-            Request = new HttpListenerRequest(this);
-            ErrorStatus = 400;
-        }
-
-        internal int ErrorStatus { get; set; }
-
-        internal string ErrorMessage { get; set; }
-
-        internal bool HaveError => ErrorMessage != null;
-
-        internal HttpConnection Connection => _connection;
-
-        internal void ParseAuthentication(System.Net.AuthenticationSchemes expectedSchemes)
-        {
-            if (expectedSchemes == System.Net.AuthenticationSchemes.Anonymous)
-                return;
-
-            string header = Request.Headers["Authorization"];
-            if (string.IsNullOrEmpty(header))
-                return;
-
-            if (IsBasicHeader(header))
-            {
-                _user = ParseBasicAuthentication(header.Substring(AuthenticationTypes.Basic.Length + 1));
-            }
-        }
-
-        internal IPrincipal ParseBasicAuthentication(string authData) =>
-            TryParseBasicAuth(authData, out HttpStatusCode errorCode, out string username, out string password) ?
-                new GenericPrincipal(new HttpListenerBasicIdentity(username, password), Array.Empty<string>()) :
-                null;
-
-        internal static bool IsBasicHeader(string header) =>
-            header.Length >= 6 &&
-            header[5] == ' ' &&
-            string.Compare(header, 0, AuthenticationTypes.Basic, 0, 5, StringComparison.OrdinalIgnoreCase) == 0;
-
-        internal static bool TryParseBasicAuth(string headerValue, out HttpStatusCode errorCode, out string username, out string password)
-        {
-            errorCode = HttpStatusCode.OK;
-            username = password = null;
-            try
-            {
-                if (string.IsNullOrWhiteSpace(headerValue))
-                {
-                    return false;
-                }
-
-                string authString = Encoding.UTF8.GetString(Convert.FromBase64String(headerValue));
-                int colonPos = authString.IndexOf(':');
-                if (colonPos < 0)
-                {
-                    // username must be at least 1 char
-                    errorCode = HttpStatusCode.BadRequest;
-                    return false;
-                }
-
-                username = authString.Substring(0, colonPos);
-                password = authString.Substring(colonPos + 1);
-                return true;
-            }
-            catch
-            {
-                errorCode = HttpStatusCode.InternalServerError;
-                return false;
-            }
-        }
-
-        public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval)
-        {
-            return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval);
-        }
-
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, int receiveBufferSize, TimeSpan keepAliveInterval, ArraySegment<byte> internalBuffer)
-        {
-            WebSocketValidate.ValidateArraySegment(internalBuffer, nameof(internalBuffer));
-            HttpWebSocket.ValidateOptions(subProtocol, receiveBufferSize, HttpWebSocket.MinSendBufferSize, keepAliveInterval);
-            return HttpWebSocket.AcceptWebSocketAsyncCore(this, subProtocol, receiveBufferSize, keepAliveInterval, internalBuffer);
-        }
-    }
-}

+ 0 - 74
SocketHttpListener/Net/HttpListenerContext.cs

@@ -1,74 +0,0 @@
-using System;
-using System.Net;
-using System.Security.Principal;
-using System.Threading.Tasks;
-using SocketHttpListener.Net.WebSockets;
-
-namespace SocketHttpListener.Net
-{
-    public sealed partial class HttpListenerContext
-    {
-        private HttpListenerResponse _response;
-        private IPrincipal _user;
-
-        public HttpListenerRequest Request { get; }
-
-        public IPrincipal User => _user;
-
-        // This can be used to cache the results of HttpListener.AuthenticationSchemeSelectorDelegate.
-        internal AuthenticationSchemes AuthenticationSchemes { get; set; }
-
-        public HttpListenerResponse Response => _response;
-
-        public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol)
-        {
-            return AcceptWebSocketAsync(subProtocol, HttpWebSocket.DefaultReceiveBufferSize, WebSocket.DefaultKeepAliveInterval);
-        }
-
-        public Task<HttpListenerWebSocketContext> AcceptWebSocketAsync(string subProtocol, TimeSpan keepAliveInterval)
-        {
-            return AcceptWebSocketAsync(subProtocol, HttpWebSocket.DefaultReceiveBufferSize, keepAliveInterval);
-        }
-    }
-
-    public class GenericPrincipal : IPrincipal
-    {
-        private IIdentity m_identity;
-        private string[] m_roles;
-
-        public GenericPrincipal(IIdentity identity, string[] roles)
-        {
-            if (identity == null)
-                throw new ArgumentNullException(nameof(identity));
-
-            m_identity = identity;
-            if (roles != null)
-            {
-                m_roles = new string[roles.Length];
-                for (int i = 0; i < roles.Length; ++i)
-                {
-                    m_roles[i] = roles[i];
-                }
-            }
-            else
-            {
-                m_roles = null;
-            }
-        }
-
-        public virtual IIdentity Identity => m_identity;
-
-        public virtual bool IsInRole(string role)
-        {
-            if (role == null || m_roles == null)
-                return false;
-
-            for (int i = 0; i < m_roles.Length; ++i)
-            {
-                if (m_roles[i] != null && string.Compare(m_roles[i], role, StringComparison.OrdinalIgnoreCase) == 0)
-                    return true;
-            }
-            return false;
-        }
-    }
-}

+ 0 - 117
SocketHttpListener/Net/HttpListenerPrefixCollection.cs

@@ -1,117 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using Microsoft.Extensions.Logging;
-
-namespace SocketHttpListener.Net
-{
-    public class HttpListenerPrefixCollection : ICollection<string>, IEnumerable<string>, IEnumerable
-    {
-        private List<string> _prefixes = new List<string>();
-        private HttpListener _listener;
-
-        private ILogger _logger;
-
-        internal HttpListenerPrefixCollection(ILogger logger, HttpListener listener)
-        {
-            _logger = logger;
-            _listener = listener;
-        }
-
-        public int Count => _prefixes.Count;
-
-        public bool IsReadOnly => false;
-
-        public bool IsSynchronized => false;
-
-        public void Add(string uriPrefix)
-        {
-            _listener.CheckDisposed();
-            //ListenerPrefix.CheckUri(uriPrefix);
-            if (_prefixes.Contains(uriPrefix))
-            {
-                return;
-            }
-
-            _prefixes.Add(uriPrefix);
-            if (_listener.IsListening)
-            {
-                HttpEndPointManager.AddPrefix(_logger, uriPrefix, _listener);
-            }
-        }
-
-        public void AddRange(IEnumerable<string> uriPrefixes)
-        {
-            _listener.CheckDisposed();
-
-            foreach (var uriPrefix in uriPrefixes)
-            {
-                if (_prefixes.Contains(uriPrefix))
-                {
-                    continue;
-                }
-
-                _prefixes.Add(uriPrefix);
-                if (_listener.IsListening)
-                {
-                    HttpEndPointManager.AddPrefix(_logger, uriPrefix, _listener);
-                }
-            }
-        }
-
-        public void Clear()
-        {
-            _listener.CheckDisposed();
-            _prefixes.Clear();
-            if (_listener.IsListening)
-            {
-                HttpEndPointManager.RemoveListener(_logger, _listener);
-            }
-        }
-
-        public bool Contains(string uriPrefix)
-        {
-            _listener.CheckDisposed();
-            return _prefixes.Contains(uriPrefix);
-        }
-
-        public void CopyTo(string[] array, int offset)
-        {
-            _listener.CheckDisposed();
-            _prefixes.CopyTo(array, offset);
-        }
-
-        public void CopyTo(Array array, int offset)
-        {
-            _listener.CheckDisposed();
-            ((ICollection)_prefixes).CopyTo(array, offset);
-        }
-
-        public IEnumerator<string> GetEnumerator()
-        {
-            return _prefixes.GetEnumerator();
-        }
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return _prefixes.GetEnumerator();
-        }
-
-        public bool Remove(string uriPrefix)
-        {
-            _listener.CheckDisposed();
-            if (uriPrefix == null)
-            {
-                throw new ArgumentNullException(nameof(uriPrefix));
-            }
-
-            bool result = _prefixes.Remove(uriPrefix);
-            if (result && _listener.IsListening)
-            {
-                HttpEndPointManager.RemovePrefix(_logger, uriPrefix, _listener);
-            }
-
-            return result;
-        }
-    }
-}

+ 0 - 325
SocketHttpListener/Net/HttpListenerRequest.Managed.cs

@@ -1,325 +0,0 @@
-using System;
-using System.IO;
-using System.Text;
-using MediaBrowser.Model.Services;
-
-namespace SocketHttpListener.Net
-{
-    public sealed partial class HttpListenerRequest
-    {
-        private long _contentLength;
-        private bool _clSet;
-        private WebHeaderCollection _headers;
-        private string _method;
-        private Stream _inputStream;
-        private HttpListenerContext _context;
-        private bool _isChunked;
-
-        private static byte[] s_100continue = Encoding.ASCII.GetBytes("HTTP/1.1 100 Continue\r\n\r\n");
-
-        internal HttpListenerRequest(HttpListenerContext context)
-        {
-            _context = context;
-            _headers = new WebHeaderCollection();
-            _version = HttpVersion.Version10;
-        }
-
-        private static readonly char[] s_separators = new char[] { ' ' };
-
-        internal void SetRequestLine(string req)
-        {
-            string[] parts = req.Split(s_separators, 3);
-            if (parts.Length != 3)
-            {
-                _context.ErrorMessage = "Invalid request line (parts).";
-                return;
-            }
-
-            _method = parts[0];
-            foreach (char c in _method)
-            {
-                int ic = (int)c;
-
-                if ((ic >= 'A' && ic <= 'Z') ||
-                    (ic > 32 && c < 127 && c != '(' && c != ')' && c != '<' &&
-                     c != '<' && c != '>' && c != '@' && c != ',' && c != ';' &&
-                     c != ':' && c != '\\' && c != '"' && c != '/' && c != '[' &&
-                     c != ']' && c != '?' && c != '=' && c != '{' && c != '}'))
-                    continue;
-
-                _context.ErrorMessage = "(Invalid verb)";
-                return;
-            }
-
-            _rawUrl = parts[1];
-            if (parts[2].Length != 8 || !parts[2].StartsWith("HTTP/"))
-            {
-                _context.ErrorMessage = "Invalid request line (version).";
-                return;
-            }
-
-            try
-            {
-                _version = new Version(parts[2].Substring(5));
-            }
-            catch
-            {
-                _context.ErrorMessage = "Invalid request line (version).";
-                return;
-            }
-
-            if (_version.Major < 1)
-            {
-                _context.ErrorMessage = "Invalid request line (version).";
-                return;
-            }
-            if (_version.Major > 1)
-            {
-                _context.ErrorStatus = (int)HttpStatusCode.HttpVersionNotSupported;
-                _context.ErrorMessage = HttpStatusDescription.Get(HttpStatusCode.HttpVersionNotSupported);
-                return;
-            }
-        }
-
-        private static bool MaybeUri(string s)
-        {
-            int p = s.IndexOf(':');
-            if (p == -1)
-                return false;
-
-            if (p >= 10)
-                return false;
-
-            return IsPredefinedScheme(s.Substring(0, p));
-        }
-
-        private static bool IsPredefinedScheme(string scheme)
-        {
-            if (scheme == null || scheme.Length < 3)
-                return false;
-
-            char c = scheme[0];
-            if (c == 'h')
-                return (scheme == UriScheme.Http || scheme == UriScheme.Https);
-            if (c == 'f')
-                return (scheme == UriScheme.File || scheme == UriScheme.Ftp);
-
-            if (c == 'n')
-            {
-                c = scheme[1];
-                if (c == 'e')
-                    return (scheme == UriScheme.News || scheme == UriScheme.NetPipe || scheme == UriScheme.NetTcp);
-                if (scheme == UriScheme.Nntp)
-                    return true;
-                return false;
-            }
-            if ((c == 'g' && scheme == UriScheme.Gopher) || (c == 'm' && scheme == UriScheme.Mailto))
-                return true;
-
-            return false;
-        }
-
-        internal void FinishInitialization()
-        {
-            string host = UserHostName;
-            if (_version > HttpVersion.Version10 && (host == null || host.Length == 0))
-            {
-                _context.ErrorMessage = "Invalid host name";
-                return;
-            }
-
-            string path;
-            Uri raw_uri = null;
-            if (MaybeUri(_rawUrl.ToLowerInvariant()) && Uri.TryCreate(_rawUrl, UriKind.Absolute, out raw_uri))
-                path = raw_uri.PathAndQuery;
-            else
-                path = _rawUrl;
-
-            if ((host == null || host.Length == 0))
-                host = UserHostAddress;
-
-            if (raw_uri != null)
-                host = raw_uri.Host;
-
-            int colon = host.IndexOf(']') == -1 ? host.IndexOf(':') : host.LastIndexOf(':');
-            if (colon >= 0)
-                host = host.Substring(0, colon);
-
-            string base_uri = string.Format("{0}://{1}:{2}", RequestScheme, host, LocalEndPoint.Port);
-
-            if (!Uri.TryCreate(base_uri + path, UriKind.Absolute, out _requestUri))
-            {
-                _context.ErrorMessage = System.Net.WebUtility.HtmlEncode("Invalid url: " + base_uri + path);
-                return;
-            }
-
-            _requestUri = HttpListenerRequestUriBuilder.GetRequestUri(_rawUrl, _requestUri.Scheme,
-                                _requestUri.Authority, _requestUri.LocalPath, _requestUri.Query);
-
-            if (_version >= HttpVersion.Version11)
-            {
-                string t_encoding = Headers[HttpKnownHeaderNames.TransferEncoding];
-                _isChunked = (t_encoding != null && string.Equals(t_encoding, "chunked", StringComparison.OrdinalIgnoreCase));
-                // 'identity' is not valid!
-                if (t_encoding != null && !_isChunked)
-                {
-                    _context.Connection.SendError(null, 501);
-                    return;
-                }
-            }
-
-            if (!_isChunked && !_clSet)
-            {
-                if (string.Equals(_method, "POST", StringComparison.OrdinalIgnoreCase) ||
-                    string.Equals(_method, "PUT", StringComparison.OrdinalIgnoreCase))
-                {
-                    _context.Connection.SendError(null, 411);
-                    return;
-                }
-            }
-
-            if (string.Compare(Headers[HttpKnownHeaderNames.Expect], "100-continue", StringComparison.OrdinalIgnoreCase) == 0)
-            {
-                HttpResponseStream output = _context.Connection.GetResponseStream();
-                output.InternalWrite(s_100continue, 0, s_100continue.Length);
-            }
-        }
-
-        internal static string Unquote(string str)
-        {
-            int start = str.IndexOf('\"');
-            int end = str.LastIndexOf('\"');
-            if (start >= 0 && end >= 0)
-                str = str.Substring(start + 1, end - 1);
-            return str.Trim();
-        }
-
-        internal void AddHeader(string header)
-        {
-            int colon = header.IndexOf(':');
-            if (colon == -1 || colon == 0)
-            {
-                _context.ErrorMessage = HttpStatusDescription.Get(400);
-                _context.ErrorStatus = 400;
-                return;
-            }
-
-            string name = header.Substring(0, colon).Trim();
-            string val = header.Substring(colon + 1).Trim();
-            if (name.Equals("content-length", StringComparison.OrdinalIgnoreCase))
-            {
-                // To match Windows behavior:
-                // Content lengths >= 0 and <= long.MaxValue are accepted as is.
-                // Content lengths > long.MaxValue and <= ulong.MaxValue are treated as 0.
-                // Content lengths < 0 cause the requests to fail.
-                // Other input is a failure, too.
-                long parsedContentLength =
-                    ulong.TryParse(val, out ulong parsedUlongContentLength) ? (parsedUlongContentLength <= long.MaxValue ? (long)parsedUlongContentLength : 0) :
-                    long.Parse(val);
-                if (parsedContentLength < 0 || (_clSet && parsedContentLength != _contentLength))
-                {
-                    _context.ErrorMessage = "Invalid Content-Length.";
-                }
-                else
-                {
-                    _contentLength = parsedContentLength;
-                    _clSet = true;
-                }
-            }
-            else if (name.Equals("transfer-encoding", StringComparison.OrdinalIgnoreCase))
-            {
-                if (Headers[HttpKnownHeaderNames.TransferEncoding] != null)
-                {
-                    _context.ErrorStatus = (int)HttpStatusCode.NotImplemented;
-                    _context.ErrorMessage = HttpStatusDescription.Get(HttpStatusCode.NotImplemented);
-                }
-            }
-
-            if (_context.ErrorMessage == null)
-            {
-                _headers.Set(name, val);
-            }
-        }
-
-        // returns true is the stream could be reused.
-        internal bool FlushInput()
-        {
-            if (!HasEntityBody)
-                return true;
-
-            int length = 2048;
-            if (_contentLength > 0)
-                length = (int)Math.Min(_contentLength, (long)length);
-
-            byte[] bytes = new byte[length];
-            while (true)
-            {
-                try
-                {
-                    IAsyncResult ares = InputStream.BeginRead(bytes, 0, length, null, null);
-                    if (!ares.IsCompleted && !ares.AsyncWaitHandle.WaitOne(1000))
-                        return false;
-                    if (InputStream.EndRead(ares) <= 0)
-                        return true;
-                }
-                catch (ObjectDisposedException)
-                {
-                    _inputStream = null;
-                    return true;
-                }
-                catch
-                {
-                    return false;
-                }
-            }
-        }
-
-        public long ContentLength64
-        {
-            get
-            {
-                if (_isChunked)
-                    _contentLength = -1;
-
-                return _contentLength;
-            }
-        }
-
-        public bool HasEntityBody => (_contentLength > 0 || _isChunked);
-
-        public QueryParamCollection Headers => _headers;
-
-        public string HttpMethod => _method;
-
-        public Stream InputStream
-        {
-            get
-            {
-                if (_inputStream == null)
-                {
-                    if (_isChunked || _contentLength > 0)
-                        _inputStream = _context.Connection.GetRequestStream(_isChunked, _contentLength);
-                    else
-                        _inputStream = Stream.Null;
-                }
-
-                return _inputStream;
-            }
-        }
-
-        public bool IsAuthenticated => false;
-
-        public bool IsSecureConnection => _context.Connection.IsSecure;
-
-        public System.Net.IPEndPoint LocalEndPoint => _context.Connection.LocalEndPoint;
-
-        public System.Net.IPEndPoint RemoteEndPoint => _context.Connection.RemoteEndPoint;
-
-        public Guid RequestTraceIdentifier { get; } = Guid.NewGuid();
-
-        public string ServiceName => null;
-
-        private Uri RequestUri => _requestUri;
-        private bool SupportsWebSockets => true;
-    }
-}

+ 0 - 537
SocketHttpListener/Net/HttpListenerRequest.cs

@@ -1,537 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Net;
-using System.Text;
-using MediaBrowser.Model.Services;
-using SocketHttpListener.Net.WebSockets;
-
-namespace SocketHttpListener.Net
-{
-    public sealed partial class HttpListenerRequest
-    {
-        private CookieCollection _cookies;
-        private bool? _keepAlive;
-        private string _rawUrl;
-        private Uri _requestUri;
-        private Version _version;
-
-        public string[] AcceptTypes => Helpers.ParseMultivalueHeader(Headers[HttpKnownHeaderNames.Accept]);
-
-        public string[] UserLanguages => Helpers.ParseMultivalueHeader(Headers[HttpKnownHeaderNames.AcceptLanguage]);
-
-        private static CookieCollection ParseCookies(Uri uri, string setCookieHeader)
-        {
-            var cookies = new CookieCollection();
-            return cookies;
-        }
-
-        public CookieCollection Cookies
-        {
-            get
-            {
-                if (_cookies == null)
-                {
-                    string cookieString = Headers[HttpKnownHeaderNames.Cookie];
-                    if (!string.IsNullOrEmpty(cookieString))
-                    {
-                        _cookies = ParseCookies(RequestUri, cookieString);
-                    }
-                    if (_cookies == null)
-                    {
-                        _cookies = new CookieCollection();
-                    }
-                }
-                return _cookies;
-            }
-        }
-
-        public Encoding ContentEncoding
-        {
-            get
-            {
-                if (UserAgent != null && CultureInfo.InvariantCulture.CompareInfo.IsPrefix(UserAgent, "UP"))
-                {
-                    string postDataCharset = Headers["x-up-devcap-post-charset"];
-                    if (postDataCharset != null && postDataCharset.Length > 0)
-                    {
-                        try
-                        {
-                            return Encoding.GetEncoding(postDataCharset);
-                        }
-                        catch (ArgumentException)
-                        {
-                        }
-                    }
-                }
-                if (HasEntityBody)
-                {
-                    if (ContentType != null)
-                    {
-                        string charSet = Helpers.GetCharSetValueFromHeader(ContentType);
-                        if (charSet != null)
-                        {
-                            try
-                            {
-                                return Encoding.GetEncoding(charSet);
-                            }
-                            catch (ArgumentException)
-                            {
-                            }
-                        }
-                    }
-                }
-                return Encoding.UTF8;
-            }
-        }
-
-        public string ContentType => Headers[HttpKnownHeaderNames.ContentType];
-
-        public bool IsLocal => LocalEndPoint.Address.Equals(RemoteEndPoint.Address);
-
-        public bool IsWebSocketRequest
-        {
-            get
-            {
-                if (!SupportsWebSockets)
-                {
-                    return false;
-                }
-
-                bool foundConnectionUpgradeHeader = false;
-                if (string.IsNullOrEmpty(Headers[HttpKnownHeaderNames.Connection]) || string.IsNullOrEmpty(Headers[HttpKnownHeaderNames.Upgrade]))
-                {
-                    return false;
-                }
-
-                foreach (string connection in Headers.GetValues(HttpKnownHeaderNames.Connection))
-                {
-                    if (string.Equals(connection, HttpKnownHeaderNames.Upgrade, StringComparison.OrdinalIgnoreCase))
-                    {
-                        foundConnectionUpgradeHeader = true;
-                        break;
-                    }
-                }
-
-                if (!foundConnectionUpgradeHeader)
-                {
-                    return false;
-                }
-
-                foreach (string upgrade in Headers.GetValues(HttpKnownHeaderNames.Upgrade))
-                {
-                    if (string.Equals(upgrade, HttpWebSocket.WebSocketUpgradeToken, StringComparison.OrdinalIgnoreCase))
-                    {
-                        return true;
-                    }
-                }
-
-                return false;
-            }
-        }
-
-        public bool KeepAlive
-        {
-            get
-            {
-                if (!_keepAlive.HasValue)
-                {
-                    string header = Headers[HttpKnownHeaderNames.ProxyConnection];
-                    if (string.IsNullOrEmpty(header))
-                    {
-                        header = Headers[HttpKnownHeaderNames.Connection];
-                    }
-                    if (string.IsNullOrEmpty(header))
-                    {
-                        if (ProtocolVersion >= HttpVersion.Version11)
-                        {
-                            _keepAlive = true;
-                        }
-                        else
-                        {
-                            header = Headers[HttpKnownHeaderNames.KeepAlive];
-                            _keepAlive = !string.IsNullOrEmpty(header);
-                        }
-                    }
-                    else
-                    {
-                        header = header.ToLowerInvariant();
-                        _keepAlive =
-                            header.IndexOf("close", StringComparison.OrdinalIgnoreCase) < 0 ||
-                            header.IndexOf("keep-alive", StringComparison.OrdinalIgnoreCase) >= 0;
-                    }
-                }
-
-                return _keepAlive.Value;
-            }
-        }
-
-        public QueryParamCollection QueryString
-        {
-            get
-            {
-                var queryString = new QueryParamCollection();
-                Helpers.FillFromString(queryString, Url.Query, true, ContentEncoding);
-                return queryString;
-            }
-        }
-
-        public string RawUrl => _rawUrl;
-
-        private string RequestScheme => IsSecureConnection ? UriScheme.Https : UriScheme.Http;
-
-        public string UserAgent => Headers[HttpKnownHeaderNames.UserAgent];
-
-        public string UserHostAddress => LocalEndPoint.ToString();
-
-        public string UserHostName => Headers[HttpKnownHeaderNames.Host];
-
-        public Uri UrlReferrer
-        {
-            get
-            {
-                string referrer = Headers[HttpKnownHeaderNames.Referer];
-                if (referrer == null)
-                {
-                    return null;
-                }
-
-                bool success = Uri.TryCreate(referrer, UriKind.RelativeOrAbsolute, out var urlReferrer);
-                return success ? urlReferrer : null;
-            }
-        }
-
-        public Uri Url => RequestUri;
-
-        public Version ProtocolVersion => _version;
-
-        private static class Helpers
-        {
-            //
-            // Get attribute off header value
-            //
-            internal static string GetCharSetValueFromHeader(string headerValue)
-            {
-                const string AttrName = "charset";
-
-                if (headerValue == null)
-                    return null;
-
-                int l = headerValue.Length;
-                int k = AttrName.Length;
-
-                // find properly separated attribute name
-                int i = 1; // start searching from 1
-
-                while (i < l)
-                {
-                    i = CultureInfo.InvariantCulture.CompareInfo.IndexOf(headerValue, AttrName, i, CompareOptions.IgnoreCase);
-                    if (i < 0)
-                        break;
-                    if (i + k >= l)
-                        break;
-
-                    char chPrev = headerValue[i - 1];
-                    char chNext = headerValue[i + k];
-                    if ((chPrev == ';' || chPrev == ',' || char.IsWhiteSpace(chPrev)) && (chNext == '=' || char.IsWhiteSpace(chNext)))
-                        break;
-
-                    i += k;
-                }
-
-                if (i < 0 || i >= l)
-                    return null;
-
-                // skip to '=' and the following whitespace
-                i += k;
-                while (i < l && char.IsWhiteSpace(headerValue[i]))
-                    i++;
-                if (i >= l || headerValue[i] != '=')
-                    return null;
-                i++;
-                while (i < l && char.IsWhiteSpace(headerValue[i]))
-                    i++;
-                if (i >= l)
-                    return null;
-
-                // parse the value
-                string attrValue = null;
-
-                int j;
-
-                if (i < l && headerValue[i] == '"')
-                {
-                    if (i == l - 1)
-                        return null;
-                    j = headerValue.IndexOf('"', i + 1);
-                    if (j < 0 || j == i + 1)
-                        return null;
-
-                    attrValue = headerValue.Substring(i + 1, j - i - 1).Trim();
-                }
-                else
-                {
-                    for (j = i; j < l; j++)
-                    {
-                        if (headerValue[j] == ';')
-                            break;
-                    }
-
-                    if (j == i)
-                        return null;
-
-                    attrValue = headerValue.Substring(i, j - i).Trim();
-                }
-
-                return attrValue;
-            }
-
-            internal static string[] ParseMultivalueHeader(string s)
-            {
-                if (s == null)
-                    return null;
-
-                int l = s.Length;
-
-                // collect comma-separated values into list
-
-                var values = new List<string>();
-                int i = 0;
-
-                while (i < l)
-                {
-                    // find next ,
-                    int ci = s.IndexOf(',', i);
-                    if (ci < 0)
-                        ci = l;
-
-                    // append corresponding server value
-                    values.Add(s.Substring(i, ci - i));
-
-                    // move to next
-                    i = ci + 1;
-
-                    // skip leading space
-                    if (i < l && s[i] == ' ')
-                        i++;
-                }
-
-                // return list as array of strings
-
-                int n = values.Count;
-                string[] strings;
-
-                // if n is 0 that means s was empty string
-
-                if (n == 0)
-                {
-                    strings = new string[1];
-                    strings[0] = string.Empty;
-                }
-                else
-                {
-                    strings = new string[n];
-                    values.CopyTo(0, strings, 0, n);
-                }
-                return strings;
-            }
-
-
-            private static string UrlDecodeStringFromStringInternal(string s, Encoding e)
-            {
-                int count = s.Length;
-                var helper = new UrlDecoder(count, e);
-
-                // go through the string's chars collapsing %XX and %uXXXX and
-                // appending each char as char, with exception of %XX constructs
-                // that are appended as bytes
-
-                for (int pos = 0; pos < count; pos++)
-                {
-                    char ch = s[pos];
-
-                    if (ch == '+')
-                    {
-                        ch = ' ';
-                    }
-                    else if (ch == '%' && pos < count - 2)
-                    {
-                        if (s[pos + 1] == 'u' && pos < count - 5)
-                        {
-                            int h1 = HexToInt(s[pos + 2]);
-                            int h2 = HexToInt(s[pos + 3]);
-                            int h3 = HexToInt(s[pos + 4]);
-                            int h4 = HexToInt(s[pos + 5]);
-
-                            if (h1 >= 0 && h2 >= 0 && h3 >= 0 && h4 >= 0)
-                            {   // valid 4 hex chars
-                                ch = (char)((h1 << 12) | (h2 << 8) | (h3 << 4) | h4);
-                                pos += 5;
-
-                                // only add as char
-                                helper.AddChar(ch);
-                                continue;
-                            }
-                        }
-                        else
-                        {
-                            int h1 = HexToInt(s[pos + 1]);
-                            int h2 = HexToInt(s[pos + 2]);
-
-                            if (h1 >= 0 && h2 >= 0)
-                            {     // valid 2 hex chars
-                                byte b = (byte)((h1 << 4) | h2);
-                                pos += 2;
-
-                                // don't add as char
-                                helper.AddByte(b);
-                                continue;
-                            }
-                        }
-                    }
-
-                    if ((ch & 0xFF80) == 0)
-                        helper.AddByte((byte)ch); // 7 bit have to go as bytes because of Unicode
-                    else
-                        helper.AddChar(ch);
-                }
-
-                return helper.GetString();
-            }
-
-            private static int HexToInt(char h)
-            {
-                return (h >= '0' && h <= '9') ? h - '0' :
-                (h >= 'a' && h <= 'f') ? h - 'a' + 10 :
-                (h >= 'A' && h <= 'F') ? h - 'A' + 10 :
-                -1;
-            }
-
-            private class UrlDecoder
-            {
-                private int _bufferSize;
-
-                // Accumulate characters in a special array
-                private int _numChars;
-                private char[] _charBuffer;
-
-                // Accumulate bytes for decoding into characters in a special array
-                private int _numBytes;
-                private byte[] _byteBuffer;
-
-                // Encoding to convert chars to bytes
-                private Encoding _encoding;
-
-                private void FlushBytes()
-                {
-                    if (_numBytes > 0)
-                    {
-                        _numChars += _encoding.GetChars(_byteBuffer, 0, _numBytes, _charBuffer, _numChars);
-                        _numBytes = 0;
-                    }
-                }
-
-                internal UrlDecoder(int bufferSize, Encoding encoding)
-                {
-                    _bufferSize = bufferSize;
-                    _encoding = encoding;
-
-                    _charBuffer = new char[bufferSize];
-                    // byte buffer created on demand
-                }
-
-                internal void AddChar(char ch)
-                {
-                    if (_numBytes > 0)
-                        FlushBytes();
-
-                    _charBuffer[_numChars++] = ch;
-                }
-
-                internal void AddByte(byte b)
-                {
-                    {
-                        if (_byteBuffer == null)
-                            _byteBuffer = new byte[_bufferSize];
-
-                        _byteBuffer[_numBytes++] = b;
-                    }
-                }
-
-                internal string GetString()
-                {
-                    if (_numBytes > 0)
-                        FlushBytes();
-
-                    if (_numChars > 0)
-                        return new string(_charBuffer, 0, _numChars);
-                    else
-                        return string.Empty;
-                }
-            }
-
-
-            internal static void FillFromString(QueryParamCollection nvc, string s, bool urlencoded, Encoding encoding)
-            {
-                int l = (s != null) ? s.Length : 0;
-                int i = (s.Length > 0 && s[0] == '?') ? 1 : 0;
-
-                while (i < l)
-                {
-                    // find next & while noting first = on the way (and if there are more)
-
-                    int si = i;
-                    int ti = -1;
-
-                    while (i < l)
-                    {
-                        char ch = s[i];
-
-                        if (ch == '=')
-                        {
-                            if (ti < 0)
-                                ti = i;
-                        }
-                        else if (ch == '&')
-                        {
-                            break;
-                        }
-
-                        i++;
-                    }
-
-                    // extract the name / value pair
-
-                    string name = null;
-                    string value = null;
-
-                    if (ti >= 0)
-                    {
-                        name = s.Substring(si, ti - si);
-                        value = s.Substring(ti + 1, i - ti - 1);
-                    }
-                    else
-                    {
-                        value = s.Substring(si, i - si);
-                    }
-
-                    // add name / value pair to the collection
-
-                    if (urlencoded)
-                        nvc.Add(
-                           name == null ? null : UrlDecodeStringFromStringInternal(name, encoding),
-                           UrlDecodeStringFromStringInternal(value, encoding));
-                    else
-                        nvc.Add(name, value);
-
-                    // trailing '&'
-
-                    if (i == l - 1 && s[i] == '&')
-                        nvc.Add(null, "");
-
-                    i++;
-                }
-            }
-        }
-    }
-}

+ 0 - 443
SocketHttpListener/Net/HttpListenerRequestUriBuilder.cs

@@ -1,443 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.Text;
-
-namespace SocketHttpListener.Net
-{
-    // We don't use the cooked URL because http.sys unescapes all percent-encoded values. However,
-    // we also can't just use the raw Uri, since http.sys supports not only Utf-8, but also ANSI/DBCS and
-    // Unicode code points. System.Uri only supports Utf-8.
-    // The purpose of this class is to convert all ANSI, DBCS, and Unicode code points into percent encoded
-    // Utf-8 characters.
-    internal sealed class HttpListenerRequestUriBuilder
-    {
-        private static readonly Encoding s_utf8Encoding = new UTF8Encoding(false, true);
-        private static readonly Encoding s_ansiEncoding = Encoding.GetEncoding(0, new EncoderExceptionFallback(), new DecoderExceptionFallback());
-
-        private readonly string _rawUri;
-        private readonly string _cookedUriScheme;
-        private readonly string _cookedUriHost;
-        private readonly string _cookedUriPath;
-        private readonly string _cookedUriQuery;
-
-        // This field is used to build the final request Uri string from the Uri parts passed to the ctor.
-        private StringBuilder _requestUriString;
-
-        // The raw path is parsed by looping through all characters from left to right. 'rawOctets'
-        // is used to store consecutive percent encoded octets as actual byte values: e.g. for path /pa%C3%84th%2F/
-        // rawOctets will be set to { 0xC3, 0x84 } when we reach character 't' and it will be { 0x2F } when
-        // we reach the final '/'. I.e. after a sequence of percent encoded octets ends, we use rawOctets as
-        // input to the encoding and percent encode the resulting string into UTF-8 octets.
-        //
-        // When parsing ANSI (Latin 1) encoded path '/pa%C4th/', %C4 will be added to rawOctets and when
-        // we reach 't', the content of rawOctets { 0xC4 } will be fed into the ANSI encoding. The resulting
-        // string 'Ä' will be percent encoded into UTF-8 octets and appended to requestUriString. The final
-        // path will be '/pa%C3%84th/', where '%C3%84' is the UTF-8 percent encoded character 'Ä'.
-        private List<byte> _rawOctets;
-        private string _rawPath;
-
-        // Holds the final request Uri.
-        private Uri _requestUri;
-
-        private HttpListenerRequestUriBuilder(string rawUri, string cookedUriScheme, string cookedUriHost,
-            string cookedUriPath, string cookedUriQuery)
-        {
-            _rawUri = rawUri;
-            _cookedUriScheme = cookedUriScheme;
-            _cookedUriHost = cookedUriHost;
-            _cookedUriPath = AddSlashToAsteriskOnlyPath(cookedUriPath);
-            _cookedUriQuery = cookedUriQuery ?? string.Empty;
-        }
-
-        public static Uri GetRequestUri(string rawUri, string cookedUriScheme, string cookedUriHost,
-            string cookedUriPath, string cookedUriQuery)
-        {
-            var builder = new HttpListenerRequestUriBuilder(rawUri,
-                cookedUriScheme, cookedUriHost, cookedUriPath, cookedUriQuery);
-
-            return builder.Build();
-        }
-
-        private Uri Build()
-        {
-            BuildRequestUriUsingRawPath();
-
-            if (_requestUri == null)
-            {
-                BuildRequestUriUsingCookedPath();
-            }
-
-            return _requestUri;
-        }
-
-        private void BuildRequestUriUsingCookedPath()
-        {
-            bool isValid = Uri.TryCreate(_cookedUriScheme + Uri.SchemeDelimiter + _cookedUriHost + _cookedUriPath +
-                _cookedUriQuery, UriKind.Absolute, out _requestUri);
-
-            // Creating a Uri from the cooked Uri should really always work: If not, we log at least.
-            if (!isValid)
-            {
-                //if (NetEventSource.IsEnabled)
-                //    NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_create_uri, _cookedUriScheme, _cookedUriHost, _cookedUriPath, _cookedUriQuery));
-            }
-        }
-
-        private void BuildRequestUriUsingRawPath()
-        {
-            bool isValid = false;
-
-            // Initialize 'rawPath' only if really needed; i.e. if we build the request Uri from the raw Uri.
-            _rawPath = GetPath(_rawUri);
-
-            // Try to check the raw path using first the primary encoding (according to http.sys settings);
-            // if it fails try the secondary encoding.
-            ParsingResult result = BuildRequestUriUsingRawPath(GetEncoding(EncodingType.Primary));
-            if (result == ParsingResult.EncodingError)
-            {
-                Encoding secondaryEncoding = GetEncoding(EncodingType.Secondary);
-                result = BuildRequestUriUsingRawPath(secondaryEncoding);
-            }
-            isValid = (result == ParsingResult.Success) ? true : false;
-
-            // Log that we weren't able to create a Uri from the raw string.
-            if (!isValid)
-            {
-                //if (NetEventSource.IsEnabled)
-                //    NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_create_uri, _cookedUriScheme, _cookedUriHost, _rawPath, _cookedUriQuery));
-            }
-        }
-
-        private static Encoding GetEncoding(EncodingType type)
-        {
-            Debug.Assert((type == EncodingType.Primary) || (type == EncodingType.Secondary),
-                "Unknown 'EncodingType' value: " + type.ToString());
-
-            if (type == EncodingType.Secondary)
-            {
-                return s_ansiEncoding;
-            }
-            else
-            {
-                return s_utf8Encoding;
-            }
-        }
-
-        private ParsingResult BuildRequestUriUsingRawPath(Encoding encoding)
-        {
-            Debug.Assert(encoding != null, "'encoding' must be assigned.");
-            Debug.Assert(!string.IsNullOrEmpty(_rawPath), "'rawPath' must have at least one character.");
-
-            _rawOctets = new List<byte>();
-            _requestUriString = new StringBuilder();
-            _requestUriString.Append(_cookedUriScheme);
-            _requestUriString.Append(Uri.SchemeDelimiter);
-            _requestUriString.Append(_cookedUriHost);
-
-            ParsingResult result = ParseRawPath(encoding);
-            if (result == ParsingResult.Success)
-            {
-                _requestUriString.Append(_cookedUriQuery);
-
-                Debug.Assert(_rawOctets.Count == 0,
-                    "Still raw octets left. They must be added to the result path.");
-
-                if (!Uri.TryCreate(_requestUriString.ToString(), UriKind.Absolute, out _requestUri))
-                {
-                    // If we can't create a Uri from the string, this is an invalid string and it doesn't make
-                    // sense to try another encoding.
-                    result = ParsingResult.InvalidString;
-                }
-            }
-
-            if (result != ParsingResult.Success)
-            {
-                //if (NetEventSource.IsEnabled)
-                //    NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_raw_path, _rawPath, encoding.EncodingName));
-            }
-
-            return result;
-        }
-
-        private ParsingResult ParseRawPath(Encoding encoding)
-        {
-            Debug.Assert(encoding != null, "'encoding' must be assigned.");
-
-            int index = 0;
-            char current = '\0';
-            while (index < _rawPath.Length)
-            {
-                current = _rawPath[index];
-                if (current == '%')
-                {
-                    // Assert is enough, since http.sys accepted the request string already. This should never happen.
-                    Debug.Assert(index + 2 < _rawPath.Length, "Expected >=2 characters after '%' (e.g. %2F)");
-
-                    index++;
-                    current = _rawPath[index];
-                    if (current == 'u' || current == 'U')
-                    {
-                        // We found "%u" which means, we have a Unicode code point of the form "%uXXXX".
-                        Debug.Assert(index + 4 < _rawPath.Length, "Expected >=4 characters after '%u' (e.g. %u0062)");
-
-                        // Decode the content of rawOctets into percent encoded UTF-8 characters and append them
-                        // to requestUriString.
-                        if (!EmptyDecodeAndAppendRawOctetsList(encoding))
-                        {
-                            return ParsingResult.EncodingError;
-                        }
-                        if (!AppendUnicodeCodePointValuePercentEncoded(_rawPath.Substring(index + 1, 4)))
-                        {
-                            return ParsingResult.InvalidString;
-                        }
-                        index += 5;
-                    }
-                    else
-                    {
-                        // We found '%', but not followed by 'u', i.e. we have a percent encoded octed: %XX
-                        if (!AddPercentEncodedOctetToRawOctetsList(encoding, _rawPath.Substring(index, 2)))
-                        {
-                            return ParsingResult.InvalidString;
-                        }
-                        index += 2;
-                    }
-                }
-                else
-                {
-                    // We found a non-'%' character: decode the content of rawOctets into percent encoded
-                    // UTF-8 characters and append it to the result.
-                    if (!EmptyDecodeAndAppendRawOctetsList(encoding))
-                    {
-                        return ParsingResult.EncodingError;
-                    }
-                    // Append the current character to the result.
-                    _requestUriString.Append(current);
-                    index++;
-                }
-            }
-
-            // if the raw path ends with a sequence of percent encoded octets, make sure those get added to the
-            // result (requestUriString).
-            if (!EmptyDecodeAndAppendRawOctetsList(encoding))
-            {
-                return ParsingResult.EncodingError;
-            }
-
-            return ParsingResult.Success;
-        }
-
-        private bool AppendUnicodeCodePointValuePercentEncoded(string codePoint)
-        {
-            // http.sys only supports %uXXXX (4 hex-digits), even though unicode code points could have up to
-            // 6 hex digits. Therefore we parse always 4 characters after %u and convert them to an int.
-            if (!int.TryParse(codePoint, NumberStyles.HexNumber, null, out var codePointValue))
-            {
-                //if (NetEventSource.IsEnabled)
-                //    NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_percent_value, codePoint));
-                return false;
-            }
-
-            string unicodeString = null;
-            try
-            {
-                unicodeString = char.ConvertFromUtf32(codePointValue);
-                AppendOctetsPercentEncoded(_requestUriString, s_utf8Encoding.GetBytes(unicodeString));
-
-                return true;
-            }
-            catch (ArgumentOutOfRangeException)
-            {
-                //if (NetEventSource.IsEnabled)
-                //    NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_percent_value, codePoint));
-            }
-            catch (EncoderFallbackException)
-            {
-                // If utf8Encoding.GetBytes() fails
-                //if (NetEventSource.IsEnabled) NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_to_utf8, unicodeString, e.Message));
-            }
-
-            return false;
-        }
-
-        private bool AddPercentEncodedOctetToRawOctetsList(Encoding encoding, string escapedCharacter)
-        {
-            if (!byte.TryParse(escapedCharacter, NumberStyles.HexNumber, null, out byte encodedValue))
-            {
-                //if (NetEventSource.IsEnabled) NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_percent_value, escapedCharacter));
-                return false;
-            }
-
-            _rawOctets.Add(encodedValue);
-
-            return true;
-        }
-
-        private bool EmptyDecodeAndAppendRawOctetsList(Encoding encoding)
-        {
-            if (_rawOctets.Count == 0)
-            {
-                return true;
-            }
-
-            string decodedString = null;
-            try
-            {
-                // If the encoding can get a string out of the byte array, this is a valid string in the
-                // 'encoding' encoding.
-                decodedString = encoding.GetString(_rawOctets.ToArray());
-
-                if (encoding == s_utf8Encoding)
-                {
-                    AppendOctetsPercentEncoded(_requestUriString, _rawOctets.ToArray());
-                }
-                else
-                {
-                    AppendOctetsPercentEncoded(_requestUriString, s_utf8Encoding.GetBytes(decodedString));
-                }
-
-                _rawOctets.Clear();
-
-                return true;
-            }
-            catch (DecoderFallbackException)
-            {
-                //if (NetEventSource.IsEnabled) NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_bytes, GetOctetsAsString(_rawOctets), e.Message));
-            }
-            catch (EncoderFallbackException)
-            {
-                // If utf8Encoding.GetBytes() fails
-                //if (NetEventSource.IsEnabled) NetEventSource.Error(this, SR.Format(SR.net_log_listener_cant_convert_to_utf8, decodedString, e.Message));
-            }
-
-            return false;
-        }
-
-        private static void AppendOctetsPercentEncoded(StringBuilder target, IEnumerable<byte> octets)
-        {
-            foreach (byte octet in octets)
-            {
-                target.Append('%');
-                target.Append(octet.ToString("X2", CultureInfo.InvariantCulture));
-            }
-        }
-
-        private static string GetOctetsAsString(IEnumerable<byte> octets)
-        {
-            var octetString = new StringBuilder();
-
-            bool first = true;
-            foreach (byte octet in octets)
-            {
-                if (first)
-                {
-                    first = false;
-                }
-                else
-                {
-                    octetString.Append(' ');
-                }
-                octetString.Append(octet.ToString("X2", CultureInfo.InvariantCulture));
-            }
-
-            return octetString.ToString();
-        }
-
-        private static string GetPath(string uriString)
-        {
-            Debug.Assert(uriString != null, "uriString must not be null");
-            Debug.Assert(uriString.Length > 0, "uriString must not be empty");
-
-            int pathStartIndex = 0;
-
-            // Perf. improvement: nearly all strings are relative Uris. So just look if the
-            // string starts with '/'. If so, we have a relative Uri and the path starts at position 0.
-            // (http.sys already trimmed leading whitespaces)
-            if (uriString[0] != '/')
-            {
-                // We can't check against cookedUriScheme, since http.sys allows for request http://myserver/ to
-                // use a request line 'GET https://myserver/' (note http vs. https). Therefore check if the
-                // Uri starts with either http:// or https://.
-                int authorityStartIndex = 0;
-                if (uriString.StartsWith("http://", StringComparison.OrdinalIgnoreCase))
-                {
-                    authorityStartIndex = 7;
-                }
-                else if (uriString.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
-                {
-                    authorityStartIndex = 8;
-                }
-
-                if (authorityStartIndex > 0)
-                {
-                    // we have an absolute Uri. Find out where the authority ends and the path begins.
-                    // Note that Uris like "http://server?query=value/1/2" are invalid according to RFC2616
-                    // and http.sys behavior: If the Uri contains a query, there must be at least one '/'
-                    // between the authority and the '?' character: It's safe to just look for the first
-                    // '/' after the authority to determine the beginning of the path.
-                    pathStartIndex = uriString.IndexOf('/', authorityStartIndex);
-                    if (pathStartIndex == -1)
-                    {
-                        // e.g. for request lines like: 'GET http://myserver' (no final '/')
-                        pathStartIndex = uriString.Length;
-                    }
-                }
-                else
-                {
-                    // RFC2616: Request-URI = "*" | absoluteURI | abs_path | authority
-                    // 'authority' can only be used with CONNECT which is never received by HttpListener.
-                    // I.e. if we don't have an absolute path (must start with '/') and we don't have
-                    // an absolute Uri (must start with http:// or https://), then 'uriString' must be '*'.
-                    Debug.Assert((uriString.Length == 1) && (uriString[0] == '*'), "Unknown request Uri string format",
-                        "Request Uri string is not an absolute Uri, absolute path, or '*': {0}", uriString);
-
-                    // Should we ever get here, be consistent with 2.0/3.5 behavior: just add an initial
-                    // slash to the string and treat it as a path:
-                    uriString = "/" + uriString;
-                }
-            }
-
-            // Find end of path: The path is terminated by
-            // - the first '?' character
-            // - the first '#' character: This is never the case here, since http.sys won't accept
-            //   Uris containing fragments. Also, RFC2616 doesn't allow fragments in request Uris.
-            // - end of Uri string
-            int queryIndex = uriString.IndexOf('?');
-            if (queryIndex == -1)
-            {
-                queryIndex = uriString.Length;
-            }
-
-            // will always return a != null string.
-            return AddSlashToAsteriskOnlyPath(uriString.Substring(pathStartIndex, queryIndex - pathStartIndex));
-        }
-
-        private static string AddSlashToAsteriskOnlyPath(string path)
-        {
-            Debug.Assert(path != null, "'path' must not be null");
-
-            // If a request like "OPTIONS * HTTP/1.1" is sent to the listener, then the request Uri
-            // should be "http[s]://server[:port]/*" to be compatible with pre-4.0 behavior.
-            if ((path.Length == 1) && (path[0] == '*'))
-            {
-                return "/*";
-            }
-
-            return path;
-        }
-
-        private enum ParsingResult
-        {
-            Success,
-            InvalidString,
-            EncodingError
-        }
-
-        private enum EncodingType
-        {
-            Primary,
-            Secondary
-        }
-    }
-}

+ 0 - 333
SocketHttpListener/Net/HttpListenerResponse.Managed.cs

@@ -1,333 +0,0 @@
-using System;
-using System.Globalization;
-using System.IO;
-using System.Net;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.IO;
-
-namespace SocketHttpListener.Net
-{
-    public sealed partial class HttpListenerResponse : IDisposable
-    {
-        private long _contentLength;
-        private Version _version = HttpVersion.Version11;
-        private int _statusCode = 200;
-        internal object _headersLock = new object();
-        private bool _forceCloseChunked;
-
-        internal HttpListenerResponse(HttpListenerContext context)
-        {
-            _httpContext = context;
-        }
-
-        internal bool ForceCloseChunked => _forceCloseChunked;
-
-        private void EnsureResponseStream()
-        {
-            if (_responseStream == null)
-            {
-                _responseStream = _httpContext.Connection.GetResponseStream();
-            }
-        }
-
-        public Version ProtocolVersion
-        {
-            get => _version;
-            set
-            {
-                CheckDisposed();
-                if (value == null)
-                {
-                    throw new ArgumentNullException(nameof(value));
-                }
-                if (value.Major != 1 || (value.Minor != 0 && value.Minor != 1))
-                {
-                    throw new ArgumentException("Wrong version");
-                }
-
-                _version = new Version(value.Major, value.Minor); // match Windows behavior, trimming to just Major.Minor
-            }
-        }
-
-        public int StatusCode
-        {
-            get => _statusCode;
-            set
-            {
-                CheckDisposed();
-
-                if (value < 100 || value > 999)
-                    throw new ProtocolViolationException("Invalid status");
-
-                _statusCode = value;
-            }
-        }
-
-        private void Dispose()
-        {
-            Close(true);
-        }
-
-        public void Close()
-        {
-            if (Disposed)
-                return;
-
-            Close(false);
-        }
-
-        public void Abort()
-        {
-            if (Disposed)
-                return;
-
-            Close(true);
-        }
-
-        private void Close(bool force)
-        {
-            Disposed = true;
-            _httpContext.Connection.Close(force);
-        }
-
-        public void Close(byte[] responseEntity, bool willBlock)
-        {
-            CheckDisposed();
-
-            if (responseEntity == null)
-            {
-                throw new ArgumentNullException(nameof(responseEntity));
-            }
-
-            if (!SentHeaders && _boundaryType != BoundaryType.Chunked)
-            {
-                ContentLength64 = responseEntity.Length;
-            }
-
-            if (willBlock)
-            {
-                try
-                {
-                    OutputStream.Write(responseEntity, 0, responseEntity.Length);
-                }
-                finally
-                {
-                    Close(false);
-                }
-            }
-            else
-            {
-                OutputStream.BeginWrite(responseEntity, 0, responseEntity.Length, iar =>
-                {
-                    var thisRef = (HttpListenerResponse)iar.AsyncState;
-                    try
-                    {
-                        try
-                        {
-                            thisRef.OutputStream.EndWrite(iar);
-                        }
-                        finally
-                        {
-                            thisRef.Close(false);
-                        }
-                    }
-                    catch (Exception)
-                    {
-                        // In case response was disposed during this time
-                    }
-                }, this);
-            }
-        }
-
-        public void CopyFrom(HttpListenerResponse templateResponse)
-        {
-            _webHeaders.Clear();
-            //_webHeaders.Add(templateResponse._webHeaders);
-            _contentLength = templateResponse._contentLength;
-            _statusCode = templateResponse._statusCode;
-            _statusDescription = templateResponse._statusDescription;
-            _keepAlive = templateResponse._keepAlive;
-            _version = templateResponse._version;
-        }
-
-        internal void SendHeaders(bool closing, MemoryStream ms, bool isWebSocketHandshake = false)
-        {
-            if (!isWebSocketHandshake)
-            {
-                if (_webHeaders["Server"] == null)
-                {
-                    _webHeaders.Set("Server", "Microsoft-NetCore/2.0");
-                }
-
-                if (_webHeaders["Date"] == null)
-                {
-                    _webHeaders.Set("Date", DateTime.UtcNow.ToString("r", CultureInfo.InvariantCulture));
-                }
-
-                if (_boundaryType == BoundaryType.None)
-                {
-                    if (HttpListenerRequest.ProtocolVersion <= HttpVersion.Version10)
-                    {
-                        _keepAlive = false;
-                    }
-                    else
-                    {
-                        _boundaryType = BoundaryType.Chunked;
-                    }
-
-                    if (CanSendResponseBody(_httpContext.Response.StatusCode))
-                    {
-                        _contentLength = -1;
-                    }
-                    else
-                    {
-                        _boundaryType = BoundaryType.ContentLength;
-                        _contentLength = 0;
-                    }
-                }
-
-                if (_boundaryType != BoundaryType.Chunked)
-                {
-                    if (_boundaryType != BoundaryType.ContentLength && closing)
-                    {
-                        _contentLength = CanSendResponseBody(_httpContext.Response.StatusCode) ? -1 : 0;
-                    }
-
-                    if (_boundaryType == BoundaryType.ContentLength)
-                    {
-                        _webHeaders.Set("Content-Length", _contentLength.ToString("D", CultureInfo.InvariantCulture));
-                    }
-                }
-
-                /* Apache forces closing the connection for these status codes:
-                 * HttpStatusCode.BadRequest            400
-                 * HttpStatusCode.RequestTimeout        408
-                 * HttpStatusCode.LengthRequired        411
-                 * HttpStatusCode.RequestEntityTooLarge 413
-                 * HttpStatusCode.RequestUriTooLong     414
-                 * HttpStatusCode.InternalServerError   500
-                 * HttpStatusCode.ServiceUnavailable    503
-                 */
-                bool conn_close = (_statusCode == (int)HttpStatusCode.BadRequest || _statusCode == (int)HttpStatusCode.RequestTimeout
-                        || _statusCode == (int)HttpStatusCode.LengthRequired || _statusCode == (int)HttpStatusCode.RequestEntityTooLarge
-                        || _statusCode == (int)HttpStatusCode.RequestUriTooLong || _statusCode == (int)HttpStatusCode.InternalServerError
-                        || _statusCode == (int)HttpStatusCode.ServiceUnavailable);
-
-                if (!conn_close)
-                {
-                    conn_close = !_httpContext.Request.KeepAlive;
-                }
-
-                // They sent both KeepAlive: true and Connection: close
-                if (!_keepAlive || conn_close)
-                {
-                    _webHeaders.Set("Connection", "Close");
-                    conn_close = true;
-                }
-
-                if (SendChunked)
-                {
-                    _webHeaders.Set("Transfer-Encoding", "Chunked");
-                }
-
-                int reuses = _httpContext.Connection.Reuses;
-                if (reuses >= 100)
-                {
-                    _forceCloseChunked = true;
-                    if (!conn_close)
-                    {
-                        _webHeaders.Set("Connection", "Close");
-                        conn_close = true;
-                    }
-                }
-
-                if (HttpListenerRequest.ProtocolVersion <= HttpVersion.Version10)
-                {
-                    if (_keepAlive)
-                    {
-                        Headers["Keep-Alive"] = "true";
-                    }
-
-                    if (!conn_close)
-                    {
-                        _webHeaders.Set("Connection", "Keep-Alive");
-                    }
-                }
-
-                ComputeCookies();
-            }
-
-            var encoding = Encoding.UTF8;
-            var writer = new StreamWriter(ms, encoding, 256);
-            writer.Write("HTTP/1.1 {0} ", _statusCode); // "1.1" matches Windows implementation, which ignores the response version
-            writer.Flush();
-            byte[] statusDescriptionBytes = WebHeaderEncoding.GetBytes(StatusDescription);
-            ms.Write(statusDescriptionBytes, 0, statusDescriptionBytes.Length);
-            writer.Write("\r\n");
-
-            writer.Write(FormatHeaders(_webHeaders));
-            writer.Flush();
-            int preamble = encoding.GetPreamble().Length;
-            EnsureResponseStream();
-
-            /* Assumes that the ms was at position 0 */
-            ms.Position = preamble;
-            SentHeaders = !isWebSocketHandshake;
-        }
-
-        private static bool HeaderCanHaveEmptyValue(string name) =>
-            !string.Equals(name, "Location", StringComparison.OrdinalIgnoreCase);
-
-        private static string FormatHeaders(WebHeaderCollection headers)
-        {
-            var sb = new StringBuilder();
-
-            for (int i = 0; i < headers.Count; i++)
-            {
-                string key = headers.GetKey(i);
-                string[] values = headers.GetValues(i);
-
-                int startingLength = sb.Length;
-
-                sb.Append(key).Append(": ");
-                bool anyValues = false;
-                for (int j = 0; j < values.Length; j++)
-                {
-                    string value = values[j];
-                    if (!string.IsNullOrWhiteSpace(value))
-                    {
-                        if (anyValues)
-                        {
-                            sb.Append(", ");
-                        }
-                        sb.Append(value);
-                        anyValues = true;
-                    }
-                }
-
-                if (anyValues || HeaderCanHaveEmptyValue(key))
-                {
-                    // Complete the header
-                    sb.Append("\r\n");
-                }
-                else
-                {
-                    // Empty header; remove it.
-                    sb.Length = startingLength;
-                }
-            }
-
-            return sb.Append("\r\n").ToString();
-        }
-
-        private bool Disposed { get; set; }
-        internal bool SentHeaders { get; set; }
-
-        public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
-        {
-            return ((HttpResponseStream)OutputStream).TransmitFile(path, offset, count, fileShareMode, cancellationToken);
-        }
-    }
-}

+ 0 - 294
SocketHttpListener/Net/HttpListenerResponse.cs

@@ -1,294 +0,0 @@
-using System;
-using System.IO;
-using System.Net;
-using System.Text;
-
-namespace SocketHttpListener.Net
-{
-    public sealed partial class HttpListenerResponse : IDisposable
-    {
-        private BoundaryType _boundaryType = BoundaryType.None;
-        private CookieCollection _cookies;
-        private HttpListenerContext _httpContext;
-        private bool _keepAlive = true;
-        private HttpResponseStream _responseStream;
-        private string _statusDescription;
-        private WebHeaderCollection _webHeaders = new WebHeaderCollection();
-
-        public WebHeaderCollection Headers => _webHeaders;
-
-        public Encoding ContentEncoding { get; set; }
-
-        public string ContentType
-        {
-            get => Headers["Content-Type"];
-            set
-            {
-                CheckDisposed();
-                if (string.IsNullOrEmpty(value))
-                {
-                    Headers.Remove("Content-Type");
-                }
-                else
-                {
-                    Headers.Set("Content-Type", value);
-                }
-            }
-        }
-
-        private HttpListenerContext HttpListenerContext => _httpContext;
-
-        private HttpListenerRequest HttpListenerRequest => HttpListenerContext.Request;
-
-        internal EntitySendFormat EntitySendFormat
-        {
-            get => (EntitySendFormat)_boundaryType;
-            set
-            {
-                CheckDisposed();
-                CheckSentHeaders();
-                if (value == EntitySendFormat.Chunked && HttpListenerRequest.ProtocolVersion.Minor == 0)
-                {
-                    throw new ProtocolViolationException("net_nochunkuploadonhttp10");
-                }
-                _boundaryType = (BoundaryType)value;
-                if (value != EntitySendFormat.ContentLength)
-                {
-                    _contentLength = -1;
-                }
-            }
-        }
-
-        public bool SendChunked
-        {
-            get => EntitySendFormat == EntitySendFormat.Chunked;
-            set => EntitySendFormat = value ? EntitySendFormat.Chunked : EntitySendFormat.ContentLength;
-        }
-
-        // We MUST NOT send message-body when we send responses with these Status codes
-        private static readonly int[] s_noResponseBody = { 100, 101, 204, 205, 304 };
-
-        private static bool CanSendResponseBody(int responseCode)
-        {
-            for (int i = 0; i < s_noResponseBody.Length; i++)
-            {
-                if (responseCode == s_noResponseBody[i])
-                {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        public long ContentLength64
-        {
-            get => _contentLength;
-            set
-            {
-                CheckDisposed();
-                CheckSentHeaders();
-                if (value >= 0)
-                {
-                    _contentLength = value;
-                    _boundaryType = BoundaryType.ContentLength;
-                }
-                else
-                {
-                    throw new ArgumentOutOfRangeException(nameof(value));
-                }
-            }
-        }
-
-        public CookieCollection Cookies
-        {
-            get => _cookies ?? (_cookies = new CookieCollection());
-            set => _cookies = value;
-        }
-
-        public bool KeepAlive
-        {
-            get => _keepAlive;
-            set
-            {
-                CheckDisposed();
-                _keepAlive = value;
-            }
-        }
-
-        public Stream OutputStream
-        {
-            get
-            {
-                CheckDisposed();
-                EnsureResponseStream();
-                return _responseStream;
-            }
-        }
-
-        public string RedirectLocation
-        {
-            get => Headers["Location"];
-            set
-            {
-                // note that this doesn't set the status code to a redirect one
-                CheckDisposed();
-                if (string.IsNullOrEmpty(value))
-                {
-                    Headers.Remove("Location");
-                }
-                else
-                {
-                    Headers.Set("Location", value);
-                }
-            }
-        }
-
-        public string StatusDescription
-        {
-            get
-            {
-                if (_statusDescription == null)
-                {
-                    // if the user hasn't set this, generated on the fly, if possible.
-                    // We know this one is safe, no need to verify it as in the setter.
-                    _statusDescription = HttpStatusDescription.Get(StatusCode);
-                }
-                if (_statusDescription == null)
-                {
-                    _statusDescription = string.Empty;
-                }
-                return _statusDescription;
-            }
-            set
-            {
-                CheckDisposed();
-                if (value == null)
-                {
-                    throw new ArgumentNullException(nameof(value));
-                }
-
-                // Need to verify the status description doesn't contain any control characters except HT.  We mask off the high
-                // byte since that's how it's encoded.
-                for (int i = 0; i < value.Length; i++)
-                {
-                    char c = (char)(0x000000ff & (uint)value[i]);
-                    if ((c <= 31 && c != (byte)'\t') || c == 127)
-                    {
-                        throw new ArgumentException("net_WebHeaderInvalidControlChars");
-                    }
-                }
-
-                _statusDescription = value;
-            }
-        }
-
-        public void AddHeader(string name, string value)
-        {
-            Headers.Set(name, value);
-        }
-
-        public void AppendHeader(string name, string value)
-        {
-            Headers.Add(name, value);
-        }
-
-        public void AppendCookie(Cookie cookie)
-        {
-            if (cookie == null)
-            {
-                throw new ArgumentNullException(nameof(cookie));
-            }
-            Cookies.Add(cookie);
-        }
-
-        private void ComputeCookies()
-        {
-            if (_cookies != null)
-            {
-                // now go through the collection, and concatenate all the cookies in per-variant strings
-                //string setCookie2 = null, setCookie = null;
-                //for (int index = 0; index < _cookies.Count; index++)
-                //{
-                //    Cookie cookie = _cookies[index];
-                //    string cookieString = cookie.ToServerString();
-                //    if (cookieString == null || cookieString.Length == 0)
-                //    {
-                //        continue;
-                //    }
-
-                //    if (cookie.IsRfc2965Variant())
-                //    {
-                //        setCookie2 = setCookie2 == null ? cookieString : setCookie2 + ", " + cookieString;
-                //    }
-                //    else
-                //    {
-                //        setCookie = setCookie == null ? cookieString : setCookie + ", " + cookieString;
-                //    }
-                //}
-
-                //if (!string.IsNullOrEmpty(setCookie))
-                //{
-                //    Headers.Set(HttpKnownHeaderNames.SetCookie, setCookie);
-                //    if (string.IsNullOrEmpty(setCookie2))
-                //    {
-                //        Headers.Remove(HttpKnownHeaderNames.SetCookie2);
-                //    }
-                //}
-
-                //if (!string.IsNullOrEmpty(setCookie2))
-                //{
-                //    Headers.Set(HttpKnownHeaderNames.SetCookie2, setCookie2);
-                //    if (string.IsNullOrEmpty(setCookie))
-                //    {
-                //        Headers.Remove(HttpKnownHeaderNames.SetCookie);
-                //    }
-                //}
-            }
-        }
-
-        public void Redirect(string url)
-        {
-            Headers["Location"] = url;
-            StatusCode = (int)HttpStatusCode.Redirect;
-            StatusDescription = "Found";
-        }
-
-        public void SetCookie(Cookie cookie)
-        {
-            if (cookie == null)
-            {
-                throw new ArgumentNullException(nameof(cookie));
-            }
-
-            //Cookie newCookie = cookie.Clone();
-            //int added = Cookies.InternalAdd(newCookie, true);
-
-            //if (added != 1)
-            //{
-            //    // The Cookie already existed and couldn't be replaced.
-            //    throw new ArgumentException("Cookie exists");
-            //}
-        }
-
-        void IDisposable.Dispose()
-        {
-            Dispose();
-        }
-
-        private void CheckDisposed()
-        {
-            if (Disposed)
-            {
-                throw new ObjectDisposedException(GetType().FullName);
-            }
-        }
-
-        private void CheckSentHeaders()
-        {
-            if (SentHeaders)
-            {
-                throw new InvalidOperationException();
-            }
-        }
-    }
-}

+ 0 - 210
SocketHttpListener/Net/HttpRequestStream.Managed.cs

@@ -1,210 +0,0 @@
-using System;
-using System.IO;
-
-namespace SocketHttpListener.Net
-{
-    // Licensed to the .NET Foundation under one or more agreements.
-    // See the LICENSE file in the project root for more information.
-    //
-    // System.Net.ResponseStream
-    //
-    // Author:
-    //  Gonzalo Paniagua Javier (gonzalo@novell.com)
-    //
-    // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
-    //
-    // Permission is hereby granted, free of charge, to any person obtaining
-    // a copy of this software and associated documentation files (the
-    // "Software"), to deal in the Software without restriction, including
-    // without limitation the rights to use, copy, modify, merge, publish,
-    // distribute, sublicense, and/or sell copies of the Software, and to
-    // permit persons to whom the Software is furnished to do so, subject to
-    // the following conditions:
-    //
-    // The above copyright notice and this permission notice shall be
-    // included in all copies or substantial portions of the Software.
-    //
-    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-    // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-    // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-    //
-
-    internal partial class HttpRequestStream : Stream
-    {
-        private byte[] _buffer;
-        private int _offset;
-        private int _length;
-        private long _remainingBody;
-        protected bool _closed;
-        private Stream _stream;
-
-        internal HttpRequestStream(Stream stream, byte[] buffer, int offset, int length)
-            : this(stream, buffer, offset, length, -1)
-        {
-        }
-
-        internal HttpRequestStream(Stream stream, byte[] buffer, int offset, int length, long contentlength)
-        {
-            _stream = stream;
-            _buffer = buffer;
-            _offset = offset;
-            _length = length;
-            _remainingBody = contentlength;
-        }
-
-        // Returns 0 if we can keep reading from the base stream,
-        // > 0 if we read something from the buffer.
-        // -1 if we had a content length set and we finished reading that many bytes.
-        private int FillFromBuffer(byte[] buffer, int offset, int count)
-        {
-            if (_remainingBody == 0)
-                return -1;
-
-            if (_length == 0)
-                return 0;
-
-            int size = Math.Min(_length, count);
-            if (_remainingBody > 0)
-                size = (int)Math.Min(size, _remainingBody);
-
-            if (_offset > _buffer.Length - size)
-            {
-                size = Math.Min(size, _buffer.Length - _offset);
-            }
-            if (size == 0)
-                return 0;
-
-            Buffer.BlockCopy(_buffer, _offset, buffer, offset, size);
-            _offset += size;
-            _length -= size;
-            if (_remainingBody > 0)
-                _remainingBody -= size;
-            return size;
-        }
-
-        protected virtual int ReadCore(byte[] buffer, int offset, int size)
-        {
-            // Call FillFromBuffer to check for buffer boundaries even when remaining_body is 0
-            int nread = FillFromBuffer(buffer, offset, size);
-            if (nread == -1)
-            { // No more bytes available (Content-Length)
-                return 0;
-            }
-            else if (nread > 0)
-            {
-                return nread;
-            }
-
-            if (_remainingBody > 0)
-            {
-                size = (int)Math.Min(_remainingBody, (long)size);
-            }
-
-            nread = _stream.Read(buffer, offset, size);
-
-            if (_remainingBody > 0)
-            {
-                if (nread == 0)
-                {
-                    throw new Exception("Bad request");
-                }
-
-                //Debug.Assert(nread <= _remainingBody);
-                _remainingBody -= nread;
-            }
-
-            return nread;
-        }
-
-        protected virtual IAsyncResult BeginReadCore(byte[] buffer, int offset, int size, AsyncCallback cback, object state)
-        {
-            if (size == 0 || _closed)
-            {
-                var ares = new HttpStreamAsyncResult(this);
-                ares._callback = cback;
-                ares._state = state;
-                ares.Complete();
-                return ares;
-            }
-
-            int nread = FillFromBuffer(buffer, offset, size);
-            if (nread > 0 || nread == -1)
-            {
-                var ares = new HttpStreamAsyncResult(this);
-                ares._buffer = buffer;
-                ares._offset = offset;
-                ares._count = size;
-                ares._callback = cback;
-                ares._state = state;
-                ares._synchRead = Math.Max(0, nread);
-                ares.Complete();
-                return ares;
-            }
-
-            // Avoid reading past the end of the request to allow
-            // for HTTP pipelining
-            if (_remainingBody >= 0 && size > _remainingBody)
-            {
-                size = (int)Math.Min(_remainingBody, (long)size);
-            }
-
-            return _stream.BeginRead(buffer, offset, size, cback, state);
-        }
-
-        public override int EndRead(IAsyncResult asyncResult)
-        {
-            if (asyncResult == null)
-                throw new ArgumentNullException(nameof(asyncResult));
-
-            var r = asyncResult as HttpStreamAsyncResult;
-            if (r != null)
-            {
-                if (!ReferenceEquals(this, r._parent))
-                {
-                    throw new ArgumentException("Invalid async result");
-                }
-                if (r._endCalled)
-                {
-                    throw new InvalidOperationException("invalid end call");
-                }
-                r._endCalled = true;
-
-                if (!asyncResult.IsCompleted)
-                {
-                    asyncResult.AsyncWaitHandle.WaitOne();
-                }
-
-                return r._synchRead;
-            }
-
-            if (_closed)
-                return 0;
-
-            int nread = 0;
-            try
-            {
-                nread = _stream.EndRead(asyncResult);
-            }
-            catch (IOException e) when (e.InnerException is ArgumentException || e.InnerException is InvalidOperationException)
-            {
-                throw e.InnerException;
-            }
-
-            if (_remainingBody > 0)
-            {
-                if (nread == 0)
-                {
-                    throw new Exception("Bad request");
-                }
-
-                _remainingBody -= nread;
-            }
-
-            return nread;
-        }
-    }
-}

+ 0 - 129
SocketHttpListener/Net/HttpRequestStream.cs

@@ -1,129 +0,0 @@
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace SocketHttpListener.Net
-{
-    // Licensed to the .NET Foundation under one or more agreements.
-    // See the LICENSE file in the project root for more information.
-    //
-    // System.Net.ResponseStream
-    //
-    // Author:
-    //  Gonzalo Paniagua Javier (gonzalo@novell.com)
-    //
-    // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
-    //
-    // Permission is hereby granted, free of charge, to any person obtaining
-    // a copy of this software and associated documentation files (the
-    // "Software"), to deal in the Software without restriction, including
-    // without limitation the rights to use, copy, modify, merge, publish,
-    // distribute, sublicense, and/or sell copies of the Software, and to
-    // permit persons to whom the Software is furnished to do so, subject to
-    // the following conditions:
-    //
-    // The above copyright notice and this permission notice shall be
-    // included in all copies or substantial portions of the Software.
-    //
-    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-    // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-    // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-    //
-
-    internal partial class HttpRequestStream : Stream
-    {
-        public override bool CanSeek => false;
-        public override bool CanWrite => false;
-        public override bool CanRead => true;
-
-        public override int Read(byte[] buffer, int offset, int size)
-        {
-            if (buffer == null)
-            {
-                throw new ArgumentNullException(nameof(buffer));
-            }
-            if (offset < 0 || offset > buffer.Length)
-            {
-                throw new ArgumentOutOfRangeException(nameof(offset));
-            }
-            if (size < 0 || size > buffer.Length - offset)
-            {
-                throw new ArgumentOutOfRangeException(nameof(size));
-            }
-            if (size == 0 || _closed)
-            {
-                return 0;
-            }
-
-            return ReadCore(buffer, offset, size);
-        }
-
-        public override IAsyncResult BeginRead(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
-        {
-            if (buffer == null)
-            {
-                throw new ArgumentNullException(nameof(buffer));
-            }
-            if (offset < 0 || offset > buffer.Length)
-            {
-                throw new ArgumentOutOfRangeException(nameof(offset));
-            }
-            if (size < 0 || size > buffer.Length - offset)
-            {
-                throw new ArgumentOutOfRangeException(nameof(size));
-            }
-
-            return BeginReadCore(buffer, offset, size, callback, state);
-        }
-
-        public override void Flush() { }
-        public override Task FlushAsync(CancellationToken cancellationToken) => Task.CompletedTask;
-
-        public override long Length => throw new NotImplementedException();
-
-        public override long Position
-        {
-            get => throw new NotImplementedException();
-
-            set => throw new NotImplementedException();
-        }
-
-        public override long Seek(long offset, SeekOrigin origin)
-        {
-            throw new NotImplementedException();
-        }
-
-        public override void SetLength(long value)
-        {
-            throw new NotImplementedException();
-        }
-
-        public override void Write(byte[] buffer, int offset, int count)
-        {
-            throw new NotImplementedException();
-        }
-
-        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
-        {
-            return base.BeginWrite(buffer, offset, count, callback, state);
-        }
-
-        public override void EndWrite(IAsyncResult asyncResult)
-        {
-            base.EndWrite(asyncResult);
-        }
-
-        internal bool Closed => _closed;
-
-        protected override void Dispose(bool disposing)
-        {
-            _closed = true;
-            base.Dispose(disposing);
-        }
-    }
-}

+ 0 - 329
SocketHttpListener/Net/HttpResponseStream.Managed.cs

@@ -1,329 +0,0 @@
-using System;
-using System.IO;
-using System.Net;
-using System.Net.Sockets;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using MediaBrowser.Model.IO;
-using MediaBrowser.Model.System;
-using Microsoft.Extensions.Logging;
-
-namespace SocketHttpListener.Net
-{
-    // Licensed to the .NET Foundation under one or more agreements.
-    // See the LICENSE file in the project root for more information.
-    //
-    // System.Net.ResponseStream
-    //
-    // Author:
-    //  Gonzalo Paniagua Javier (gonzalo@novell.com)
-    //
-    // Copyright (c) 2005 Novell, Inc. (http://www.novell.com)
-    //
-    // Permission is hereby granted, free of charge, to any person obtaining
-    // a copy of this software and associated documentation files (the
-    // "Software"), to deal in the Software without restriction, including
-    // without limitation the rights to use, copy, modify, merge, publish,
-    // distribute, sublicense, and/or sell copies of the Software, and to
-    // permit persons to whom the Software is furnished to do so, subject to
-    // the following conditions:
-    //
-    // The above copyright notice and this permission notice shall be
-    // included in all copies or substantial portions of the Software.
-    //
-    // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
-    // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-    // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
-    // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-    // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-    // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-    // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-    //
-
-    internal partial class HttpResponseStream : Stream
-    {
-        private HttpListenerResponse _response;
-        private bool _ignore_errors;
-        private bool _trailer_sent;
-        private Stream _stream;
-        private readonly IStreamHelper _streamHelper;
-        private readonly Socket _socket;
-        private readonly bool _supportsDirectSocketAccess;
-        private readonly IEnvironmentInfo _environment;
-        private readonly IFileSystem _fileSystem;
-        private readonly ILogger _logger;
-
-        internal HttpResponseStream(Stream stream, HttpListenerResponse response, bool ignore_errors, IStreamHelper streamHelper, Socket socket, bool supportsDirectSocketAccess, IEnvironmentInfo environment, IFileSystem fileSystem, ILogger logger)
-        {
-            _response = response;
-            _ignore_errors = ignore_errors;
-            _streamHelper = streamHelper;
-            _socket = socket;
-            _supportsDirectSocketAccess = supportsDirectSocketAccess;
-            _environment = environment;
-            _fileSystem = fileSystem;
-            _logger = logger;
-            _stream = stream;
-        }
-
-        private void DisposeCore()
-        {
-            byte[] bytes = null;
-            MemoryStream ms = GetHeaders(true);
-            bool chunked = _response.SendChunked;
-            if (_stream.CanWrite)
-            {
-                try
-                {
-                    if (ms != null)
-                    {
-                        long start = ms.Position;
-                        if (chunked && !_trailer_sent)
-                        {
-                            bytes = GetChunkSizeBytes(0, true);
-                            ms.Position = ms.Length;
-                            ms.Write(bytes, 0, bytes.Length);
-                        }
-                        InternalWrite(ms.GetBuffer(), (int)start, (int)(ms.Length - start));
-                        _trailer_sent = true;
-                    }
-                    else if (chunked && !_trailer_sent)
-                    {
-                        bytes = GetChunkSizeBytes(0, true);
-                        InternalWrite(bytes, 0, bytes.Length);
-                        _trailer_sent = true;
-                    }
-                }
-                catch (HttpListenerException)
-                {
-                    // Ignore error due to connection reset by peer
-                }
-            }
-            _response.Close();
-        }
-
-        internal async Task WriteWebSocketHandshakeHeadersAsync()
-        {
-            if (_closed)
-                throw new ObjectDisposedException(GetType().ToString());
-
-            if (_stream.CanWrite)
-            {
-                MemoryStream ms = GetHeaders(closing: false, isWebSocketHandshake: true);
-                bool chunked = _response.SendChunked;
-
-                long start = ms.Position;
-                if (chunked)
-                {
-                    byte[] bytes = GetChunkSizeBytes(0, true);
-                    ms.Position = ms.Length;
-                    ms.Write(bytes, 0, bytes.Length);
-                }
-
-                await InternalWriteAsync(ms.GetBuffer(), (int)start, (int)(ms.Length - start)).ConfigureAwait(false);
-                await _stream.FlushAsync().ConfigureAwait(false);
-            }
-        }
-
-        private MemoryStream GetHeaders(bool closing, bool isWebSocketHandshake = false)
-        {
-            //// SendHeaders works on shared headers
-            //lock (_response.headers_lock)
-            //{
-            //    if (_response.HeadersSent)
-            //        return null;
-            //    var ms = CreateNew();
-            //    _response.SendHeaders(closing, ms);
-            //    return ms;
-            //}
-
-            // SendHeaders works on shared headers
-            lock (_response._headersLock)
-            {
-                if (_response.SentHeaders)
-                {
-                    return null;
-                }
-
-                MemoryStream ms = new MemoryStream();
-                _response.SendHeaders(closing, ms, isWebSocketHandshake);
-                return ms;
-            }
-        }
-
-        private static byte[] s_crlf = new byte[] { 13, 10 };
-        private static byte[] GetChunkSizeBytes(int size, bool final)
-        {
-            string str = string.Format("{0:x}\r\n{1}", size, final ? "\r\n" : "");
-            return Encoding.ASCII.GetBytes(str);
-        }
-
-        internal void InternalWrite(byte[] buffer, int offset, int count)
-        {
-            if (_ignore_errors)
-            {
-                try
-                {
-                    _stream.Write(buffer, offset, count);
-                }
-                catch { }
-            }
-            else
-            {
-                _stream.Write(buffer, offset, count);
-            }
-        }
-
-        internal Task InternalWriteAsync(byte[] buffer, int offset, int count) =>
-            _ignore_errors ? InternalWriteIgnoreErrorsAsync(buffer, offset, count) : _stream.WriteAsync(buffer, offset, count);
-
-        private async Task InternalWriteIgnoreErrorsAsync(byte[] buffer, int offset, int count)
-        {
-            try { await _stream.WriteAsync(buffer, offset, count).ConfigureAwait(false); }
-            catch { }
-        }
-
-        private void WriteCore(byte[] buffer, int offset, int size)
-        {
-            if (size == 0)
-                return;
-
-            byte[] bytes = null;
-            MemoryStream ms = GetHeaders(false);
-            bool chunked = _response.SendChunked;
-            if (ms != null)
-            {
-                long start = ms.Position; // After the possible preamble for the encoding
-                ms.Position = ms.Length;
-                if (chunked)
-                {
-                    bytes = GetChunkSizeBytes(size, false);
-                    ms.Write(bytes, 0, bytes.Length);
-                }
-
-                int new_count = Math.Min(size, 16384 - (int)ms.Position + (int)start);
-                ms.Write(buffer, offset, new_count);
-                size -= new_count;
-                offset += new_count;
-                InternalWrite(ms.GetBuffer(), (int)start, (int)(ms.Length - start));
-                ms.SetLength(0);
-                ms.Capacity = 0; // 'dispose' the buffer in ms.
-            }
-            else if (chunked)
-            {
-                bytes = GetChunkSizeBytes(size, false);
-                InternalWrite(bytes, 0, bytes.Length);
-            }
-
-            if (size > 0)
-                InternalWrite(buffer, offset, size);
-            if (chunked)
-                InternalWrite(s_crlf, 0, 2);
-        }
-
-        private IAsyncResult BeginWriteCore(byte[] buffer, int offset, int size, AsyncCallback cback, object state)
-        {
-            if (_closed)
-            {
-                var ares = new HttpStreamAsyncResult(this);
-                ares._callback = cback;
-                ares._state = state;
-                ares.Complete();
-                return ares;
-            }
-
-            byte[] bytes = null;
-            MemoryStream ms = GetHeaders(false);
-            bool chunked = _response.SendChunked;
-            if (ms != null)
-            {
-                long start = ms.Position;
-                ms.Position = ms.Length;
-                if (chunked)
-                {
-                    bytes = GetChunkSizeBytes(size, false);
-                    ms.Write(bytes, 0, bytes.Length);
-                }
-                ms.Write(buffer, offset, size);
-                buffer = ms.GetBuffer();
-                offset = (int)start;
-                size = (int)(ms.Position - start);
-            }
-            else if (chunked)
-            {
-                bytes = GetChunkSizeBytes(size, false);
-                InternalWrite(bytes, 0, bytes.Length);
-            }
-
-            return _stream.BeginWrite(buffer, offset, size, cback, state);
-        }
-
-        private void EndWriteCore(IAsyncResult asyncResult)
-        {
-            if (_closed)
-                return;
-
-            if (_ignore_errors)
-            {
-                try
-                {
-                    _stream.EndWrite(asyncResult);
-                    if (_response.SendChunked)
-                        _stream.Write(s_crlf, 0, 2);
-                }
-                catch { }
-            }
-            else
-            {
-                _stream.EndWrite(asyncResult);
-                if (_response.SendChunked)
-                    _stream.Write(s_crlf, 0, 2);
-            }
-        }
-
-        public Task TransmitFile(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
-        {
-            return TransmitFileManaged(path, offset, count, fileShareMode, cancellationToken);
-        }
-
-        const int StreamCopyToBufferSize = 81920;
-        private async Task TransmitFileManaged(string path, long offset, long count, FileShareMode fileShareMode, CancellationToken cancellationToken)
-        {
-            var allowAsync = _environment.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows;
-
-            //if (count <= 0)
-            //{
-            //    allowAsync = true;
-            //}
-
-            var fileOpenOptions = 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)
-                {
-                    fs.Position = offset;
-                }
-
-                var targetStream = this;
-
-                if (count > 0)
-                {
-                    await _streamHelper.CopyToAsync(fs, targetStream, count, cancellationToken).ConfigureAwait(false);
-                }
-                else
-                {
-                    await fs.CopyToAsync(targetStream, StreamCopyToBufferSize, cancellationToken).ConfigureAwait(false);
-                }
-            }
-        }
-    }
-}

+ 0 - 124
SocketHttpListener/Net/HttpResponseStream.cs

@@ -1,124 +0,0 @@
-using System;
-using System.IO;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace SocketHttpListener.Net
-{
-    internal sealed partial class HttpResponseStream : Stream
-    {
-        private bool _closed;
-        internal bool Closed => _closed;
-
-        public override bool CanRead => false;
-        public override bool CanSeek => false;
-        public override bool CanWrite => true;
-
-        public override void Flush() { }
-        public override Task FlushAsync(CancellationToken cancellationToken) => Task.CompletedTask;
-
-        public override long Length => throw new NotImplementedException();
-
-        public override long Position
-        {
-            get => throw new NotImplementedException();
-
-            set => throw new NotImplementedException();
-        }
-
-        public override long Seek(long offset, SeekOrigin origin)
-        {
-            throw new NotImplementedException();
-        }
-
-        public override void SetLength(long value)
-        {
-            throw new NotImplementedException();
-        }
-
-        public override int Read(byte[] buffer, int offset, int count)
-        {
-            throw new NotImplementedException();
-        }
-
-        public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
-        {
-            return base.BeginRead(buffer, offset, count, callback, state);
-        }
-
-        public override int EndRead(IAsyncResult asyncResult)
-        {
-            return base.EndRead(asyncResult);
-        }
-
-        public override void Write(byte[] buffer, int offset, int size)
-        {
-            if (buffer == null)
-            {
-                throw new ArgumentNullException(nameof(buffer));
-            }
-            if (offset < 0 || offset > buffer.Length)
-            {
-                throw new ArgumentOutOfRangeException(nameof(offset));
-            }
-            if (size < 0 || size > buffer.Length - offset)
-            {
-                throw new ArgumentOutOfRangeException(nameof(size));
-            }
-            if (_closed)
-            {
-                return;
-            }
-
-            WriteCore(buffer, offset, size);
-        }
-
-        public override IAsyncResult BeginWrite(byte[] buffer, int offset, int size, AsyncCallback callback, object state)
-        {
-            if (buffer == null)
-            {
-                throw new ArgumentNullException(nameof(buffer));
-            }
-            if (offset < 0 || offset > buffer.Length)
-            {
-                throw new ArgumentOutOfRangeException(nameof(offset));
-            }
-            if (size < 0 || size > buffer.Length - offset)
-            {
-                throw new ArgumentOutOfRangeException(nameof(size));
-            }
-
-            return BeginWriteCore(buffer, offset, size, callback, state);
-        }
-
-        public override void EndWrite(IAsyncResult asyncResult)
-        {
-            if (asyncResult == null)
-            {
-                throw new ArgumentNullException(nameof(asyncResult));
-            }
-
-            EndWriteCore(asyncResult);
-        }
-
-        protected override void Dispose(bool disposing)
-        {
-            try
-            {
-                if (disposing)
-                {
-                    if (_closed)
-                    {
-                        return;
-                    }
-                    _closed = true;
-                    DisposeCore();
-                }
-            }
-            finally
-            {
-                base.Dispose(disposing);
-            }
-        }
-    }
-}

+ 0 - 321
SocketHttpListener/Net/HttpStatusCode.cs

@@ -1,321 +0,0 @@
-namespace SocketHttpListener.Net
-{
-    /// <summary>
-    /// Contains the values of the HTTP status codes.
-    /// </summary>
-    /// <remarks>
-    /// The HttpStatusCode enumeration contains the values of the HTTP status codes defined in
-    /// <see href="http://tools.ietf.org/html/rfc2616#section-10">RFC 2616</see> for HTTP 1.1.
-    /// </remarks>
-    public enum HttpStatusCode
-    {
-        /// <summary>
-        /// Equivalent to status code 100.
-        /// Indicates that the client should continue with its request.
-        /// </summary>
-        Continue = 100,
-        /// <summary>
-        /// Equivalent to status code 101.
-        /// Indicates that the server is switching the HTTP version or protocol on the connection.
-        /// </summary>
-        SwitchingProtocols = 101,
-        /// <summary>
-        /// Equivalent to status code 200.
-        /// Indicates that the client's request has succeeded.
-        /// </summary>
-        OK = 200,
-        /// <summary>
-        /// Equivalent to status code 201.
-        /// Indicates that the client's request has been fulfilled and resulted in a new resource being
-        /// created.
-        /// </summary>
-        Created = 201,
-        /// <summary>
-        /// Equivalent to status code 202.
-        /// Indicates that the client's request has been accepted for processing, but the processing
-        /// hasn't been completed.
-        /// </summary>
-        Accepted = 202,
-        /// <summary>
-        /// Equivalent to status code 203.
-        /// Indicates that the returned metainformation is from a local or a third-party copy instead of
-        /// the origin server.
-        /// </summary>
-        NonAuthoritativeInformation = 203,
-        /// <summary>
-        /// Equivalent to status code 204.
-        /// Indicates that the server has fulfilled the client's request but doesn't need to return
-        /// an entity-body.
-        /// </summary>
-        NoContent = 204,
-        /// <summary>
-        /// Equivalent to status code 205.
-        /// Indicates that the server has fulfilled the client's request, and the user agent should
-        /// reset the document view which caused the request to be sent.
-        /// </summary>
-        ResetContent = 205,
-        /// <summary>
-        /// Equivalent to status code 206.
-        /// Indicates that the server has fulfilled the partial GET request for the resource.
-        /// </summary>
-        PartialContent = 206,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 300.
-        ///   Indicates that the requested resource corresponds to any of multiple representations.
-        ///   </para>
-        ///   <para>
-        ///   MultipleChoices is a synonym for Ambiguous.
-        ///   </para>
-        /// </summary>
-        MultipleChoices = 300,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 300.
-        ///   Indicates that the requested resource corresponds to any of multiple representations.
-        ///   </para>
-        ///   <para>
-        ///   Ambiguous is a synonym for MultipleChoices.
-        ///   </para>
-        /// </summary>
-        Ambiguous = 300,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 301.
-        ///   Indicates that the requested resource has been assigned a new permanent URI and
-        ///   any future references to this resource should use one of the returned URIs.
-        ///   </para>
-        ///   <para>
-        ///   MovedPermanently is a synonym for Moved.
-        ///   </para>
-        /// </summary>
-        MovedPermanently = 301,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 301.
-        ///   Indicates that the requested resource has been assigned a new permanent URI and
-        ///   any future references to this resource should use one of the returned URIs.
-        ///   </para>
-        ///   <para>
-        ///   Moved is a synonym for MovedPermanently.
-        ///   </para>
-        /// </summary>
-        Moved = 301,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 302.
-        ///   Indicates that the requested resource is located temporarily under a different URI.
-        ///   </para>
-        ///   <para>
-        ///   Found is a synonym for Redirect.
-        ///   </para>
-        /// </summary>
-        Found = 302,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 302.
-        ///   Indicates that the requested resource is located temporarily under a different URI.
-        ///   </para>
-        ///   <para>
-        ///   Redirect is a synonym for Found.
-        ///   </para>
-        /// </summary>
-        Redirect = 302,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 303.
-        ///   Indicates that the response to the request can be found under a different URI and
-        ///   should be retrieved using a GET method on that resource.
-        ///   </para>
-        ///   <para>
-        ///   SeeOther is a synonym for RedirectMethod.
-        ///   </para>
-        /// </summary>
-        SeeOther = 303,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 303.
-        ///   Indicates that the response to the request can be found under a different URI and
-        ///   should be retrieved using a GET method on that resource.
-        ///   </para>
-        ///   <para>
-        ///   RedirectMethod is a synonym for SeeOther.
-        ///   </para>
-        /// </summary>
-        RedirectMethod = 303,
-        /// <summary>
-        /// Equivalent to status code 304.
-        /// Indicates that the client has performed a conditional GET request and access is allowed,
-        /// but the document hasn't been modified.
-        /// </summary>
-        NotModified = 304,
-        /// <summary>
-        /// Equivalent to status code 305.
-        /// Indicates that the requested resource must be accessed through the proxy given by
-        /// the Location field.
-        /// </summary>
-        UseProxy = 305,
-        /// <summary>
-        /// Equivalent to status code 306.
-        /// This status code was used in a previous version of the specification, is no longer used,
-        /// and is reserved for future use.
-        /// </summary>
-        Unused = 306,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 307.
-        ///   Indicates that the requested resource is located temporarily under a different URI.
-        ///   </para>
-        ///   <para>
-        ///   TemporaryRedirect is a synonym for RedirectKeepVerb.
-        ///   </para>
-        /// </summary>
-        TemporaryRedirect = 307,
-        /// <summary>
-        ///   <para>
-        ///   Equivalent to status code 307.
-        ///   Indicates that the requested resource is located temporarily under a different URI.
-        ///   </para>
-        ///   <para>
-        ///   RedirectKeepVerb is a synonym for TemporaryRedirect.
-        ///   </para>
-        /// </summary>
-        RedirectKeepVerb = 307,
-        /// <summary>
-        /// Equivalent to status code 400.
-        /// Indicates that the client's request couldn't be understood by the server due to
-        /// malformed syntax.
-        /// </summary>
-        BadRequest = 400,
-        /// <summary>
-        /// Equivalent to status code 401.
-        /// Indicates that the client's request requires user authentication.
-        /// </summary>
-        Unauthorized = 401,
-        /// <summary>
-        /// Equivalent to status code 402.
-        /// This status code is reserved for future use.
-        /// </summary>
-        PaymentRequired = 402,
-        /// <summary>
-        /// Equivalent to status code 403.
-        /// Indicates that the server understood the client's request but is refusing to fulfill it.
-        /// </summary>
-        Forbidden = 403,
-        /// <summary>
-        /// Equivalent to status code 404.
-        /// Indicates that the server hasn't found anything matching the request URI.
-        /// </summary>
-        NotFound = 404,
-        /// <summary>
-        /// Equivalent to status code 405.
-        /// Indicates that the method specified in the request line isn't allowed for the resource
-        /// identified by the request URI.
-        /// </summary>
-        MethodNotAllowed = 405,
-        /// <summary>
-        /// Equivalent to status code 406.
-        /// Indicates that the server doesn't have the appropriate resource to respond to the Accept
-        /// headers in the client's request.
-        /// </summary>
-        NotAcceptable = 406,
-        /// <summary>
-        /// Equivalent to status code 407.
-        /// Indicates that the client must first authenticate itself with the proxy.
-        /// </summary>
-        ProxyAuthenticationRequired = 407,
-        /// <summary>
-        /// Equivalent to status code 408.
-        /// Indicates that the client didn't produce a request within the time that the server was
-        /// prepared to wait.
-        /// </summary>
-        RequestTimeout = 408,
-        /// <summary>
-        /// Equivalent to status code 409.
-        /// Indicates that the client's request couldn't be completed due to a conflict on the server.
-        /// </summary>
-        Conflict = 409,
-        /// <summary>
-        /// Equivalent to status code 410.
-        /// Indicates that the requested resource is no longer available at the server and
-        /// no forwarding address is known.
-        /// </summary>
-        Gone = 410,
-        /// <summary>
-        /// Equivalent to status code 411.
-        /// Indicates that the server refuses to accept the client's request without a defined
-        /// Content-Length.
-        /// </summary>
-        LengthRequired = 411,
-        /// <summary>
-        /// Equivalent to status code 412.
-        /// Indicates that the precondition given in one or more of the request headers evaluated to
-        /// false when it was tested on the server.
-        /// </summary>
-        PreconditionFailed = 412,
-        /// <summary>
-        /// Equivalent to status code 413.
-        /// Indicates that the entity of the client's request is larger than the server is willing or
-        /// able to process.
-        /// </summary>
-        RequestEntityTooLarge = 413,
-        /// <summary>
-        /// Equivalent to status code 414.
-        /// Indicates that the request URI is longer than the server is willing to interpret.
-        /// </summary>
-        RequestUriTooLong = 414,
-        /// <summary>
-        /// Equivalent to status code 415.
-        /// Indicates that the entity of the client's request is in a format not supported by
-        /// the requested resource for the requested method.
-        /// </summary>
-        UnsupportedMediaType = 415,
-        /// <summary>
-        /// Equivalent to status code 416.
-        /// Indicates that none of the range specifier values in a Range request header overlap
-        /// the current extent of the selected resource.
-        /// </summary>
-        RequestedRangeNotSatisfiable = 416,
-        /// <summary>
-        /// Equivalent to status code 417.
-        /// Indicates that the expectation given in an Expect request header couldn't be met by
-        /// the server.
-        /// </summary>
-        ExpectationFailed = 417,
-        /// <summary>
-        /// Equivalent to status code 500.
-        /// Indicates that the server encountered an unexpected condition which prevented it from
-        /// fulfilling the client's request.
-        /// </summary>
-        InternalServerError = 500,
-        /// <summary>
-        /// Equivalent to status code 501.
-        /// Indicates that the server doesn't support the functionality required to fulfill the client's
-        /// request.
-        /// </summary>
-        NotImplemented = 501,
-        /// <summary>
-        /// Equivalent to status code 502.
-        /// Indicates that a gateway or proxy server received an invalid response from the upstream
-        /// server.
-        /// </summary>
-        BadGateway = 502,
-        /// <summary>
-        /// Equivalent to status code 503.
-        /// Indicates that the server is currently unable to handle the client's request due to
-        /// a temporary overloading or maintenance of the server.
-        /// </summary>
-        ServiceUnavailable = 503,
-        /// <summary>
-        /// Equivalent to status code 504.
-        /// Indicates that a gateway or proxy server didn't receive a timely response from the upstream
-        /// server or some other auxiliary server.
-        /// </summary>
-        GatewayTimeout = 504,
-        /// <summary>
-        /// Equivalent to status code 505.
-        /// Indicates that the server doesn't support the HTTP version used in the client's request.
-        /// </summary>
-        HttpVersionNotSupported = 505,
-    }
-}

+ 0 - 69
SocketHttpListener/Net/HttpStatusDescription.cs

@@ -1,69 +0,0 @@
-namespace SocketHttpListener.Net
-{
-    internal static class HttpStatusDescription
-    {
-        internal static string Get(HttpStatusCode code)
-        {
-            return Get((int)code);
-        }
-
-        internal static string Get(int code)
-        {
-            switch (code)
-            {
-                case 100: return "Continue";
-                case 101: return "Switching Protocols";
-                case 102: return "Processing";
-
-                case 200: return "OK";
-                case 201: return "Created";
-                case 202: return "Accepted";
-                case 203: return "Non-Authoritative Information";
-                case 204: return "No Content";
-                case 205: return "Reset Content";
-                case 206: return "Partial Content";
-                case 207: return "Multi-Status";
-
-                case 300: return "Multiple Choices";
-                case 301: return "Moved Permanently";
-                case 302: return "Found";
-                case 303: return "See Other";
-                case 304: return "Not Modified";
-                case 305: return "Use Proxy";
-                case 307: return "Temporary Redirect";
-
-                case 400: return "Bad Request";
-                case 401: return "Unauthorized";
-                case 402: return "Payment Required";
-                case 403: return "Forbidden";
-                case 404: return "Not Found";
-                case 405: return "Method Not Allowed";
-                case 406: return "Not Acceptable";
-                case 407: return "Proxy Authentication Required";
-                case 408: return "Request Timeout";
-                case 409: return "Conflict";
-                case 410: return "Gone";
-                case 411: return "Length Required";
-                case 412: return "Precondition Failed";
-                case 413: return "Request Entity Too Large";
-                case 414: return "Request-Uri Too Long";
-                case 415: return "Unsupported Media Type";
-                case 416: return "Requested Range Not Satisfiable";
-                case 417: return "Expectation Failed";
-                case 422: return "Unprocessable Entity";
-                case 423: return "Locked";
-                case 424: return "Failed Dependency";
-                case 426: return "Upgrade Required"; // RFC 2817
-
-                case 500: return "Internal Server Error";
-                case 501: return "Not Implemented";
-                case 502: return "Bad Gateway";
-                case 503: return "Service Unavailable";
-                case 504: return "Gateway Timeout";
-                case 505: return "Http Version Not Supported";
-                case 507: return "Insufficient Storage";
-            }
-            return null;
-        }
-    }
-}

+ 0 - 79
SocketHttpListener/Net/HttpStreamAsyncResult.cs

@@ -1,79 +0,0 @@
-using System;
-using System.Threading;
-using System.Threading.Tasks;
-
-namespace SocketHttpListener.Net
-{
-    internal class HttpStreamAsyncResult : IAsyncResult
-    {
-        private object _locker = new object();
-        private ManualResetEvent _handle;
-        private bool _completed;
-
-        internal readonly object _parent;
-        internal byte[] _buffer;
-        internal int _offset;
-        internal int _count;
-        internal AsyncCallback _callback;
-        internal object _state;
-        internal int _synchRead;
-        internal Exception _error;
-        internal bool _endCalled;
-
-        internal HttpStreamAsyncResult(object parent)
-        {
-            _parent = parent;
-        }
-
-        public void Complete(Exception e)
-        {
-            _error = e;
-            Complete();
-        }
-
-        public void Complete()
-        {
-            lock (_locker)
-            {
-                if (_completed)
-                    return;
-
-                _completed = true;
-                if (_handle != null)
-                    _handle.Set();
-
-                if (_callback != null)
-                    Task.Run(() => _callback(this));
-            }
-        }
-
-        public object AsyncState => _state;
-
-        public WaitHandle AsyncWaitHandle
-        {
-            get
-            {
-                lock (_locker)
-                {
-                    if (_handle == null)
-                        _handle = new ManualResetEvent(_completed);
-                }
-
-                return _handle;
-            }
-        }
-
-        public bool CompletedSynchronously => false;
-
-        public bool IsCompleted
-        {
-            get
-            {
-                lock (_locker)
-                {
-                    return _completed;
-                }
-            }
-        }
-    }
-}

+ 0 - 16
SocketHttpListener/Net/HttpVersion.cs

@@ -1,16 +0,0 @@
-using System;
-
-namespace SocketHttpListener.Net
-{
-    // <remarks>
-    // </remarks>
-    public class HttpVersion
-    {
-
-        public static readonly Version Version10 = new Version(1, 0);
-        public static readonly Version Version11 = new Version(1, 1);
-
-        // pretty useless..
-        public HttpVersion() { }
-    }
-}

+ 0 - 89
SocketHttpListener/Net/ListenerPrefix.cs

@@ -1,89 +0,0 @@
-using System;
-using System.Net;
-
-namespace SocketHttpListener.Net
-{
-    internal sealed class ListenerPrefix
-    {
-        private string _original;
-        private string _host;
-        private ushort _port;
-        private string _path;
-        private bool _secure;
-        private IPAddress[] _addresses;
-        internal HttpListener _listener;
-
-        public ListenerPrefix(string prefix)
-        {
-            _original = prefix;
-            Parse(prefix);
-        }
-
-        public override string ToString()
-        {
-            return _original;
-        }
-
-        public IPAddress[] Addresses
-        {
-            get => _addresses;
-            set => _addresses = value;
-        }
-        public bool Secure => _secure;
-
-        public string Host => _host;
-
-        public int Port => _port;
-
-        public string Path => _path;
-
-        // Equals and GetHashCode are required to detect duplicates in HttpListenerPrefixCollection.
-        public override bool Equals(object o)
-        {
-            var other = o as ListenerPrefix;
-            if (other == null)
-                return false;
-
-            return (_original == other._original);
-        }
-
-        public override int GetHashCode()
-        {
-            return _original.GetHashCode();
-        }
-
-        private void Parse(string uri)
-        {
-            ushort default_port = 80;
-            if (uri.StartsWith("https://"))
-            {
-                default_port = 443;
-                _secure = true;
-            }
-
-            int length = uri.Length;
-            int start_host = uri.IndexOf(':') + 3;
-            if (start_host >= length)
-                throw new ArgumentException("net_listener_host");
-
-            int colon = uri.IndexOf(':', start_host, length - start_host);
-            int root;
-            if (colon > 0)
-            {
-                _host = uri.Substring(start_host, colon - start_host);
-                root = uri.IndexOf('/', colon, length - colon);
-                _port = (ushort)int.Parse(uri.Substring(colon + 1, root - colon - 1));
-                _path = uri.Substring(root);
-            }
-            else
-            {
-                root = uri.IndexOf('/', start_host, length - start_host);
-                _host = uri.Substring(start_host, root - start_host);
-                _port = default_port;
-                _path = uri.Substring(root);
-            }
-            if (_path.Length != 1)
-                _path = _path.Substring(0, _path.Length - 1);
-        }
-    }
-}

+ 0 - 20
SocketHttpListener/Net/UriScheme.cs

@@ -1,20 +0,0 @@
-namespace SocketHttpListener.Net
-{
-    internal static class UriScheme
-    {
-        public const string File = "file";
-        public const string Ftp = "ftp";
-        public const string Gopher = "gopher";
-        public const string Http = "http";
-        public const string Https = "https";
-        public const string News = "news";
-        public const string NetPipe = "net.pipe";
-        public const string NetTcp = "net.tcp";
-        public const string Nntp = "nntp";
-        public const string Mailto = "mailto";
-        public const string Ws = "ws";
-        public const string Wss = "wss";
-
-        public const string SchemeDelimiter = "://";
-    }
-}

+ 0 - 360
SocketHttpListener/Net/WebHeaderCollection.cs

@@ -1,360 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Text;
-using MediaBrowser.Model.Services;
-
-namespace SocketHttpListener.Net
-{
-    [ComVisible(true)]
-    public class WebHeaderCollection : QueryParamCollection
-    {
-        [Flags]
-        internal enum HeaderInfo
-        {
-            Request = 1,
-            Response = 1 << 1,
-            MultiValue = 1 << 10
-        }
-
-        static readonly bool[] allowed_chars = {
-            false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-            false, false, false, false, false, false, false, false, false, false, false, false, false, false,
-            false, false, false, false, false, true, false, true, true, true, true, false, false, false, true,
-            true, false, true, true, false, true, true, true, true, true, true, true, true, true, true, false,
-            false, false, false, false, false, false, true, true, true, true, true, true, true, true, true,
-            true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
-            false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true,
-            true, true, true, true, true, true, true, true, true, true, true, true, true, true, true, true,
-            false, true, false
-        };
-
-        static readonly Dictionary<string, HeaderInfo> headers;
-
-        static WebHeaderCollection()
-        {
-            headers = new Dictionary<string, HeaderInfo>(StringComparer.OrdinalIgnoreCase) {
-                { "Allow", HeaderInfo.MultiValue },
-                { "Accept", HeaderInfo.Request | HeaderInfo.MultiValue },
-                { "Accept-Charset", HeaderInfo.MultiValue },
-                { "Accept-Encoding", HeaderInfo.MultiValue },
-                { "Accept-Language", HeaderInfo.MultiValue },
-                { "Accept-Ranges", HeaderInfo.MultiValue },
-                { "Age", HeaderInfo.Response },
-                { "Authorization", HeaderInfo.MultiValue },
-                { "Cache-Control", HeaderInfo.MultiValue },
-                { "Cookie", HeaderInfo.MultiValue },
-                { "Connection", HeaderInfo.Request | HeaderInfo.MultiValue },
-                { "Content-Encoding", HeaderInfo.MultiValue },
-                { "Content-Length", HeaderInfo.Request | HeaderInfo.Response },
-                { "Content-Type", HeaderInfo.Request },
-                { "Content-Language", HeaderInfo.MultiValue },
-                { "Date", HeaderInfo.Request },
-                { "Expect", HeaderInfo.Request | HeaderInfo.MultiValue},
-                { "Host", HeaderInfo.Request },
-                { "If-Match", HeaderInfo.MultiValue },
-                { "If-Modified-Since", HeaderInfo.Request },
-                { "If-None-Match", HeaderInfo.MultiValue },
-                { "Keep-Alive", HeaderInfo.Response },
-                { "Pragma", HeaderInfo.MultiValue },
-                { "Proxy-Authenticate", HeaderInfo.MultiValue },
-                { "Proxy-Authorization", HeaderInfo.MultiValue },
-                { "Proxy-Connection", HeaderInfo.Request | HeaderInfo.MultiValue },
-                { "Range", HeaderInfo.Request | HeaderInfo.MultiValue },
-                { "Referer", HeaderInfo.Request },
-                { "Set-Cookie", HeaderInfo.MultiValue },
-                { "Set-Cookie2", HeaderInfo.MultiValue },
-                { "Server", HeaderInfo.Response },
-                { "TE", HeaderInfo.MultiValue },
-                { "Trailer", HeaderInfo.MultiValue },
-                { "Transfer-Encoding", HeaderInfo.Request | HeaderInfo.Response | HeaderInfo.MultiValue },
-                { "Translate", HeaderInfo.Request | HeaderInfo.Response },
-                { "Upgrade", HeaderInfo.MultiValue },
-                { "User-Agent", HeaderInfo.Request },
-                { "Vary", HeaderInfo.MultiValue },
-                { "Via", HeaderInfo.MultiValue },
-                { "Warning", HeaderInfo.MultiValue },
-                { "WWW-Authenticate", HeaderInfo.Response | HeaderInfo. MultiValue },
-                { "SecWebSocketAccept",  HeaderInfo.Response },
-                { "SecWebSocketExtensions", HeaderInfo.Request | HeaderInfo.Response | HeaderInfo. MultiValue },
-                { "SecWebSocketKey", HeaderInfo.Request },
-                { "Sec-WebSocket-Protocol", HeaderInfo.Request | HeaderInfo.Response | HeaderInfo. MultiValue },
-                { "SecWebSocketVersion", HeaderInfo.Response | HeaderInfo. MultiValue }
-            };
-        }
-
-        // Methods
-
-        public void Add(string header)
-        {
-            if (header == null)
-                throw new ArgumentNullException(nameof(header));
-            int pos = header.IndexOf(':');
-            if (pos == -1)
-                throw new ArgumentException("no colon found", nameof(header));
-
-            this.Add(header.Substring(0, pos), header.Substring(pos + 1));
-        }
-
-        public override void Add(string name, string value)
-        {
-            if (name == null)
-                throw new ArgumentNullException(nameof(name));
-
-            this.AddWithoutValidate(name, value);
-        }
-
-        protected void AddWithoutValidate(string headerName, string headerValue)
-        {
-            if (!IsHeaderName(headerName))
-                throw new ArgumentException("invalid header name: " + headerName, nameof(headerName));
-            if (headerValue == null)
-                headerValue = string.Empty;
-            else
-                headerValue = headerValue.Trim();
-            if (!IsHeaderValue(headerValue))
-                throw new ArgumentException("invalid header value: " + headerValue, nameof(headerValue));
-
-            AddValue(headerName, headerValue);
-        }
-
-        internal void AddValue(string headerName, string headerValue)
-        {
-            base.Add(headerName, headerValue);
-        }
-
-        internal List<string> GetValues_internal(string header, bool split)
-        {
-            if (header == null)
-                throw new ArgumentNullException(nameof(header));
-
-            var values = base.GetValues(header);
-            if (values == null || values.Count == 0)
-                return null;
-
-            if (split && IsMultiValue(header))
-            {
-                List<string> separated = null;
-                foreach (var value in values)
-                {
-                    if (value.IndexOf(',') < 0)
-                    {
-                        if (separated != null)
-                            separated.Add(value);
-
-                        continue;
-                    }
-
-                    if (separated == null)
-                    {
-                        separated = new List<string>(values.Count + 1);
-                        foreach (var v in values)
-                        {
-                            if (v == value)
-                                break;
-
-                            separated.Add(v);
-                        }
-                    }
-
-                    var slices = value.Split(',');
-                    var slices_length = slices.Length;
-                    if (value[value.Length - 1] == ',')
-                        --slices_length;
-
-                    for (int i = 0; i < slices_length; ++i)
-                    {
-                        separated.Add(slices[i].Trim());
-                    }
-                }
-
-                if (separated != null)
-                    return separated;
-            }
-
-            return values;
-        }
-
-        public override List<string> GetValues(string header)
-        {
-            return GetValues_internal(header, true);
-        }
-
-        public override string[] GetValues(int index)
-        {
-            string[] values = base.GetValues(index);
-
-            if (values == null || values.Length == 0)
-            {
-                return null;
-            }
-
-            return values;
-        }
-
-        public static bool IsRestricted(string headerName)
-        {
-            return IsRestricted(headerName, false);
-        }
-
-        public static bool IsRestricted(string headerName, bool response)
-        {
-            if (headerName == null)
-                throw new ArgumentNullException(nameof(headerName));
-
-            if (headerName.Length == 0)
-                throw new ArgumentException("empty string", nameof(headerName));
-
-            if (!IsHeaderName(headerName))
-                throw new ArgumentException("Invalid character in header");
-
-            if (!headers.TryGetValue(headerName, out HeaderInfo info))
-                return false;
-
-            var flag = response ? HeaderInfo.Response : HeaderInfo.Request;
-            return (info & flag) != 0;
-        }
-
-        public override void Set(string name, string value)
-        {
-            if (name == null)
-                throw new ArgumentNullException(nameof(name));
-            if (!IsHeaderName(name))
-                throw new ArgumentException("invalid header name");
-            if (value == null)
-                value = string.Empty;
-            else
-                value = value.Trim();
-            if (!IsHeaderValue(value))
-                throw new ArgumentException("invalid header value");
-
-            base.Set(name, value);
-        }
-
-        internal string ToStringMultiValue()
-        {
-            var sb = new StringBuilder();
-
-            int count = base.Count;
-            for (int i = 0; i < count; i++)
-            {
-                string key = GetKey(i);
-                if (IsMultiValue(key))
-                {
-                    foreach (string v in GetValues(i))
-                    {
-                        sb.Append(key)
-                          .Append(": ")
-                          .Append(v)
-                          .Append("\r\n");
-                    }
-                }
-                else
-                {
-                    sb.Append(key)
-                      .Append(": ")
-                      .Append(Get(i))
-                      .Append("\r\n");
-                }
-            }
-            return sb.Append("\r\n").ToString();
-        }
-
-        public override string ToString()
-        {
-            var sb = new StringBuilder();
-
-            int count = base.Count;
-            for (int i = 0; i < count; i++)
-                sb.Append(GetKey(i))
-                  .Append(": ")
-                  .Append(Get(i))
-                  .Append("\r\n");
-
-            return sb.Append("\r\n").ToString();
-        }
-
-
-        // Internal Methods
-
-        // With this we don't check for invalid characters in header. See bug #55994.
-        internal void SetInternal(string header)
-        {
-            int pos = header.IndexOf(':');
-            if (pos == -1)
-                throw new ArgumentException("no colon found", nameof(header));
-
-            SetInternal(header.Substring(0, pos), header.Substring(pos + 1));
-        }
-
-        internal void SetInternal(string name, string value)
-        {
-            if (value == null)
-                value = string.Empty;
-            else
-                value = value.Trim();
-            if (!IsHeaderValue(value))
-                throw new ArgumentException("invalid header value");
-
-            if (IsMultiValue(name))
-            {
-                base.Add(name, value);
-            }
-            else
-            {
-                base.Remove(name);
-                base.Set(name, value);
-            }
-        }
-
-        internal static bool IsMultiValue(string headerName)
-        {
-            if (headerName == null)
-                return false;
-
-            return headers.TryGetValue(headerName, out HeaderInfo info) && (info & HeaderInfo.MultiValue) != 0;
-        }
-
-        internal static bool IsHeaderValue(string value)
-        {
-            // TEXT any 8 bit value except CTL's (0-31 and 127)
-            //      but including \r\n space and \t
-            //      after a newline at least one space or \t must follow
-            //      certain header fields allow comments ()
-
-            int len = value.Length;
-            for (int i = 0; i < len; i++)
-            {
-                char c = value[i];
-                if (c == 127)
-                    return false;
-                if (c < 0x20 && (c != '\r' && c != '\n' && c != '\t'))
-                    return false;
-                if (c == '\n' && ++i < len)
-                {
-                    c = value[i];
-                    if (c != ' ' && c != '\t')
-                        return false;
-                }
-            }
-
-            return true;
-        }
-
-        internal static bool IsHeaderName(string name)
-        {
-            if (name == null || name.Length == 0)
-                return false;
-
-            int len = name.Length;
-            for (int i = 0; i < len; i++)
-            {
-                char c = name[i];
-                if (c > 126 || !allowed_chars[c])
-                    return false;
-            }
-
-            return true;
-        }
-    }
-}

+ 0 - 84
SocketHttpListener/Net/WebHeaderEncoding.cs

@@ -1,84 +0,0 @@
-using System.Text;
-
-namespace SocketHttpListener.Net
-{
-    // we use this static class as a helper class to encode/decode HTTP headers.
-    // what we need is a 1-1 correspondence between a char in the range U+0000-U+00FF
-    // and a byte in the range 0x00-0xFF (which is the range that can hit the network).
-    // The Latin-1 encoding (ISO-88591-1) (GetEncoding(28591)) works for byte[] to string, but is a little slow.
-    // It doesn't work for string -> byte[] because of best-fit-mapping problems.
-    internal static class WebHeaderEncoding
-    {
-        // We don't want '?' replacement characters, just fail.
-        private static readonly Encoding s_utf8Decoder = Encoding.GetEncoding("utf-8", EncoderFallback.ExceptionFallback, DecoderFallback.ExceptionFallback);
-
-        internal static unsafe string GetString(byte[] bytes, int byteIndex, int byteCount)
-        {
-            fixed (byte* pBytes = bytes)
-                return GetString(pBytes + byteIndex, byteCount);
-        }
-
-        internal static unsafe string GetString(byte* pBytes, int byteCount)
-        {
-            if (byteCount < 1)
-                return "";
-
-            string s = new string('\0', byteCount);
-
-            fixed (char* pStr = s)
-            {
-                char* pString = pStr;
-                while (byteCount >= 8)
-                {
-                    pString[0] = (char)pBytes[0];
-                    pString[1] = (char)pBytes[1];
-                    pString[2] = (char)pBytes[2];
-                    pString[3] = (char)pBytes[3];
-                    pString[4] = (char)pBytes[4];
-                    pString[5] = (char)pBytes[5];
-                    pString[6] = (char)pBytes[6];
-                    pString[7] = (char)pBytes[7];
-                    pString += 8;
-                    pBytes += 8;
-                    byteCount -= 8;
-                }
-                for (int i = 0; i < byteCount; i++)
-                {
-                    pString[i] = (char)pBytes[i];
-                }
-            }
-
-            return s;
-        }
-
-        internal static int GetByteCount(string myString)
-        {
-            return myString.Length;
-        }
-        internal static unsafe void GetBytes(string myString, int charIndex, int charCount, byte[] bytes, int byteIndex)
-        {
-            if (myString.Length == 0)
-            {
-                return;
-            }
-            fixed (byte* bufferPointer = bytes)
-            {
-                byte* newBufferPointer = bufferPointer + byteIndex;
-                int finalIndex = charIndex + charCount;
-                while (charIndex < finalIndex)
-                {
-                    *newBufferPointer++ = (byte)myString[charIndex++];
-                }
-            }
-        }
-        internal static byte[] GetBytes(string myString)
-        {
-            byte[] bytes = new byte[myString.Length];
-            if (myString.Length != 0)
-            {
-                GetBytes(myString, 0, myString.Length, bytes, 0);
-            }
-            return bytes;
-        }
-    }
-}

+ 0 - 92
SocketHttpListener/Net/WebSockets/HttpListenerWebSocketContext.cs

@@ -1,92 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Security.Principal;
-using MediaBrowser.Model.Services;
-
-namespace SocketHttpListener.Net.WebSockets
-{
-    public class HttpListenerWebSocketContext : WebSocketContext
-    {
-        private readonly Uri _requestUri;
-        private readonly QueryParamCollection _headers;
-        private readonly CookieCollection _cookieCollection;
-        private readonly IPrincipal _user;
-        private readonly bool _isAuthenticated;
-        private readonly bool _isLocal;
-        private readonly bool _isSecureConnection;
-
-        private readonly string _origin;
-        private readonly IEnumerable<string> _secWebSocketProtocols;
-        private readonly string _secWebSocketVersion;
-        private readonly string _secWebSocketKey;
-
-        private readonly WebSocket _webSocket;
-
-        internal HttpListenerWebSocketContext(
-            Uri requestUri,
-            QueryParamCollection headers,
-            CookieCollection cookieCollection,
-            IPrincipal user,
-            bool isAuthenticated,
-            bool isLocal,
-            bool isSecureConnection,
-            string origin,
-            IEnumerable<string> secWebSocketProtocols,
-            string secWebSocketVersion,
-            string secWebSocketKey,
-            WebSocket webSocket)
-        {
-            _cookieCollection = new CookieCollection();
-            _cookieCollection.Add(cookieCollection);
-
-            //_headers = new NameValueCollection(headers);
-            _headers = headers;
-            _user = CopyPrincipal(user);
-
-            _requestUri = requestUri;
-            _isAuthenticated = isAuthenticated;
-            _isLocal = isLocal;
-            _isSecureConnection = isSecureConnection;
-            _origin = origin;
-            _secWebSocketProtocols = secWebSocketProtocols;
-            _secWebSocketVersion = secWebSocketVersion;
-            _secWebSocketKey = secWebSocketKey;
-            _webSocket = webSocket;
-        }
-
-        public override Uri RequestUri => _requestUri;
-
-        public override QueryParamCollection Headers => _headers;
-
-        public override string Origin => _origin;
-
-        public override IEnumerable<string> SecWebSocketProtocols => _secWebSocketProtocols;
-
-        public override string SecWebSocketVersion => _secWebSocketVersion;
-
-        public override string SecWebSocketKey => _secWebSocketKey;
-
-        public override CookieCollection CookieCollection => _cookieCollection;
-
-        public override IPrincipal User => _user;
-
-        public override bool IsAuthenticated => _isAuthenticated;
-
-        public override bool IsLocal => _isLocal;
-
-        public override bool IsSecureConnection => _isSecureConnection;
-
-        public override WebSocket WebSocket => _webSocket;
-
-        private static IPrincipal CopyPrincipal(IPrincipal user)
-        {
-            if (user != null)
-            {
-                throw new NotImplementedException();
-            }
-
-            return null;
-        }
-    }
-}

+ 0 - 81
SocketHttpListener/Net/WebSockets/HttpWebSocket.Managed.cs

@@ -1,81 +0,0 @@
-using System;
-using System.Threading.Tasks;
-
-namespace SocketHttpListener.Net.WebSockets
-{
-    internal static partial class HttpWebSocket
-    {
-        private const string SupportedVersion = "13";
-
-        internal static async Task<HttpListenerWebSocketContext> AcceptWebSocketAsyncCore(HttpListenerContext context,
-            string subProtocol,
-            int receiveBufferSize,
-            TimeSpan keepAliveInterval,
-            ArraySegment<byte>? internalBuffer = null)
-        {
-            ValidateOptions(subProtocol, receiveBufferSize, MinSendBufferSize, keepAliveInterval);
-
-            // get property will create a new response if one doesn't exist.
-            HttpListenerResponse response = context.Response;
-            HttpListenerRequest request = context.Request;
-            ValidateWebSocketHeaders(context);
-
-            string secWebSocketVersion = request.Headers[HttpKnownHeaderNames.SecWebSocketVersion];
-
-            // Optional for non-browser client
-            string origin = request.Headers[HttpKnownHeaderNames.Origin];
-
-            string[] secWebSocketProtocols = null;
-            bool shouldSendSecWebSocketProtocolHeader =
-                ProcessWebSocketProtocolHeader(
-                    request.Headers[HttpKnownHeaderNames.SecWebSocketProtocol],
-                    subProtocol,
-                    out var outgoingSecWebSocketProtocolString);
-
-            if (shouldSendSecWebSocketProtocolHeader)
-            {
-                secWebSocketProtocols = new string[] { outgoingSecWebSocketProtocolString };
-                response.Headers.Add(HttpKnownHeaderNames.SecWebSocketProtocol, outgoingSecWebSocketProtocolString);
-            }
-
-            // negotiate the websocket key return value
-            string secWebSocketKey = request.Headers[HttpKnownHeaderNames.SecWebSocketKey];
-            string secWebSocketAccept = HttpWebSocket.GetSecWebSocketAcceptString(secWebSocketKey);
-
-            response.Headers.Add(HttpKnownHeaderNames.Connection, HttpKnownHeaderNames.Upgrade);
-            response.Headers.Add(HttpKnownHeaderNames.Upgrade, WebSocketUpgradeToken);
-            response.Headers.Add(HttpKnownHeaderNames.SecWebSocketAccept, secWebSocketAccept);
-
-            response.StatusCode = (int)HttpStatusCode.SwitchingProtocols; // HTTP 101
-            response.StatusDescription = HttpStatusDescription.Get(HttpStatusCode.SwitchingProtocols);
-
-            var responseStream = response.OutputStream as HttpResponseStream;
-
-            // Send websocket handshake headers
-            await responseStream.WriteWebSocketHandshakeHeadersAsync().ConfigureAwait(false);
-
-            //WebSocket webSocket = WebSocket.CreateFromStream(context.Connection.ConnectedStream, isServer: true, subProtocol, keepAliveInterval);
-            var webSocket = new WebSocket(subProtocol);
-
-            var webSocketContext = new HttpListenerWebSocketContext(
-                                                                request.Url,
-                                                                request.Headers,
-                                                                request.Cookies,
-                                                                context.User,
-                                                                request.IsAuthenticated,
-                                                                request.IsLocal,
-                                                                request.IsSecureConnection,
-                                                                origin,
-                                                                secWebSocketProtocols != null ? secWebSocketProtocols : Array.Empty<string>(),
-                                                                secWebSocketVersion,
-                                                                secWebSocketKey,
-                                                                webSocket);
-
-            webSocket.SetContext(webSocketContext, context.Connection.Close, context.Connection.Stream);
-
-            return webSocketContext;
-        }
-
-        private const bool WebSocketsSupported = true;
-    }
-}

+ 0 - 159
SocketHttpListener/Net/WebSockets/HttpWebSocket.cs

@@ -1,159 +0,0 @@
-using System;
-using System.Diagnostics.CodeAnalysis;
-using System.Security.Cryptography;
-using System.Text;
-using System.Threading;
-
-namespace SocketHttpListener.Net.WebSockets
-{
-    internal static partial class HttpWebSocket
-    {
-        internal const string SecWebSocketKeyGuid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
-        internal const string WebSocketUpgradeToken = "websocket";
-        internal const int DefaultReceiveBufferSize = 16 * 1024;
-        internal const int DefaultClientSendBufferSize = 16 * 1024;
-
-        [SuppressMessage("Microsoft.Security", "CA5350", Justification = "SHA1 used only for hashing purposes, not for crypto.")]
-        internal static string GetSecWebSocketAcceptString(string secWebSocketKey)
-        {
-            string retVal;
-
-            // SHA1 used only for hashing purposes, not for crypto. Check here for FIPS compat.
-            using (var sha1 = SHA1.Create())
-            {
-                string acceptString = string.Concat(secWebSocketKey, HttpWebSocket.SecWebSocketKeyGuid);
-                byte[] toHash = Encoding.UTF8.GetBytes(acceptString);
-                retVal = Convert.ToBase64String(sha1.ComputeHash(toHash));
-            }
-
-            return retVal;
-        }
-
-        // return value here signifies if a Sec-WebSocket-Protocol header should be returned by the server.
-        internal static bool ProcessWebSocketProtocolHeader(string clientSecWebSocketProtocol,
-            string subProtocol,
-            out string acceptProtocol)
-        {
-            acceptProtocol = string.Empty;
-            if (string.IsNullOrEmpty(clientSecWebSocketProtocol))
-            {
-                // client hasn't specified any Sec-WebSocket-Protocol header
-                if (subProtocol != null)
-                {
-                    // If the server specified _anything_ this isn't valid.
-                    throw new WebSocketException("UnsupportedProtocol");
-                }
-                // Treat empty and null from the server as the same thing here, server should not send headers.
-                return false;
-            }
-
-            // here, we know the client specified something and it's non-empty.
-
-            if (subProtocol == null)
-            {
-                // client specified some protocols, server specified 'null'. So server should send headers.
-                return true;
-            }
-
-            // here, we know that the client has specified something, it's not empty
-            // and the server has specified exactly one protocol
-
-            string[] requestProtocols = clientSecWebSocketProtocol.Split(new char[] { ',' },
-                StringSplitOptions.RemoveEmptyEntries);
-            acceptProtocol = subProtocol;
-
-            // client specified protocols, serverOptions has exactly 1 non-empty entry. Check that
-            // this exists in the list the client specified.
-            for (int i = 0; i < requestProtocols.Length; i++)
-            {
-                string currentRequestProtocol = requestProtocols[i].Trim();
-                if (string.Equals(acceptProtocol, currentRequestProtocol, StringComparison.OrdinalIgnoreCase))
-                {
-                    return true;
-                }
-            }
-
-            throw new WebSocketException("net_WebSockets_AcceptUnsupportedProtocol");
-        }
-
-        internal static void ValidateOptions(string subProtocol, int receiveBufferSize, int sendBufferSize, TimeSpan keepAliveInterval)
-        {
-            if (subProtocol != null)
-            {
-                WebSocketValidate.ValidateSubprotocol(subProtocol);
-            }
-
-            if (receiveBufferSize < MinReceiveBufferSize)
-            {
-                throw new ArgumentOutOfRangeException(nameof(receiveBufferSize), "The receiveBufferSize was too small.");
-            }
-
-            if (sendBufferSize < MinSendBufferSize)
-            {
-                throw new ArgumentOutOfRangeException(nameof(sendBufferSize), "The sendBufferSize was too small.");
-            }
-
-            if (receiveBufferSize > MaxBufferSize)
-            {
-                throw new ArgumentOutOfRangeException(nameof(receiveBufferSize), "The receiveBufferSize was too large.");
-            }
-
-            if (sendBufferSize > MaxBufferSize)
-            {
-                throw new ArgumentOutOfRangeException(nameof(sendBufferSize), "The sendBufferSize was too large.");
-            }
-
-            if (keepAliveInterval < Timeout.InfiniteTimeSpan) // -1 millisecond
-            {
-                throw new ArgumentOutOfRangeException(nameof(keepAliveInterval), "The keepAliveInterval was too small.");
-            }
-        }
-
-        internal const int MinSendBufferSize = 16;
-        internal const int MinReceiveBufferSize = 256;
-        internal const int MaxBufferSize = 64 * 1024;
-
-        private static void ValidateWebSocketHeaders(HttpListenerContext context)
-        {
-            if (!WebSocketsSupported)
-            {
-                throw new PlatformNotSupportedException("net_WebSockets_UnsupportedPlatform");
-            }
-
-            if (!context.Request.IsWebSocketRequest)
-            {
-                throw new WebSocketException("net_WebSockets_AcceptNotAWebSocket");
-            }
-
-            string secWebSocketVersion = context.Request.Headers[HttpKnownHeaderNames.SecWebSocketVersion];
-            if (string.IsNullOrEmpty(secWebSocketVersion))
-            {
-                throw new WebSocketException("net_WebSockets_AcceptHeaderNotFound");
-            }
-
-            if (!string.Equals(secWebSocketVersion, SupportedVersion, StringComparison.OrdinalIgnoreCase))
-            {
-                throw new WebSocketException("net_WebSockets_AcceptUnsupportedWebSocketVersion");
-            }
-
-            string secWebSocketKey = context.Request.Headers[HttpKnownHeaderNames.SecWebSocketKey];
-            bool isSecWebSocketKeyInvalid = string.IsNullOrWhiteSpace(secWebSocketKey);
-            if (!isSecWebSocketKeyInvalid)
-            {
-                try
-                {
-                    // key must be 16 bytes then base64-encoded
-                    isSecWebSocketKeyInvalid = Convert.FromBase64String(secWebSocketKey).Length != 16;
-                }
-                catch
-                {
-                    isSecWebSocketKeyInvalid = true;
-                }
-            }
-            if (isSecWebSocketKeyInvalid)
-            {
-                throw new WebSocketException("net_WebSockets_AcceptHeaderNotFound");
-            }
-        }
-    }
-}

+ 0 - 27
SocketHttpListener/Net/WebSockets/WebSocketCloseStatus.cs

@@ -1,27 +0,0 @@
-namespace SocketHttpListener.Net.WebSockets
-{
-    public enum WebSocketCloseStatus
-    {
-        NormalClosure = 1000,
-        EndpointUnavailable = 1001,
-        ProtocolError = 1002,
-        InvalidMessageType = 1003,
-        Empty = 1005,
-        // AbnormalClosure = 1006, // 1006 is reserved and should never be used by user
-        InvalidPayloadData = 1007,
-        PolicyViolation = 1008,
-        MessageTooBig = 1009,
-        MandatoryExtension = 1010,
-        InternalServerError = 1011
-        // TLSHandshakeFailed = 1015, // 1015 is reserved and should never be used by user
-
-        // 0 - 999 Status codes in the range 0-999 are not used.
-        // 1000 - 1999 Status codes in the range 1000-1999 are reserved for definition by this protocol.
-        // 2000 - 2999 Status codes in the range 2000-2999 are reserved for use by extensions.
-        // 3000 - 3999 Status codes in the range 3000-3999 MAY be used by libraries and frameworks. The
-        //             interpretation of these codes is undefined by this protocol. End applications MUST
-        //             NOT use status codes in this range.
-        // 4000 - 4999 Status codes in the range 4000-4999 MAY be used by application code. The interpretation
-        //             of these codes is undefined by this protocol.
-    }
-}

+ 0 - 24
SocketHttpListener/Net/WebSockets/WebSocketContext.cs

@@ -1,24 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Security.Principal;
-using MediaBrowser.Model.Services;
-
-namespace SocketHttpListener.Net.WebSockets
-{
-    public abstract class WebSocketContext
-    {
-        public abstract Uri RequestUri { get; }
-        public abstract QueryParamCollection Headers { get; }
-        public abstract string Origin { get; }
-        public abstract IEnumerable<string> SecWebSocketProtocols { get; }
-        public abstract string SecWebSocketVersion { get; }
-        public abstract string SecWebSocketKey { get; }
-        public abstract CookieCollection CookieCollection { get; }
-        public abstract IPrincipal User { get; }
-        public abstract bool IsAuthenticated { get; }
-        public abstract bool IsLocal { get; }
-        public abstract bool IsSecureConnection { get; }
-        public abstract WebSocket WebSocket { get; }
-    }
-}

+ 0 - 141
SocketHttpListener/Net/WebSockets/WebSocketValidate.cs

@@ -1,141 +0,0 @@
-using System;
-using System.Globalization;
-using System.Text;
-using WebSocketState = System.Net.WebSockets.WebSocketState;
-
-namespace SocketHttpListener.Net.WebSockets
-{
-    internal static partial class WebSocketValidate
-    {
-        internal const int MaxControlFramePayloadLength = 123;
-        private const int CloseStatusCodeAbort = 1006;
-        private const int CloseStatusCodeFailedTLSHandshake = 1015;
-        private const int InvalidCloseStatusCodesFrom = 0;
-        private const int InvalidCloseStatusCodesTo = 999;
-        private const string Separators = "()<>@,;:\\\"/[]?={} ";
-
-        internal static void ThrowIfInvalidState(WebSocketState currentState, bool isDisposed, WebSocketState[] validStates)
-        {
-            string validStatesText = string.Empty;
-
-            if (validStates != null && validStates.Length > 0)
-            {
-                foreach (WebSocketState validState in validStates)
-                {
-                    if (currentState == validState)
-                    {
-                        // Ordering is important to maintain .NET 4.5 WebSocket implementation exception behavior.
-                        if (isDisposed)
-                        {
-                            throw new ObjectDisposedException(nameof(WebSocket));
-                        }
-
-                        return;
-                    }
-                }
-
-                validStatesText = string.Join(", ", validStates);
-            }
-
-            throw new WebSocketException("net_WebSockets_InvalidState");
-        }
-
-        internal static void ValidateSubprotocol(string subProtocol)
-        {
-            if (string.IsNullOrWhiteSpace(subProtocol))
-            {
-                throw new ArgumentException("net_WebSockets_InvalidEmptySubProtocol");
-            }
-
-            string invalidChar = null;
-            int i = 0;
-            while (i < subProtocol.Length)
-            {
-                char ch = subProtocol[i];
-                if (ch < 0x21 || ch > 0x7e)
-                {
-                    invalidChar = string.Format(CultureInfo.InvariantCulture, "[{0}]", (int)ch);
-                    break;
-                }
-
-                if (!char.IsLetterOrDigit(ch) &&
-                    Separators.IndexOf(ch) >= 0)
-                {
-                    invalidChar = ch.ToString();
-                    break;
-                }
-
-                i++;
-            }
-
-            if (invalidChar != null)
-            {
-                throw new ArgumentException("net_WebSockets_InvalidCharInProtocolString");
-            }
-        }
-
-        internal static void ValidateCloseStatus(WebSocketCloseStatus closeStatus, string statusDescription)
-        {
-            if (closeStatus == WebSocketCloseStatus.Empty && !string.IsNullOrEmpty(statusDescription))
-            {
-                throw new ArgumentException("net_WebSockets_ReasonNotNull");
-            }
-
-            int closeStatusCode = (int)closeStatus;
-
-            if ((closeStatusCode >= InvalidCloseStatusCodesFrom &&
-                closeStatusCode <= InvalidCloseStatusCodesTo) ||
-                closeStatusCode == CloseStatusCodeAbort ||
-                closeStatusCode == CloseStatusCodeFailedTLSHandshake)
-            {
-                // CloseStatus 1006 means Aborted - this will never appear on the wire and is reflected by calling WebSocket.Abort
-                throw new ArgumentException("net_WebSockets_InvalidCloseStatusCode");
-            }
-
-            int length = 0;
-            if (!string.IsNullOrEmpty(statusDescription))
-            {
-                length = Encoding.UTF8.GetByteCount(statusDescription);
-            }
-
-            if (length > MaxControlFramePayloadLength)
-            {
-                throw new ArgumentException("net_WebSockets_InvalidCloseStatusDescription");
-            }
-        }
-
-        internal static void ValidateArraySegment(ArraySegment<byte> arraySegment, string parameterName)
-        {
-            if (arraySegment.Array == null)
-            {
-                throw new ArgumentNullException(parameterName + "." + nameof(arraySegment.Array));
-            }
-            if (arraySegment.Offset < 0 || arraySegment.Offset > arraySegment.Array.Length)
-            {
-                throw new ArgumentOutOfRangeException(parameterName + "." + nameof(arraySegment.Offset));
-            }
-            if (arraySegment.Count < 0 || arraySegment.Count > (arraySegment.Array.Length - arraySegment.Offset))
-            {
-                throw new ArgumentOutOfRangeException(parameterName + "." + nameof(arraySegment.Count));
-            }
-        }
-
-        internal static void ValidateBuffer(byte[] buffer, int offset, int count)
-        {
-            if (buffer == null)
-            {
-                throw new ArgumentNullException(nameof(buffer));
-            }
-
-            if (offset < 0 || offset > buffer.Length)
-            {
-                throw new ArgumentOutOfRangeException(nameof(offset));
-            }
-
-            if (count < 0 || count > (buffer.Length - offset))
-            {
-                throw new ArgumentOutOfRangeException(nameof(count));
-            }
-        }
-    }
-}

+ 1 - 2
SocketHttpListener/WebSocket.cs

@@ -4,11 +4,10 @@ using System.Collections.Generic;
 using System.IO;
 using System.IO;
 using System.Net;
 using System.Net;
 using System.Net.Sockets;
 using System.Net.Sockets;
+using System.Net.WebSockets;
 using System.Text;
 using System.Text;
 using System.Threading;
 using System.Threading;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
-using SocketHttpListener.Net.WebSockets;
-using HttpStatusCode = SocketHttpListener.Net.HttpStatusCode;
 using WebSocketState = System.Net.WebSockets.WebSocketState;
 using WebSocketState = System.Net.WebSockets.WebSocketState;
 
 
 namespace SocketHttpListener
 namespace SocketHttpListener