diff --git a/Emby.Server.Implementations/Emby.Server.Implementations.csproj b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
index 230e4892c..d4db5f2fc 100644
--- a/Emby.Server.Implementations/Emby.Server.Implementations.csproj
+++ b/Emby.Server.Implementations/Emby.Server.Implementations.csproj
@@ -9,7 +9,6 @@
-
@@ -40,7 +39,6 @@
-
diff --git a/Emby.Server.Implementations/SocketSharp/SharpWebSocket.cs b/Emby.Server.Implementations/SocketSharp/SharpWebSocket.cs
index 66c5cc334..dcbfb8048 100644
--- a/Emby.Server.Implementations/SocketSharp/SharpWebSocket.cs
+++ b/Emby.Server.Implementations/SocketSharp/SharpWebSocket.cs
@@ -23,9 +23,8 @@ namespace Emby.Server.Implementations.SocketSharp
/// The web socket.
private readonly WebSocket _webSocket;
- private TaskCompletionSource _taskCompletionSource = new TaskCompletionSource();
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
- private bool _disposed = false;
+ private bool _disposed;
public SharpWebSocket(WebSocket socket, ILogger logger)
{
diff --git a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs
index 38d033230..53dce667b 100644
--- a/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs
+++ b/Emby.Server.Implementations/SocketSharp/WebSocketSharpRequest.cs
@@ -11,7 +11,6 @@ using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Primitives;
using Microsoft.Net.Http.Headers;
-using SocketHttpListener.Net;
using IHttpFile = MediaBrowser.Model.Services.IHttpFile;
using IHttpRequest = MediaBrowser.Model.Services.IHttpRequest;
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
diff --git a/MediaBrowser.sln b/MediaBrowser.sln
index 62ae58d73..5edc1a25a 100644
--- a/MediaBrowser.sln
+++ b/MediaBrowser.sln
@@ -1,192 +1,187 @@
-Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.26730.3
-MinimumVisualStudioVersion = 10.0.40219.1
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Common", "MediaBrowser.Common\MediaBrowser.Common.csproj", "{9142EEFA-7570-41E1-BFCC-468BB571AF2F}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Model", "MediaBrowser.Model\MediaBrowser.Model.csproj", "{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.WebDashboard", "MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj", "{5624B7B5-B5A7-41D8-9F10-CC5611109619}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Providers", "MediaBrowser.Providers\MediaBrowser.Providers.csproj", "{442B5058-DCAF-4263-BB6A-F21E31120A1B}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenSubtitlesHandler", "OpenSubtitlesHandler\OpenSubtitlesHandler.csproj", "{4A4402D4-E910-443B-B8FC-2C18286A2CA0}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.XbmcMetadata", "MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj", "{23499896-B135-4527-8574-C26E926EA99E}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.LocalMetadata", "MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj", "{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Drawing", "Emby.Drawing\Emby.Drawing.csproj", "{08FFF49B-F175-4807-A2B5-73B0EBD9F716}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Photos", "Emby.Photos\Emby.Photos.csproj", "{89AB4548-770D-41FD-A891-8DAFF44F452C}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DvdLib", "DvdLib\DvdLib.csproj", "{713F42B5-878E-499D-A878-E4C652B1D5E8}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BDInfo", "BDInfo\BDInfo.csproj", "{88AE38DF-19D7-406F-A6A9-09527719A21E}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Server.Implementations", "Emby.Server.Implementations\Emby.Server.Implementations.csproj", "{E383961B-9356-4D5D-8233-9A1079D03055}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSSDP", "RSSDP\RSSDP.csproj", "{21002819-C39A-4D3E-BE83-2A276A77FB1F}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Dlna", "Emby.Dlna\Emby.Dlna.csproj", "{805844AB-E92F-45E6-9D99-4F6D48D129A5}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Nat", "Mono.Nat\Mono.Nat.csproj", "{CB7F2326-6497-4A3D-BA03-48513B17A7BE}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SocketHttpListener", "SocketHttpListener\SocketHttpListener.csproj", "{1D74413B-E7CF-455B-B021-F52BDF881542}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Notifications", "Emby.Notifications\Emby.Notifications.csproj", "{2E030C33-6923-4530-9E54-FA29FA6AD1A9}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Naming", "Emby.Naming\Emby.Naming.csproj", "{E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.XmlTv", "Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj", "{6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IsoMounter", "Emby.IsoMounting\IsoMounter\IsoMounter.csproj", "{9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{960295EE-4AF4-4440-A525-B4C295B01A61}"
-EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Server", "Jellyfin.Server\Jellyfin.Server.csproj", "{07E39F42-A2C6-4B32-AF8C-725F957A73FF}"
-EndProject
-Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{41093F42-C7CC-4D07-956B-6182CBEDE2EC}"
- ProjectSection(SolutionItems) = preProject
- .editorconfig = .editorconfig
- SharedVersion.cs = SharedVersion.cs
- EndProjectSection
-EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Jellyfin.Drawing.Skia", "Jellyfin.Drawing.Skia\Jellyfin.Drawing.Skia.csproj", "{154872D9-6C12-4007-96E3-8F70A58386CE}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.Build.0 = Release|Any CPU
- {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.Build.0 = Release|Any CPU
- {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.Build.0 = Release|Any CPU
- {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.Build.0 = Release|Any CPU
- {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.Build.0 = Release|Any CPU
- {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU
- {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.Build.0 = Release|Any CPU
- {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.Build.0 = Release|Any CPU
- {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.Build.0 = Release|Any CPU
- {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.Build.0 = Release|Any CPU
- {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.Build.0 = Release|Any CPU
- {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Any CPU.Build.0 = Release|Any CPU
- {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Any CPU.Build.0 = Release|Any CPU
- {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Any CPU.Build.0 = Release|Any CPU
- {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.Build.0 = Release|Any CPU
- {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.Build.0 = Release|Any CPU
- {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Any CPU.Build.0 = Release|Any CPU
- {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {1D74413B-E7CF-455B-B021-F52BDF881542}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {1D74413B-E7CF-455B-B021-F52BDF881542}.Release|Any CPU.Build.0 = Release|Any CPU
- {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Any CPU.Build.0 = Release|Any CPU
- {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Any CPU.Build.0 = Release|Any CPU
- {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.Build.0 = Release|Any CPU
- {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.Build.0 = Release|Any CPU
- {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Any CPU.Build.0 = Release|Any CPU
- {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.Build.0 = Release|Any CPU
- {154872D9-6C12-4007-96E3-8F70A58386CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {154872D9-6C12-4007-96E3-8F70A58386CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {154872D9-6C12-4007-96E3-8F70A58386CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {154872D9-6C12-4007-96E3-8F70A58386CE}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
- GlobalSection(ExtensibilityGlobals) = postSolution
- SolutionGuid = {3448830C-EBDC-426C-85CD-7BBB9651A7FE}
- EndGlobalSection
- GlobalSection(AutomaticVersions) = postSolution
- UpdateAssemblyVersion = True
- UpdateAssemblyFileVersion = True
- UpdateAssemblyInfoVersion = True
- AssemblyVersionSettings = None.None.None.None
- AssemblyFileVersionSettings = None.None.None.None
- AssemblyInfoVersionSettings = None.None.None.None
- UpdatePackageVersion = False
- AssemblyInfoVersionType = SettingsVersion
- InheritWinAppVersionFrom = None
- EndGlobalSection
- GlobalSection(MonoDevelopProperties) = preSolution
- Policies = $0
- $0.StandardHeader = $1
- $1.Text = @### This header should be used to start new files.\n### It provides an explicit per-file license reference that should be present on all new files.\n### To use this header, delete these lines and the following empty line, modify to\n### the proper full path, and then add new code following the header and a single empty line.\n\n// ${FileName}\n// Part of the Jellyfin project (https://jellyfin.media)\n//\n// All copyright belongs to the Jellyfin contributors; a full list can\n// be found in the file CONTRIBUTORS.md\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, version 2.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n
- $0.DotNetNamingPolicy = $2
- $2.DirectoryNamespaceAssociation = PrefixedHierarchical
- EndGlobalSection
-EndGlobal
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26730.3
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Controller", "MediaBrowser.Controller\MediaBrowser.Controller.csproj", "{17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Api", "MediaBrowser.Api\MediaBrowser.Api.csproj", "{4FD51AC5-2C16-4308-A993-C3A84F3B4582}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Common", "MediaBrowser.Common\MediaBrowser.Common.csproj", "{9142EEFA-7570-41E1-BFCC-468BB571AF2F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Model", "MediaBrowser.Model\MediaBrowser.Model.csproj", "{7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.WebDashboard", "MediaBrowser.WebDashboard\MediaBrowser.WebDashboard.csproj", "{5624B7B5-B5A7-41D8-9F10-CC5611109619}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.Providers", "MediaBrowser.Providers\MediaBrowser.Providers.csproj", "{442B5058-DCAF-4263-BB6A-F21E31120A1B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenSubtitlesHandler", "OpenSubtitlesHandler\OpenSubtitlesHandler.csproj", "{4A4402D4-E910-443B-B8FC-2C18286A2CA0}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.XbmcMetadata", "MediaBrowser.XbmcMetadata\MediaBrowser.XbmcMetadata.csproj", "{23499896-B135-4527-8574-C26E926EA99E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.LocalMetadata", "MediaBrowser.LocalMetadata\MediaBrowser.LocalMetadata.csproj", "{7EF9F3E0-697D-42F3-A08F-19DEB5F84392}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Drawing", "Emby.Drawing\Emby.Drawing.csproj", "{08FFF49B-F175-4807-A2B5-73B0EBD9F716}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Photos", "Emby.Photos\Emby.Photos.csproj", "{89AB4548-770D-41FD-A891-8DAFF44F452C}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DvdLib", "DvdLib\DvdLib.csproj", "{713F42B5-878E-499D-A878-E4C652B1D5E8}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BDInfo", "BDInfo\BDInfo.csproj", "{88AE38DF-19D7-406F-A6A9-09527719A21E}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Server.Implementations", "Emby.Server.Implementations\Emby.Server.Implementations.csproj", "{E383961B-9356-4D5D-8233-9A1079D03055}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RSSDP", "RSSDP\RSSDP.csproj", "{21002819-C39A-4D3E-BE83-2A276A77FB1F}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Dlna", "Emby.Dlna\Emby.Dlna.csproj", "{805844AB-E92F-45E6-9D99-4F6D48D129A5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Mono.Nat", "Mono.Nat\Mono.Nat.csproj", "{CB7F2326-6497-4A3D-BA03-48513B17A7BE}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Notifications", "Emby.Notifications\Emby.Notifications.csproj", "{2E030C33-6923-4530-9E54-FA29FA6AD1A9}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.Naming", "Emby.Naming\Emby.Naming.csproj", "{E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Emby.XmlTv", "Emby.XmlTv\Emby.XmlTv\Emby.XmlTv.csproj", "{6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IsoMounter", "Emby.IsoMounting\IsoMounter\IsoMounter.csproj", "{9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MediaBrowser.MediaEncoding", "MediaBrowser.MediaEncoding\MediaBrowser.MediaEncoding.csproj", "{960295EE-4AF4-4440-A525-B4C295B01A61}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Server", "Jellyfin.Server\Jellyfin.Server.csproj", "{07E39F42-A2C6-4B32-AF8C-725F957A73FF}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{41093F42-C7CC-4D07-956B-6182CBEDE2EC}"
+ ProjectSection(SolutionItems) = preProject
+ .editorconfig = .editorconfig
+ SharedVersion.cs = SharedVersion.cs
+ EndProjectSection
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Jellyfin.Drawing.Skia", "Jellyfin.Drawing.Skia\Jellyfin.Drawing.Skia.csproj", "{154872D9-6C12-4007-96E3-8F70A58386CE}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {17E1F4E6-8ABD-4FE5-9ECF-43D4B6087BA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4FD51AC5-2C16-4308-A993-C3A84F3B4582}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9142EEFA-7570-41E1-BFCC-468BB571AF2F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7EEEB4BB-F3E8-48FC-B4C5-70F0FFF8329B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {5624B7B5-B5A7-41D8-9F10-CC5611109619}.Release|Any CPU.Build.0 = Release|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {442B5058-DCAF-4263-BB6A-F21E31120A1B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {4A4402D4-E910-443B-B8FC-2C18286A2CA0}.Release|Any CPU.Build.0 = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {23499896-B135-4527-8574-C26E926EA99E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7EF9F3E0-697D-42F3-A08F-19DEB5F84392}.Release|Any CPU.Build.0 = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {08FFF49B-F175-4807-A2B5-73B0EBD9F716}.Release|Any CPU.Build.0 = Release|Any CPU
+ {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {89AB4548-770D-41FD-A891-8DAFF44F452C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {89AB4548-770D-41FD-A891-8DAFF44F452C}.Release|Any CPU.Build.0 = Release|Any CPU
+ {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {713F42B5-878E-499D-A878-E4C652B1D5E8}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {713F42B5-878E-499D-A878-E4C652B1D5E8}.Release|Any CPU.Build.0 = Release|Any CPU
+ {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {88AE38DF-19D7-406F-A6A9-09527719A21E}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {88AE38DF-19D7-406F-A6A9-09527719A21E}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E383961B-9356-4D5D-8233-9A1079D03055}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E383961B-9356-4D5D-8233-9A1079D03055}.Release|Any CPU.Build.0 = Release|Any CPU
+ {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {21002819-C39A-4D3E-BE83-2A276A77FB1F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {805844AB-E92F-45E6-9D99-4F6D48D129A5}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CB7F2326-6497-4A3D-BA03-48513B17A7BE}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2E030C33-6923-4530-9E54-FA29FA6AD1A9}.Release|Any CPU.Build.0 = Release|Any CPU
+ {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {E5AF7B26-2239-4CE0-B477-0AA2018EDAA2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6EAFA7F0-8A82-49E6-B2FA-086C5CAEA95B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {9BA471D2-6DB9-4DBF-B3A0-9FB3171F94A6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {960295EE-4AF4-4440-A525-B4C295B01A61}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {960295EE-4AF4-4440-A525-B4C295B01A61}.Release|Any CPU.Build.0 = Release|Any CPU
+ {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {07E39F42-A2C6-4B32-AF8C-725F957A73FF}.Release|Any CPU.Build.0 = Release|Any CPU
+ {154872D9-6C12-4007-96E3-8F70A58386CE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {154872D9-6C12-4007-96E3-8F70A58386CE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {154872D9-6C12-4007-96E3-8F70A58386CE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {154872D9-6C12-4007-96E3-8F70A58386CE}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+ GlobalSection(ExtensibilityGlobals) = postSolution
+ SolutionGuid = {3448830C-EBDC-426C-85CD-7BBB9651A7FE}
+ EndGlobalSection
+ GlobalSection(AutomaticVersions) = postSolution
+ UpdateAssemblyVersion = True
+ UpdateAssemblyFileVersion = True
+ UpdateAssemblyInfoVersion = True
+ AssemblyVersionSettings = None.None.None.None
+ AssemblyFileVersionSettings = None.None.None.None
+ AssemblyInfoVersionSettings = None.None.None.None
+ UpdatePackageVersion = False
+ AssemblyInfoVersionType = SettingsVersion
+ InheritWinAppVersionFrom = None
+ EndGlobalSection
+ GlobalSection(MonoDevelopProperties) = preSolution
+ Policies = $0
+ $0.StandardHeader = $1
+ $1.Text = @### This header should be used to start new files.\n### It provides an explicit per-file license reference that should be present on all new files.\n### To use this header, delete these lines and the following empty line, modify to\n### the proper full path, and then add new code following the header and a single empty line.\n\n// ${FileName}\n// Part of the Jellyfin project (https://jellyfin.media)\n//\n// All copyright belongs to the Jellyfin contributors; a full list can\n// be found in the file CONTRIBUTORS.md\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, version 2.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see .\n
+ $0.DotNetNamingPolicy = $2
+ $2.DirectoryNamespaceAssociation = PrefixedHierarchical
+ EndGlobalSection
+EndGlobal
diff --git a/SocketHttpListener/ByteOrder.cs b/SocketHttpListener/ByteOrder.cs
deleted file mode 100644
index c04150c74..000000000
--- a/SocketHttpListener/ByteOrder.cs
+++ /dev/null
@@ -1,17 +0,0 @@
-namespace SocketHttpListener
-{
- ///
- /// Contains the values that indicate whether the byte order is a Little-endian or Big-endian.
- ///
- public enum ByteOrder : byte
- {
- ///
- /// Indicates a Little-endian.
- ///
- Little,
- ///
- /// Indicates a Big-endian.
- ///
- Big
- }
-}
diff --git a/SocketHttpListener/CloseEventArgs.cs b/SocketHttpListener/CloseEventArgs.cs
deleted file mode 100644
index c6460fd23..000000000
--- a/SocketHttpListener/CloseEventArgs.cs
+++ /dev/null
@@ -1,79 +0,0 @@
-using System;
-using System.Text;
-
-namespace SocketHttpListener
-{
- ///
- /// Contains the event data associated with a event.
- ///
- ///
- /// A event occurs when the WebSocket connection has been closed.
- /// If you would like to get the reason for the close, you should access the or
- /// property.
- ///
- public class CloseEventArgs : EventArgs
- {
- #region Private Fields
-
- private bool _clean;
- private ushort _code;
- private string _reason;
-
- #endregion
-
- #region Internal Constructors
-
- internal CloseEventArgs(PayloadData payload)
- {
- var data = payload.ApplicationData;
- var len = data.Length;
- _code = len > 1
- ? data.SubArray(0, 2).ToUInt16(ByteOrder.Big)
- : (ushort)CloseStatusCode.NoStatusCode;
-
- _reason = len > 2
- ? GetUtf8String(data.SubArray(2, len - 2))
- : string.Empty;
- }
-
- private static string GetUtf8String(byte[] bytes)
- {
- return Encoding.UTF8.GetString(bytes, 0, bytes.Length);
- }
-
- #endregion
-
- #region Public Properties
-
- ///
- /// Gets the status code for the close.
- ///
- ///
- /// A that represents the status code for the close if any.
- ///
- public ushort Code => _code;
-
- ///
- /// Gets the reason for the close.
- ///
- ///
- /// A that represents the reason for the close if any.
- ///
- public string Reason => _reason;
-
- ///
- /// Gets a value indicating whether the WebSocket connection has been closed cleanly.
- ///
- ///
- /// true if the WebSocket connection has been closed cleanly; otherwise, false.
- ///
- public bool WasClean
- {
- get => _clean;
-
- internal set => _clean = value;
- }
-
- #endregion
- }
-}
diff --git a/SocketHttpListener/CloseStatusCode.cs b/SocketHttpListener/CloseStatusCode.cs
deleted file mode 100644
index 428595bb0..000000000
--- a/SocketHttpListener/CloseStatusCode.cs
+++ /dev/null
@@ -1,94 +0,0 @@
-namespace SocketHttpListener
-{
- ///
- /// Contains the values of the status code for the WebSocket connection close.
- ///
- ///
- ///
- /// The values of the status code are defined in
- /// Section 7.4
- /// of RFC 6455.
- ///
- ///
- /// "Reserved value" must not be set as a status code in a close control frame
- /// by an endpoint. It's designated for use in applications expecting a status
- /// code to indicate that the connection was closed due to the system grounds.
- ///
- ///
- public enum CloseStatusCode : ushort
- {
- ///
- /// Equivalent to close status 1000.
- /// Indicates a normal close.
- ///
- Normal = 1000,
- ///
- /// Equivalent to close status 1001.
- /// Indicates that an endpoint is going away.
- ///
- Away = 1001,
- ///
- /// Equivalent to close status 1002.
- /// Indicates that an endpoint is terminating the connection due to a protocol error.
- ///
- ProtocolError = 1002,
- ///
- /// Equivalent to close status 1003.
- /// Indicates that an endpoint is terminating the connection because it has received
- /// an unacceptable type message.
- ///
- IncorrectData = 1003,
- ///
- /// Equivalent to close status 1004.
- /// Still undefined. Reserved value.
- ///
- Undefined = 1004,
- ///
- /// Equivalent to close status 1005.
- /// Indicates that no status code was actually present. Reserved value.
- ///
- NoStatusCode = 1005,
- ///
- /// Equivalent to close status 1006.
- /// Indicates that the connection was closed abnormally. Reserved value.
- ///
- Abnormal = 1006,
- ///
- /// Equivalent to close status 1007.
- /// Indicates that an endpoint is terminating the connection because it has received
- /// a message that contains a data that isn't consistent with the type of the message.
- ///
- InconsistentData = 1007,
- ///
- /// Equivalent to close status 1008.
- /// Indicates that an endpoint is terminating the connection because it has received
- /// a message that violates its policy.
- ///
- PolicyViolation = 1008,
- ///
- /// Equivalent to close status 1009.
- /// Indicates that an endpoint is terminating the connection because it has received
- /// a message that is too big to process.
- ///
- TooBig = 1009,
- ///
- /// Equivalent to close status 1010.
- /// Indicates that the client is terminating the connection because it has expected
- /// the server to negotiate one or more extension, but the server didn't return them
- /// in the handshake response.
- ///
- IgnoreExtension = 1010,
- ///
- /// Equivalent to close status 1011.
- /// Indicates that the server is terminating the connection because it has encountered
- /// an unexpected condition that prevented it from fulfilling the request.
- ///
- ServerError = 1011,
- ///
- /// Equivalent to close status 1015.
- /// Indicates that the connection was closed due to a failure to perform a TLS handshake.
- /// Reserved value.
- ///
- TlsHandshakeFailure = 1015
- }
-}
diff --git a/SocketHttpListener/CompressionMethod.cs b/SocketHttpListener/CompressionMethod.cs
deleted file mode 100644
index d6bcd63d8..000000000
--- a/SocketHttpListener/CompressionMethod.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace SocketHttpListener
-{
- ///
- /// Contains the values of the compression method used to compress the message on the WebSocket
- /// connection.
- ///
- ///
- /// The values of the compression method are defined in
- /// Compression
- /// Extensions for WebSocket.
- ///
- public enum CompressionMethod : byte
- {
- ///
- /// Indicates non compression.
- ///
- None,
- ///
- /// Indicates using DEFLATE.
- ///
- Deflate
- }
-}
diff --git a/SocketHttpListener/ErrorEventArgs.cs b/SocketHttpListener/ErrorEventArgs.cs
deleted file mode 100644
index 9502d2a15..000000000
--- a/SocketHttpListener/ErrorEventArgs.cs
+++ /dev/null
@@ -1,42 +0,0 @@
-using System;
-
-namespace SocketHttpListener
-{
- ///
- /// Contains the event data associated with a event.
- ///
- ///
- /// A event occurs when the gets an error.
- /// If you would like to get the error message, you should access the
- /// property.
- ///
- public class ErrorEventArgs : EventArgs
- {
- #region Private Fields
-
- private string _message;
-
- #endregion
-
- #region Internal Constructors
-
- internal ErrorEventArgs(string message)
- {
- _message = message;
- }
-
- #endregion
-
- #region Public Properties
-
- ///
- /// Gets the error message.
- ///
- ///
- /// A that represents the error message.
- ///
- public string Message => _message;
-
- #endregion
- }
-}
diff --git a/SocketHttpListener/Ext.cs b/SocketHttpListener/Ext.cs
deleted file mode 100644
index 697c5d5b7..000000000
--- a/SocketHttpListener/Ext.cs
+++ /dev/null
@@ -1,946 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.IO.Compression;
-using System.Net;
-using System.Text;
-using System.Threading.Tasks;
-using MediaBrowser.Model.Services;
-using WebSocketState = System.Net.WebSockets.WebSocketState;
-
-namespace SocketHttpListener
-{
- ///
- /// Provides a set of static methods for the websocket-sharp.
- ///
- public static class Ext
- {
- #region Private Const Fields
-
- private const string _tspecials = "()<>@,;:\\\"/[]?={} \t";
-
- #endregion
-
- #region Private Methods
-
- private static MemoryStream compress(this Stream stream)
- {
- var output = new MemoryStream();
- if (stream.Length == 0)
- return output;
-
- stream.Position = 0;
- using (var ds = new DeflateStream(output, CompressionMode.Compress, true))
- {
- stream.CopyTo(ds);
- //ds.Close(); // "BFINAL" set to 1.
- output.Position = 0;
-
- return output;
- }
- }
-
- private static byte[] decompress(this byte[] value)
- {
- if (value.Length == 0)
- return value;
-
- using (var input = new MemoryStream(value))
- {
- return input.decompressToArray();
- }
- }
-
- private static MemoryStream decompress(this Stream stream)
- {
- var output = new MemoryStream();
- if (stream.Length == 0)
- return output;
-
- stream.Position = 0;
- using (var ds = new DeflateStream(stream, CompressionMode.Decompress, true))
- {
- ds.CopyTo(output, true);
- return output;
- }
- }
-
- private static byte[] decompressToArray(this Stream stream)
- {
- using (var decomp = stream.decompress())
- {
- return decomp.ToArray();
- }
- }
-
- private static async Task ReadBytesAsync(this Stream stream, byte[] buffer, int offset, int length)
- {
- var len = await stream.ReadAsync(buffer, offset, length).ConfigureAwait(false);
- if (len < 1)
- return buffer.SubArray(0, offset);
-
- var tmp = 0;
- while (len < length)
- {
- tmp = await stream.ReadAsync(buffer, offset + len, length - len).ConfigureAwait(false);
- if (tmp < 1)
- {
- break;
- }
-
- len += tmp;
- }
-
- return len < length
- ? buffer.SubArray(0, offset + len)
- : buffer;
- }
-
- private static async Task ReadBytesAsync(this Stream stream, byte[] buffer, int offset, int length, Stream dest)
- {
- var bytes = await stream.ReadBytesAsync(buffer, offset, length).ConfigureAwait(false);
- var len = bytes.Length;
- dest.Write(bytes, 0, len);
-
- return len == offset + length;
- }
-
- #endregion
-
- #region Internal Methods
-
- internal static async Task AppendAsync(this ushort code, string reason)
- {
- using (var buffer = new MemoryStream())
- {
- var tmp = code.ToByteArrayInternally(ByteOrder.Big);
- await buffer.WriteAsync(tmp, 0, 2).ConfigureAwait(false);
- if (reason != null && reason.Length > 0)
- {
- tmp = Encoding.UTF8.GetBytes(reason);
- await buffer.WriteAsync(tmp, 0, tmp.Length).ConfigureAwait(false);
- }
-
- return buffer.ToArray();
- }
- }
-
- internal static string CheckIfClosable(this WebSocketState state)
- {
- return state == WebSocketState.CloseSent
- ? "While closing the WebSocket connection."
- : state == WebSocketState.Closed
- ? "The WebSocket connection has already been closed."
- : null;
- }
-
- internal static string CheckIfOpen(this WebSocketState state)
- {
- return state == WebSocketState.Connecting
- ? "A WebSocket connection isn't established."
- : state == WebSocketState.CloseSent
- ? "While closing the WebSocket connection."
- : state == WebSocketState.Closed
- ? "The WebSocket connection has already been closed."
- : null;
- }
-
- internal static string CheckIfValidControlData(this byte[] data, string paramName)
- {
- return data.Length > 125
- ? string.Format("'{0}' length must be less.", paramName)
- : null;
- }
-
- internal static Stream Compress(this Stream stream, CompressionMethod method)
- {
- return method == CompressionMethod.Deflate
- ? stream.compress()
- : stream;
- }
-
- internal static bool Contains(this IEnumerable source, Func condition)
- {
- foreach (T elm in source)
- if (condition(elm))
- return true;
-
- return false;
- }
-
- internal static void CopyTo(this Stream src, Stream dest, bool setDefaultPosition)
- {
- var readLen = 0;
- var bufferLen = 256;
- var buffer = new byte[bufferLen];
- while ((readLen = src.Read(buffer, 0, bufferLen)) > 0)
- {
- dest.Write(buffer, 0, readLen);
- }
-
- if (setDefaultPosition)
- dest.Position = 0;
- }
-
- internal static byte[] Decompress(this byte[] value, CompressionMethod method)
- {
- return method == CompressionMethod.Deflate
- ? value.decompress()
- : value;
- }
-
- internal static byte[] DecompressToArray(this Stream stream, CompressionMethod method)
- {
- return method == CompressionMethod.Deflate
- ? stream.decompressToArray()
- : stream.ToByteArray();
- }
-
- ///
- /// Determines whether the specified equals the specified ,
- /// and invokes the specified Action<int> delegate at the same time.
- ///
- ///
- /// true if equals ;
- /// otherwise, false.
- ///
- ///
- /// An to compare.
- ///
- ///
- /// A to compare.
- ///
- ///
- /// An Action<int> delegate that references the method(s) called at
- /// the same time as comparing. An parameter to pass to
- /// the method(s) is .
- ///
- ///
- /// isn't between 0 and 255.
- ///
- internal static bool EqualsWith(this int value, char c, Action action)
- {
- if (value < 0 || value > 255)
- throw new ArgumentOutOfRangeException(nameof(value));
-
- action(value);
- return value == c - 0;
- }
-
- internal static string GetMessage(this CloseStatusCode code)
- {
- return code == CloseStatusCode.ProtocolError
- ? "A WebSocket protocol error has occurred."
- : code == CloseStatusCode.IncorrectData
- ? "An incorrect data has been received."
- : code == CloseStatusCode.Abnormal
- ? "An exception has occurred."
- : code == CloseStatusCode.InconsistentData
- ? "An inconsistent data has been received."
- : code == CloseStatusCode.PolicyViolation
- ? "A policy violation has occurred."
- : code == CloseStatusCode.TooBig
- ? "A too big data has been received."
- : code == CloseStatusCode.IgnoreExtension
- ? "WebSocket client did not receive expected extension(s)."
- : code == CloseStatusCode.ServerError
- ? "WebSocket server got an internal error."
- : code == CloseStatusCode.TlsHandshakeFailure
- ? "An error has occurred while handshaking."
- : string.Empty;
- }
-
- internal static string GetNameInternal(this string nameAndValue, string separator)
- {
- var i = nameAndValue.IndexOf(separator);
- return i > 0
- ? nameAndValue.Substring(0, i).Trim()
- : null;
- }
-
- internal static string GetValueInternal(this string nameAndValue, string separator)
- {
- var i = nameAndValue.IndexOf(separator);
- return i >= 0 && i < nameAndValue.Length - 1
- ? nameAndValue.Substring(i + 1).Trim()
- : null;
- }
-
- internal static bool IsCompressionExtension(this string value, CompressionMethod method)
- {
- return value.StartsWith(method.ToExtensionString());
- }
-
- internal static bool IsPortNumber(this int value)
- {
- return value > 0 && value < 65536;
- }
-
- internal static bool IsReserved(this ushort code)
- {
- return code == (ushort)CloseStatusCode.Undefined ||
- code == (ushort)CloseStatusCode.NoStatusCode ||
- code == (ushort)CloseStatusCode.Abnormal ||
- code == (ushort)CloseStatusCode.TlsHandshakeFailure;
- }
-
- internal static bool IsReserved(this CloseStatusCode code)
- {
- return code == CloseStatusCode.Undefined ||
- code == CloseStatusCode.NoStatusCode ||
- code == CloseStatusCode.Abnormal ||
- code == CloseStatusCode.TlsHandshakeFailure;
- }
-
- internal static bool IsText(this string value)
- {
- var len = value.Length;
- for (var i = 0; i < len; i++)
- {
- char c = value[i];
- if (c < 0x20 && !"\r\n\t".Contains(c))
- return false;
-
- if (c == 0x7f)
- return false;
-
- if (c == '\n' && ++i < len)
- {
- c = value[i];
- if (!" \t".Contains(c))
- return false;
- }
- }
-
- return true;
- }
-
- internal static bool IsToken(this string value)
- {
- foreach (char c in value)
- if (c < 0x20 || c >= 0x7f || _tspecials.Contains(c))
- return false;
-
- return true;
- }
-
- internal static string Quote(this string value)
- {
- return value.IsToken()
- ? value
- : string.Format("\"{0}\"", value.Replace("\"", "\\\""));
- }
-
- internal static Task ReadBytesAsync(this Stream stream, int length)
- => stream.ReadBytesAsync(new byte[length], 0, length);
-
- internal static async Task ReadBytesAsync(this Stream stream, long length, int bufferLength)
- {
- using (var result = new MemoryStream())
- {
- var count = length / bufferLength;
- var rem = (int)(length % bufferLength);
-
- var buffer = new byte[bufferLength];
- var end = false;
- for (long i = 0; i < count; i++)
- {
- if (!await stream.ReadBytesAsync(buffer, 0, bufferLength, result).ConfigureAwait(false))
- {
- end = true;
- break;
- }
- }
-
- if (!end && rem > 0)
- {
- await stream.ReadBytesAsync(new byte[rem], 0, rem, result).ConfigureAwait(false);
- }
-
- return result.ToArray();
- }
- }
-
- internal static string RemovePrefix(this string value, params string[] prefixes)
- {
- var i = 0;
- foreach (var prefix in prefixes)
- {
- if (value.StartsWith(prefix))
- {
- i = prefix.Length;
- break;
- }
- }
-
- return i > 0
- ? value.Substring(i)
- : value;
- }
-
- internal static T[] Reverse(this T[] array)
- {
- var len = array.Length;
- T[] reverse = new T[len];
-
- var end = len - 1;
- for (var i = 0; i <= end; i++)
- reverse[i] = array[end - i];
-
- return reverse;
- }
-
- internal static IEnumerable SplitHeaderValue(
- this string value, params char[] separator)
- {
- var len = value.Length;
- var separators = new string(separator);
-
- var buffer = new StringBuilder(32);
- var quoted = false;
- var escaped = false;
-
- char c;
- for (var i = 0; i < len; i++)
- {
- c = value[i];
- if (c == '"')
- {
- if (escaped)
- escaped = !escaped;
- else
- quoted = !quoted;
- }
- else if (c == '\\')
- {
- if (i < len - 1 && value[i + 1] == '"')
- escaped = true;
- }
- else if (separators.Contains(c))
- {
- if (!quoted)
- {
- yield return buffer.ToString();
- buffer.Length = 0;
-
- continue;
- }
- }
- else
- {
- }
-
- buffer.Append(c);
- }
-
- if (buffer.Length > 0)
- yield return buffer.ToString();
- }
-
- internal static byte[] ToByteArray(this Stream stream)
- {
- using (var output = new MemoryStream())
- {
- stream.Position = 0;
- stream.CopyTo(output);
-
- return output.ToArray();
- }
- }
-
- internal static byte[] ToByteArrayInternally(this ushort value, ByteOrder order)
- {
- var bytes = BitConverter.GetBytes(value);
- if (!order.IsHostOrder())
- Array.Reverse(bytes);
-
- return bytes;
- }
-
- internal static byte[] ToByteArrayInternally(this ulong value, ByteOrder order)
- {
- var bytes = BitConverter.GetBytes(value);
- if (!order.IsHostOrder())
- Array.Reverse(bytes);
-
- return bytes;
- }
-
- internal static string ToExtensionString(
- this CompressionMethod method, params string[] parameters)
- {
- if (method == CompressionMethod.None)
- return string.Empty;
-
- var m = string.Format("permessage-{0}", method.ToString().ToLowerInvariant());
- if (parameters == null || parameters.Length == 0)
- return m;
-
- return string.Format("{0}; {1}", m, parameters.ToString("; "));
- }
-
- internal static ushort ToUInt16(this byte[] src, ByteOrder srcOrder)
- {
- src.ToHostOrder(srcOrder);
- return BitConverter.ToUInt16(src, 0);
- }
-
- internal static ulong ToUInt64(this byte[] src, ByteOrder srcOrder)
- {
- src.ToHostOrder(srcOrder);
- return BitConverter.ToUInt64(src, 0);
- }
-
- internal static string TrimEndSlash(this string value)
- {
- value = value.TrimEnd('/');
- return value.Length > 0
- ? value
- : "/";
- }
-
- internal static string Unquote(this string value)
- {
- var start = value.IndexOf('\"');
- var end = value.LastIndexOf('\"');
- if (start < end)
- value = value.Substring(start + 1, end - start - 1).Replace("\\\"", "\"");
-
- return value.Trim();
- }
-
- internal static void WriteBytes(this Stream stream, byte[] value)
- {
- using (var src = new MemoryStream(value))
- {
- src.CopyTo(stream);
- }
- }
-
- #endregion
-
- #region Public Methods
-
- ///
- /// Determines whether the specified contains any of characters
- /// in the specified array of .
- ///
- ///
- /// true if contains any of ;
- /// otherwise, false.
- ///
- ///
- /// A to test.
- ///
- ///
- /// An array of that contains characters to find.
- ///
- public static bool Contains(this string value, params char[] chars)
- {
- return chars == null || chars.Length == 0
- ? true
- : value == null || value.Length == 0
- ? false
- : value.IndexOfAny(chars) != -1;
- }
-
- ///
- /// Determines whether the specified contains the entry
- /// with the specified .
- ///
- ///
- /// true if contains the entry
- /// with ; otherwise, false.
- ///
- ///
- /// A to test.
- ///
- ///
- /// A that represents the key of the entry to find.
- ///
- public static bool Contains(this QueryParamCollection collection, string name)
- {
- return collection == null || collection.Count == 0
- ? false
- : collection[name] != null;
- }
-
- ///
- /// Determines whether the specified contains the entry
- /// with the specified both and .
- ///
- ///
- /// true if contains the entry
- /// with both and ;
- /// otherwise, false.
- ///
- ///
- /// A to test.
- ///
- ///
- /// A that represents the key of the entry to find.
- ///
- ///
- /// A that represents the value of the entry to find.
- ///
- public static bool Contains(this QueryParamCollection collection, string name, string value)
- {
- if (collection == null || collection.Count == 0)
- return false;
-
- var values = collection[name];
- if (values == null)
- return false;
-
- foreach (var v in values.Split(','))
- if (v.Trim().Equals(value, StringComparison.OrdinalIgnoreCase))
- return true;
-
- return false;
- }
-
- ///
- /// Emits the specified EventHandler<TEventArgs> delegate
- /// if it isn't .
- ///
- ///
- /// An EventHandler<TEventArgs> to emit.
- ///
- ///
- /// An from which emits this .
- ///
- ///
- /// A TEventArgs that represents the event data.
- ///
- ///
- /// The type of the event data generated by the event.
- ///
- public static void Emit(
- this EventHandler eventHandler, object sender, TEventArgs e)
- where TEventArgs : EventArgs
- {
- if (eventHandler != null)
- eventHandler(sender, e);
- }
-
- ///
- /// Gets the description of the specified HTTP status .
- ///
- ///
- /// A that represents the description of the HTTP status code.
- ///
- ///
- /// One of enum values, indicates the HTTP status codes.
- ///
- public static string GetDescription(this HttpStatusCode code)
- {
- return ((int)code).GetStatusDescription();
- }
-
- ///
- /// Gets the description of the specified HTTP status .
- ///
- ///
- /// A that represents the description of the HTTP status code.
- ///
- ///
- /// An that represents the HTTP status code.
- ///
- public static string GetStatusDescription(this 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 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 string.Empty;
- }
-
- ///
- /// Determines whether the specified is host
- /// (this computer architecture) byte order.
- ///
- ///
- /// true if is host byte order;
- /// otherwise, false.
- ///
- ///
- /// One of the enum values, to test.
- ///
- public static bool IsHostOrder(this ByteOrder order)
- {
- // true : !(true ^ true) or !(false ^ false)
- // false: !(true ^ false) or !(false ^ true)
- return !(BitConverter.IsLittleEndian ^ (order == ByteOrder.Little));
- }
-
- ///
- /// Determines whether the specified is a predefined scheme.
- ///
- ///
- /// true if is a predefined scheme; otherwise, false.
- ///
- ///
- /// A to test.
- ///
- public static bool IsPredefinedScheme(this string value)
- {
- if (value == null || value.Length < 2)
- return false;
-
- var c = value[0];
- if (c == 'h')
- return value == "http" || value == "https";
-
- if (c == 'w')
- return value == "ws" || value == "wss";
-
- if (c == 'f')
- return value == "file" || value == "ftp";
-
- if (c == 'n')
- {
- c = value[1];
- return c == 'e'
- ? value == "news" || value == "net.pipe" || value == "net.tcp"
- : value == "nntp";
- }
-
- return (c == 'g' && value == "gopher") || (c == 'm' && value == "mailto");
- }
-
- ///
- /// Determines whether the specified is a URI string.
- ///
- ///
- /// true if may be a URI string; otherwise, false.
- ///
- ///
- /// A to test.
- ///
- public static bool MaybeUri(this string value)
- {
- if (value == null || value.Length == 0)
- return false;
-
- var i = value.IndexOf(':');
- if (i == -1)
- return false;
-
- if (i >= 10)
- return false;
-
- return value.Substring(0, i).IsPredefinedScheme();
- }
-
- ///
- /// Retrieves a sub-array from the specified .
- /// A sub-array starts at the specified element position.
- ///
- ///
- /// An array of T that receives a sub-array, or an empty array of T if any problems
- /// with the parameters.
- ///
- ///
- /// An array of T that contains the data to retrieve a sub-array.
- ///
- ///
- /// An that contains the zero-based starting position of a sub-array
- /// in .
- ///
- ///
- /// An that contains the number of elements to retrieve a sub-array.
- ///
- ///
- /// The type of elements in the .
- ///
- public static T[] SubArray(this T[] array, int startIndex, int length)
- {
- if (array == null || array.Length == 0)
- return new T[0];
-
- if (startIndex < 0 || length <= 0)
- return new T[0];
-
- if (startIndex + length > array.Length)
- return new T[0];
-
- if (startIndex == 0 && array.Length == length)
- return array;
-
- T[] subArray = new T[length];
- Array.Copy(array, startIndex, subArray, 0, length);
-
- return subArray;
- }
-
- ///
- /// Converts the order of the specified array of to the host byte order.
- ///
- ///
- /// An array of converted from .
- ///
- ///
- /// An array of to convert.
- ///
- ///
- /// One of the enum values, indicates the byte order of
- /// .
- ///
- ///
- /// is .
- ///
- public static void ToHostOrder(this byte[] src, ByteOrder srcOrder)
- {
- if (src == null)
- {
- throw new ArgumentNullException(nameof(src));
- }
-
- if (src.Length > 1 && !srcOrder.IsHostOrder())
- {
- Array.Reverse(src);
- }
- }
-
- ///
- /// Converts the specified to a that
- /// concatenates the each element of across the specified
- /// .
- ///
- ///
- /// A converted from ,
- /// or if is empty.
- ///
- ///
- /// An array of T to convert.
- ///
- ///
- /// A that represents the separator string.
- ///
- ///
- /// The type of elements in .
- ///
- ///
- /// is .
- ///
- public static string ToString(this T[] array, string separator)
- {
- if (array == null)
- throw new ArgumentNullException(nameof(array));
-
- var len = array.Length;
- if (len == 0)
- return string.Empty;
-
- if (separator == null)
- separator = string.Empty;
-
- var buff = new StringBuilder(64);
- (len - 1).Times(i => buff.AppendFormat("{0}{1}", array[i].ToString(), separator));
-
- buff.Append(array[len - 1].ToString());
- return buff.ToString();
- }
-
- ///
- /// Executes the specified Action<int> delegate times.
- ///
- ///
- /// An is the number of times to execute.
- ///
- ///
- /// An Action<int> delegate that references the method(s) to execute.
- /// An parameter to pass to the method(s) is the zero-based count of
- /// iteration.
- ///
- public static void Times(this int n, Action action)
- {
- if (n > 0 && action != null)
- for (int i = 0; i < n; i++)
- action(i);
- }
-
- ///
- /// Converts the specified to a .
- ///
- ///
- /// A converted from , or
- /// if isn't successfully converted.
- ///
- ///
- /// A to convert.
- ///
- public static Uri ToUri(this string uriString)
- {
- return Uri.TryCreate(
- uriString, uriString.MaybeUri() ? UriKind.Absolute : UriKind.Relative, out var res)
- ? res
- : null;
- }
-
- ///
- /// URL-decodes the specified .
- ///
- ///
- /// A that receives the decoded string, or the
- /// if it's or empty.
- ///
- ///
- /// A to decode.
- ///
- public static string UrlDecode(this string value)
- {
- return value == null || value.Length == 0
- ? value
- : WebUtility.UrlDecode(value);
- }
-
- #endregion
- }
-}
diff --git a/SocketHttpListener/Fin.cs b/SocketHttpListener/Fin.cs
deleted file mode 100644
index c8ffbf2b2..000000000
--- a/SocketHttpListener/Fin.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace SocketHttpListener
-{
- internal enum Fin : byte
- {
- More = 0x0,
- Final = 0x1
- }
-}
diff --git a/SocketHttpListener/HttpBase.cs b/SocketHttpListener/HttpBase.cs
deleted file mode 100644
index c386b9374..000000000
--- a/SocketHttpListener/HttpBase.cs
+++ /dev/null
@@ -1,70 +0,0 @@
-using System;
-using System.Text;
-using MediaBrowser.Model.Services;
-
-namespace SocketHttpListener
-{
- internal abstract class HttpBase
- {
- #region Private Fields
-
- private QueryParamCollection _headers;
- private Version _version;
-
- #endregion
-
- #region Protected Fields
-
- protected const string CrLf = "\r\n";
-
- #endregion
-
- #region Protected Constructors
-
- protected HttpBase(Version version, QueryParamCollection headers)
- {
- _version = version;
- _headers = headers;
- }
-
- #endregion
-
- #region Public Properties
-
- public QueryParamCollection Headers => _headers;
-
- public Version ProtocolVersion => _version;
-
- #endregion
-
- #region Private Methods
-
- private static Encoding getEncoding(string contentType)
- {
- if (contentType == null || contentType.Length == 0)
- return Encoding.UTF8;
-
- var i = contentType.IndexOf("charset=", StringComparison.Ordinal);
- if (i == -1)
- return Encoding.UTF8;
-
- var charset = contentType.Substring(i + 8);
- i = charset.IndexOf(';');
- if (i != -1)
- charset = charset.Substring(0, i).TrimEnd();
-
- return Encoding.GetEncoding(charset.Trim('"'));
- }
-
- #endregion
-
- #region Public Methods
-
- public byte[] ToByteArray()
- {
- return Encoding.UTF8.GetBytes(ToString());
- }
-
- #endregion
- }
-}
diff --git a/SocketHttpListener/HttpResponse.cs b/SocketHttpListener/HttpResponse.cs
deleted file mode 100644
index a33b94295..000000000
--- a/SocketHttpListener/HttpResponse.cs
+++ /dev/null
@@ -1,122 +0,0 @@
-using System;
-using System.Linq;
-using System.Net;
-using System.Text;
-using MediaBrowser.Model.Services;
-using SocketHttpListener.Net;
-
-namespace SocketHttpListener
-{
- // 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().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
- }
-}
diff --git a/SocketHttpListener/Mask.cs b/SocketHttpListener/Mask.cs
deleted file mode 100644
index c56f5b08c..000000000
--- a/SocketHttpListener/Mask.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace SocketHttpListener
-{
- internal enum Mask : byte
- {
- Unmask = 0x0,
- Mask = 0x1
- }
-}
diff --git a/SocketHttpListener/MessageEventArgs.cs b/SocketHttpListener/MessageEventArgs.cs
deleted file mode 100644
index 8e2151cb7..000000000
--- a/SocketHttpListener/MessageEventArgs.cs
+++ /dev/null
@@ -1,84 +0,0 @@
-using System;
-using System.Text;
-
-namespace SocketHttpListener
-{
- ///
- /// Contains the event data associated with a event.
- ///
- ///
- /// A event occurs when the receives
- /// a text or binary data frame.
- /// If you want to get the received data, you access the or
- /// property.
- ///
- public class MessageEventArgs : EventArgs
- {
- #region Private Fields
-
- private string _data;
- private Opcode _opcode;
- private byte[] _rawData;
-
- #endregion
-
- #region Internal Constructors
-
- internal MessageEventArgs(Opcode opcode, byte[] data)
- {
- _opcode = opcode;
- _rawData = data;
- _data = convertToString(opcode, data);
- }
-
- internal MessageEventArgs(Opcode opcode, PayloadData payload)
- {
- _opcode = opcode;
- _rawData = payload.ApplicationData;
- _data = convertToString(opcode, _rawData);
- }
-
- #endregion
-
- #region Public Properties
-
- ///
- /// Gets the received data as a .
- ///
- ///
- /// A that contains the received data.
- ///
- public string Data => _data;
-
- ///
- /// Gets the received data as an array of .
- ///
- ///
- /// An array of that contains the received data.
- ///
- public byte[] RawData => _rawData;
-
- ///
- /// Gets the type of the received data.
- ///
- ///
- /// One of the values, indicates the type of the received data.
- ///
- public Opcode Type => _opcode;
-
- #endregion
-
- #region Private Methods
-
- private static string convertToString(Opcode opcode, byte[] data)
- {
- return data.Length == 0
- ? string.Empty
- : opcode == Opcode.Text
- ? Encoding.UTF8.GetString(data, 0, data.Length)
- : opcode.ToString();
- }
-
- #endregion
- }
-}
diff --git a/SocketHttpListener/Net/CookieHelper.cs b/SocketHttpListener/Net/CookieHelper.cs
deleted file mode 100644
index 3ad76ff23..000000000
--- a/SocketHttpListener/Net/CookieHelper.cs
+++ /dev/null
@@ -1,141 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Globalization;
-using System.Net;
-using System.Text;
-
-namespace SocketHttpListener.Net
-{
- public static class CookieHelper
- {
- internal static CookieCollection Parse(string value, bool response)
- {
- return response
- ? parseResponse(value)
- : null;
- }
-
- private static string[] splitCookieHeaderValue(string value)
- {
- return new List(value.SplitHeaderValue(',', ';')).ToArray();
- }
-
- private static CookieCollection parseResponse(string value)
- {
- var cookies = new CookieCollection();
-
- Cookie cookie = null;
- var pairs = splitCookieHeaderValue(value);
- for (int i = 0; i < pairs.Length; i++)
- {
- var pair = pairs[i].Trim();
- if (pair.Length == 0)
- continue;
-
- if (pair.StartsWith("version", StringComparison.OrdinalIgnoreCase))
- {
- if (cookie != null)
- cookie.Version = int.Parse(pair.GetValueInternal("=").Trim('"'));
- }
- else if (pair.StartsWith("expires", StringComparison.OrdinalIgnoreCase))
- {
- var buffer = new StringBuilder(pair.GetValueInternal("="), 32);
- if (i < pairs.Length - 1)
- buffer.AppendFormat(", {0}", pairs[++i].Trim());
-
- if (!DateTime.TryParseExact(
- buffer.ToString(),
- new[] { "ddd, dd'-'MMM'-'yyyy HH':'mm':'ss 'GMT'", "r" },
- new CultureInfo("en-US"),
- DateTimeStyles.AdjustToUniversal | DateTimeStyles.AssumeUniversal,
- out var expires))
- expires = DateTime.Now;
-
- if (cookie != null && cookie.Expires == DateTime.MinValue)
- cookie.Expires = expires.ToLocalTime();
- }
- else if (pair.StartsWith("max-age", StringComparison.OrdinalIgnoreCase))
- {
- var max = int.Parse(pair.GetValueInternal("=").Trim('"'));
- var expires = DateTime.Now.AddSeconds((double)max);
- if (cookie != null)
- cookie.Expires = expires;
- }
- else if (pair.StartsWith("path", StringComparison.OrdinalIgnoreCase))
- {
- if (cookie != null)
- cookie.Path = pair.GetValueInternal("=");
- }
- else if (pair.StartsWith("domain", StringComparison.OrdinalIgnoreCase))
- {
- if (cookie != null)
- cookie.Domain = pair.GetValueInternal("=");
- }
- else if (pair.StartsWith("port", StringComparison.OrdinalIgnoreCase))
- {
- var port = pair.Equals("port", StringComparison.OrdinalIgnoreCase)
- ? "\"\""
- : pair.GetValueInternal("=");
-
- if (cookie != null)
- cookie.Port = port;
- }
- else if (pair.StartsWith("comment", StringComparison.OrdinalIgnoreCase))
- {
- if (cookie != null)
- cookie.Comment = pair.GetValueInternal("=").UrlDecode();
- }
- else if (pair.StartsWith("commenturl", StringComparison.OrdinalIgnoreCase))
- {
- if (cookie != null)
- cookie.CommentUri = pair.GetValueInternal("=").Trim('"').ToUri();
- }
- else if (pair.StartsWith("discard", StringComparison.OrdinalIgnoreCase))
- {
- if (cookie != null)
- cookie.Discard = true;
- }
- else if (pair.StartsWith("secure", StringComparison.OrdinalIgnoreCase))
- {
- if (cookie != null)
- cookie.Secure = true;
- }
- else if (pair.StartsWith("httponly", StringComparison.OrdinalIgnoreCase))
- {
- if (cookie != null)
- cookie.HttpOnly = true;
- }
- else
- {
- if (cookie != null)
- cookies.Add(cookie);
-
- string name;
- string val = string.Empty;
-
- var pos = pair.IndexOf('=');
- if (pos == -1)
- {
- name = pair;
- }
- else if (pos == pair.Length - 1)
- {
- name = pair.Substring(0, pos).TrimEnd(' ');
- }
- else
- {
- name = pair.Substring(0, pos).TrimEnd(' ');
- val = pair.Substring(pos + 1).TrimStart(' ');
- }
-
- cookie = new Cookie(name, val);
- }
- }
-
- if (cookie != null)
- cookies.Add(cookie);
-
- return cookies;
- }
- }
-}
diff --git a/SocketHttpListener/Opcode.cs b/SocketHttpListener/Opcode.cs
deleted file mode 100644
index 69cf3f372..000000000
--- a/SocketHttpListener/Opcode.cs
+++ /dev/null
@@ -1,43 +0,0 @@
-namespace SocketHttpListener
-{
- ///
- /// Contains the values of the opcode that indicates the type of a WebSocket frame.
- ///
- ///
- /// The values of the opcode are defined in
- /// Section 5.2 of RFC 6455.
- ///
- public enum Opcode : byte
- {
- ///
- /// Equivalent to numeric value 0.
- /// Indicates a continuation frame.
- ///
- Cont = 0x0,
- ///
- /// Equivalent to numeric value 1.
- /// Indicates a text frame.
- ///
- Text = 0x1,
- ///
- /// Equivalent to numeric value 2.
- /// Indicates a binary frame.
- ///
- Binary = 0x2,
- ///
- /// Equivalent to numeric value 8.
- /// Indicates a connection close frame.
- ///
- Close = 0x8,
- ///
- /// Equivalent to numeric value 9.
- /// Indicates a ping frame.
- ///
- Ping = 0x9,
- ///
- /// Equivalent to numeric value 10.
- /// Indicates a pong frame.
- ///
- Pong = 0xa
- }
-}
diff --git a/SocketHttpListener/PayloadData.cs b/SocketHttpListener/PayloadData.cs
deleted file mode 100644
index 6d15a6bcb..000000000
--- a/SocketHttpListener/PayloadData.cs
+++ /dev/null
@@ -1,130 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Text;
-
-namespace SocketHttpListener
-{
- internal class PayloadData : IEnumerable
- {
- #region Private Fields
-
- private byte[] _applicationData;
- private byte[] _extensionData;
- private bool _masked;
-
- #endregion
-
- #region Public Const Fields
-
- public const ulong MaxLength = long.MaxValue;
-
- #endregion
-
- #region Public Constructors
-
- public PayloadData()
- : this(new byte[0], new byte[0], false)
- {
- }
-
- public PayloadData(byte[] applicationData)
- : this(new byte[0], applicationData, false)
- {
- }
-
- public PayloadData(string applicationData)
- : this(new byte[0], Encoding.UTF8.GetBytes(applicationData), false)
- {
- }
-
- public PayloadData(byte[] applicationData, bool masked)
- : this(new byte[0], applicationData, masked)
- {
- }
-
- public PayloadData(byte[] extensionData, byte[] applicationData, bool masked)
- {
- _extensionData = extensionData;
- _applicationData = applicationData;
- _masked = masked;
- }
-
- #endregion
-
- #region Internal Properties
-
- internal bool ContainsReservedCloseStatusCode =>
- _applicationData.Length > 1 &&
- _applicationData.SubArray(0, 2).ToUInt16(ByteOrder.Big).IsReserved();
-
- #endregion
-
- #region Public Properties
-
- public byte[] ApplicationData => _applicationData;
-
- public byte[] ExtensionData => _extensionData;
-
- public bool IsMasked => _masked;
-
- public ulong Length => (ulong)(_extensionData.Length + _applicationData.Length);
-
- #endregion
-
- #region Private Methods
-
- private static void mask(byte[] src, byte[] key)
- {
- for (long i = 0; i < src.Length; i++)
- src[i] = (byte)(src[i] ^ key[i % 4]);
- }
-
- #endregion
-
- #region Public Methods
-
- public IEnumerator GetEnumerator()
- {
- foreach (byte b in _extensionData)
- yield return b;
-
- foreach (byte b in _applicationData)
- yield return b;
- }
-
- public void Mask(byte[] maskingKey)
- {
- if (_extensionData.Length > 0)
- mask(_extensionData, maskingKey);
-
- if (_applicationData.Length > 0)
- mask(_applicationData, maskingKey);
-
- _masked = !_masked;
- }
-
- public byte[] ToByteArray()
- {
- return _extensionData.Length > 0
- ? new List(this).ToArray()
- : _applicationData;
- }
-
- public override string ToString()
- {
- return BitConverter.ToString(ToByteArray());
- }
-
- #endregion
-
- #region Explicitly Implemented Interface Members
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- #endregion
- }
-}
diff --git a/SocketHttpListener/Properties/AssemblyInfo.cs b/SocketHttpListener/Properties/AssemblyInfo.cs
deleted file mode 100644
index a69bd176f..000000000
--- a/SocketHttpListener/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,21 +0,0 @@
-using System.Reflection;
-using System.Resources;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("SocketHttpListener")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Jellyfin Project")]
-[assembly: AssemblyProduct("Jellyfin: The Free Software Media System")]
-[assembly: AssemblyCopyright("Copyright © 2019 Jellyfin Contributors. Code released under the GNU General Public License Version 2")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-[assembly: NeutralResourcesLanguage("en")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
diff --git a/SocketHttpListener/Rsv.cs b/SocketHttpListener/Rsv.cs
deleted file mode 100644
index 87283791e..000000000
--- a/SocketHttpListener/Rsv.cs
+++ /dev/null
@@ -1,8 +0,0 @@
-namespace SocketHttpListener
-{
- internal enum Rsv : byte
- {
- Off = 0x0,
- On = 0x1
- }
-}
diff --git a/SocketHttpListener/SocketHttpListener.csproj b/SocketHttpListener/SocketHttpListener.csproj
deleted file mode 100644
index e700540a9..000000000
--- a/SocketHttpListener/SocketHttpListener.csproj
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
- netstandard2.0
- true
- false
-
-
-
diff --git a/SocketHttpListener/SocketStream.cs b/SocketHttpListener/SocketStream.cs
deleted file mode 100644
index f51fde97e..000000000
--- a/SocketHttpListener/SocketStream.cs
+++ /dev/null
@@ -1,74 +0,0 @@
-using System;
-using System.IO;
-using System.Net.Sockets;
-
-namespace SocketHttpListener
-{
- public class SocketStream : Stream
- {
- private readonly Socket _socket;
-
- public SocketStream(Socket socket, bool ownsSocket)
- {
- _socket = socket;
- }
-
- public override void Flush()
- {
- }
-
- public override bool CanRead => true;
-
- public override bool CanSeek => false;
-
- public override bool CanWrite => true;
-
- public override long Length => throw new NotImplementedException();
-
- public override long Position
- {
- get => throw new NotImplementedException();
- set => throw new NotImplementedException();
- }
-
- public override void Write(byte[] buffer, int offset, int count)
- {
- _socket.Send(buffer, offset, count, SocketFlags.None);
- }
-
- public override IAsyncResult BeginWrite(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- return _socket.BeginSend(buffer, offset, count, SocketFlags.None, callback, state);
- }
-
- public override void EndWrite(IAsyncResult asyncResult)
- {
- _socket.EndSend(asyncResult);
- }
-
- public override void SetLength(long value)
- {
- throw new NotImplementedException();
- }
-
- public override long Seek(long offset, SeekOrigin origin)
- {
- throw new NotImplementedException();
- }
-
- public override int Read(byte[] buffer, int offset, int count)
- {
- return _socket.Receive(buffer, offset, count, SocketFlags.None);
- }
-
- public override IAsyncResult BeginRead(byte[] buffer, int offset, int count, AsyncCallback callback, object state)
- {
- return _socket.BeginReceive(buffer, offset, count, SocketFlags.None, callback, state);
- }
-
- public override int EndRead(IAsyncResult asyncResult)
- {
- return _socket.EndReceive(asyncResult);
- }
- }
-}
diff --git a/SocketHttpListener/WebSocket.cs b/SocketHttpListener/WebSocket.cs
deleted file mode 100644
index afce871fd..000000000
--- a/SocketHttpListener/WebSocket.cs
+++ /dev/null
@@ -1,777 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Net;
-using System.Net.Sockets;
-using System.Net.WebSockets;
-using System.Text;
-using System.Threading;
-using System.Threading.Tasks;
-using WebSocketState = System.Net.WebSockets.WebSocketState;
-
-namespace SocketHttpListener
-{
- ///
- /// Implements the WebSocket interface.
- ///
- ///
- /// The WebSocket class provides a set of methods and properties for two-way communication using
- /// the WebSocket protocol (RFC 6455).
- ///
- public class WebSocket : IDisposable
- {
- #region Private Fields
-
- private Action _closeContext;
- private CompressionMethod _compression;
- private WebSocketContext _context;
- private CookieCollection _cookies;
- private AutoResetEvent _exitReceiving;
- private object _forConn;
- private readonly SemaphoreSlim _forEvent = new SemaphoreSlim(1, 1);
- private object _forMessageEventQueue;
- private readonly SemaphoreSlim _forSend = new SemaphoreSlim(1, 1);
- private const string _guid = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
- private Queue _messageEventQueue;
- private string _protocol;
- private volatile WebSocketState _readyState;
- private AutoResetEvent _receivePong;
- private bool _secure;
- private Stream _stream;
- private const string _version = "13";
-
- #endregion
-
- #region Internal Fields
-
- internal const int FragmentLength = 1016; // Max value is int.MaxValue - 14.
-
- #endregion
-
- #region Internal Constructors
-
- // As server
- internal WebSocket(string protocol)
- {
- _protocol = protocol;
- }
-
- public void SetContext(HttpListenerWebSocketContext context, Action closeContextFn, Stream stream)
- {
- _context = context;
-
- _closeContext = closeContextFn;
- _secure = context.IsSecureConnection;
- _stream = stream;
-
- init();
- }
-
- // In the .NET Framework, this pulls the value from a P/Invoke. Here we just hardcode it to a reasonable default.
- public static TimeSpan DefaultKeepAliveInterval => TimeSpan.FromSeconds(30);
-
- #endregion
-
- ///
- /// Gets the state of the WebSocket connection.
- ///
- ///
- /// One of the enum values, indicates the state of the WebSocket
- /// connection. The default value is .
- ///
- public WebSocketState ReadyState => _readyState;
-
- #region Public Events
-
- ///
- /// Occurs when the WebSocket connection has been closed.
- ///
- public event EventHandler OnClose;
-
- ///
- /// Occurs when the gets an error.
- ///
- public event EventHandler OnError;
-
- ///
- /// Occurs when the receives a message.
- ///
- public event EventHandler OnMessage;
-
- ///
- /// Occurs when the WebSocket connection has been established.
- ///
- public event EventHandler OnOpen;
-
- #endregion
-
- #region Private Methods
-
- private async Task CloseAsync(CloseStatusCode code, string reason, bool wait)
- {
- await CloseAsync(new PayloadData(
- await ((ushort)code).AppendAsync(reason).ConfigureAwait(false)),
- !code.IsReserved(),
- wait).ConfigureAwait(false);
- }
-
- private async Task CloseAsync(PayloadData payload, bool send, bool wait)
- {
- lock (_forConn)
- {
- if (_readyState == WebSocketState.CloseSent || _readyState == WebSocketState.Closed)
- {
- return;
- }
-
- _readyState = WebSocketState.CloseSent;
- }
-
- var e = new CloseEventArgs(payload)
- {
- WasClean = await CloseHandshakeAsync(
- send ? WebSocketFrame.CreateCloseFrame(Mask.Unmask, payload).ToByteArray() : null,
- wait ? 1000 : 0).ConfigureAwait(false)
- };
-
- _readyState = WebSocketState.Closed;
- try
- {
- OnClose.Emit(this, e);
- }
- catch (Exception ex)
- {
- error("An exception has occurred while OnClose.", ex);
- }
- }
-
- private async Task CloseHandshakeAsync(byte[] frameAsBytes, int millisecondsTimeout)
- {
- var sent = frameAsBytes != null && await WriteBytesAsync(frameAsBytes).ConfigureAwait(false);
- var received =
- millisecondsTimeout == 0 ||
- (sent && _exitReceiving != null && _exitReceiving.WaitOne(millisecondsTimeout));
-
- closeServerResources();
-
- if (_receivePong != null)
- {
- _receivePong.Dispose();
- _receivePong = null;
- }
-
- if (_exitReceiving != null)
- {
- _exitReceiving.Dispose();
- _exitReceiving = null;
- }
-
- var result = sent && received;
-
- return result;
- }
-
- // As server
- private void closeServerResources()
- {
- if (_closeContext == null)
- return;
-
- try
- {
- _closeContext();
- }
- catch (SocketException)
- {
- // it could be unable to send the handshake response
- }
-
- _closeContext = null;
- _stream = null;
- _context = null;
- }
-
- private async Task ConcatenateFragmentsIntoAsync(Stream dest)
- {
- while (true)
- {
- var frame = await WebSocketFrame.ReadAsync(_stream, true).ConfigureAwait(false);
- if (frame.IsFinal)
- {
- /* FINAL */
-
- // CONT
- if (frame.IsContinuation)
- {
- dest.WriteBytes(frame.PayloadData.ApplicationData);
- break;
- }
-
- // PING
- if (frame.IsPing)
- {
- processPingFrame(frame);
- continue;
- }
-
- // PONG
- if (frame.IsPong)
- {
- processPongFrame(frame);
- continue;
- }
-
- // CLOSE
- if (frame.IsClose)
- return await ProcessCloseFrameAsync(frame).ConfigureAwait(false);
- }
- else
- {
- /* MORE */
-
- // CONT
- if (frame.IsContinuation)
- {
- dest.WriteBytes(frame.PayloadData.ApplicationData);
- continue;
- }
- }
-
- // ?
- return await ProcessUnsupportedFrameAsync(
- frame,
- CloseStatusCode.IncorrectData,
- "An incorrect data has been received while receiving fragmented data.").ConfigureAwait(false);
- }
-
- return true;
- }
-
- // As server
- private HttpResponse createHandshakeCloseResponse(HttpStatusCode code)
- {
- var res = HttpResponse.CreateCloseResponse(code);
- res.Headers["Sec-WebSocket-Version"] = _version;
-
- return res;
- }
-
- private MessageEventArgs dequeueFromMessageEventQueue()
- {
- lock (_forMessageEventQueue)
- return _messageEventQueue.Count > 0
- ? _messageEventQueue.Dequeue()
- : null;
- }
-
- private void enqueueToMessageEventQueue(MessageEventArgs e)
- {
- lock (_forMessageEventQueue)
- _messageEventQueue.Enqueue(e);
- }
-
- private void error(string message, Exception exception)
- {
- try
- {
- if (exception != null)
- {
- message += ". Exception.Message: " + exception.Message;
- }
- OnError.Emit(this, new ErrorEventArgs(message));
- }
- catch (Exception)
- {
- }
- }
-
- private void error(string message)
- {
- try
- {
- OnError.Emit(this, new ErrorEventArgs(message));
- }
- catch (Exception)
- {
- }
- }
-
- private void init()
- {
- _compression = CompressionMethod.None;
- _cookies = new CookieCollection();
- _forConn = new object();
- _messageEventQueue = new Queue();
- _forMessageEventQueue = ((ICollection)_messageEventQueue).SyncRoot;
- _readyState = WebSocketState.Connecting;
- }
-
- private async Task OpenAsync()
- {
- try
- {
- startReceiving();
-
- }
- catch (Exception ex)
- {
- await ProcessExceptionAsync(ex, "An exception has occurred while opening.").ConfigureAwait(false);
- }
-
- await _forEvent.WaitAsync().ConfigureAwait(false);
- try
- {
- OnOpen?.Invoke(this, EventArgs.Empty);
- }
- catch (Exception ex)
- {
- await ProcessExceptionAsync(ex, "An exception has occurred while OnOpen.").ConfigureAwait(false);
- }
- finally
- {
- _forEvent.Release();
- }
- }
-
- private async Task ProcessCloseFrameAsync(WebSocketFrame frame)
- {
- var payload = frame.PayloadData;
- await CloseAsync(payload, !payload.ContainsReservedCloseStatusCode, false).ConfigureAwait(false);
-
- return false;
- }
-
- private bool processDataFrame(WebSocketFrame frame)
- {
- var e = frame.IsCompressed
- ? new MessageEventArgs(
- frame.Opcode, frame.PayloadData.ApplicationData.Decompress(_compression))
- : new MessageEventArgs(frame.Opcode, frame.PayloadData);
-
- enqueueToMessageEventQueue(e);
- return true;
- }
-
- private async Task ProcessExceptionAsync(Exception exception, string message)
- {
- var code = CloseStatusCode.Abnormal;
- var reason = message;
- if (exception is WebSocketException)
- {
- var wsex = (WebSocketException)exception;
- code = wsex.Code;
- reason = wsex.Message;
- }
-
- error(message ?? code.GetMessage(), exception);
- if (_readyState == WebSocketState.Connecting)
- {
- await CloseAsync(HttpStatusCode.BadRequest).ConfigureAwait(false);
- }
- else
- {
- await CloseAsync(code, reason ?? code.GetMessage(), false).ConfigureAwait(false);
- }
- }
-
- private Task ProcessFragmentedFrameAsync(WebSocketFrame frame)
- {
- return frame.IsContinuation // Not first fragment
- ? Task.FromResult(true)
- : ProcessFragmentsAsync(frame);
- }
-
- private async Task ProcessFragmentsAsync(WebSocketFrame first)
- {
- using (var buff = new MemoryStream())
- {
- buff.WriteBytes(first.PayloadData.ApplicationData);
- if (!await ConcatenateFragmentsIntoAsync(buff).ConfigureAwait(false))
- {
- return false;
- }
-
- byte[] data;
- if (_compression != CompressionMethod.None)
- {
- data = buff.DecompressToArray(_compression);
- }
- else
- {
- data = buff.ToArray();
- }
-
- enqueueToMessageEventQueue(new MessageEventArgs(first.Opcode, data));
- return true;
- }
- }
-
- private bool processPingFrame(WebSocketFrame frame)
- {
- return true;
- }
-
- private bool processPongFrame(WebSocketFrame frame)
- {
- _receivePong.Set();
-
- return true;
- }
-
- private async Task ProcessUnsupportedFrameAsync(WebSocketFrame frame, CloseStatusCode code, string reason)
- {
- await ProcessExceptionAsync(new WebSocketException(code, reason), null).ConfigureAwait(false);
-
- return false;
- }
-
- private Task ProcessWebSocketFrameAsync(WebSocketFrame frame)
- {
- // TODO: @bond change to if/else chain
- return frame.IsCompressed && _compression == CompressionMethod.None
- ? ProcessUnsupportedFrameAsync(
- frame,
- CloseStatusCode.IncorrectData,
- "A compressed data has been received without available decompression method.")
- : frame.IsFragmented
- ? ProcessFragmentedFrameAsync(frame)
- : frame.IsData
- ? Task.FromResult(processDataFrame(frame))
- : frame.IsPing
- ? Task.FromResult(processPingFrame(frame))
- : frame.IsPong
- ? Task.FromResult(processPongFrame(frame))
- : frame.IsClose
- ? ProcessCloseFrameAsync(frame)
- : ProcessUnsupportedFrameAsync(frame, CloseStatusCode.PolicyViolation, null);
- }
-
- private async Task SendAsync(Opcode opcode, Stream stream)
- {
- await _forSend.WaitAsync().ConfigureAwait(false);
- try
- {
- var src = stream;
- var compressed = false;
- var sent = false;
- try
- {
- if (_compression != CompressionMethod.None)
- {
- stream = stream.Compress(_compression);
- compressed = true;
- }
-
- sent = await SendAsync(opcode, Mask.Unmask, stream, compressed).ConfigureAwait(false);
- if (!sent)
- error("Sending a data has been interrupted.");
- }
- catch (Exception ex)
- {
- error("An exception has occurred while sending a data.", ex);
- }
- finally
- {
- if (compressed)
- stream.Dispose();
-
- src.Dispose();
- }
-
- return sent;
- }
- finally
- {
- _forSend.Release();
- }
- }
-
- private async Task SendAsync(Opcode opcode, Mask mask, Stream stream, bool compressed)
- {
- var len = stream.Length;
-
- /* Not fragmented */
-
- if (len == 0)
- return await SendAsync(Fin.Final, opcode, mask, new byte[0], compressed).ConfigureAwait(false);
-
- var quo = len / FragmentLength;
- var rem = (int)(len % FragmentLength);
-
- byte[] buff = null;
- if (quo == 0)
- {
- buff = new byte[rem];
- return await stream.ReadAsync(buff, 0, rem).ConfigureAwait(false) == rem &&
- await SendAsync(Fin.Final, opcode, mask, buff, compressed).ConfigureAwait(false);
- }
-
- buff = new byte[FragmentLength];
- if (quo == 1 && rem == 0)
- return await stream.ReadAsync(buff, 0, FragmentLength).ConfigureAwait(false) == FragmentLength &&
- await SendAsync(Fin.Final, opcode, mask, buff, compressed).ConfigureAwait(false);
-
- /* Send fragmented */
-
- // Begin
- if (await stream.ReadAsync(buff, 0, FragmentLength).ConfigureAwait(false) != FragmentLength ||
- !await SendAsync(Fin.More, opcode, mask, buff, compressed).ConfigureAwait(false))
- return false;
-
- var n = rem == 0 ? quo - 2 : quo - 1;
- for (long i = 0; i < n; i++)
- if (await stream.ReadAsync(buff, 0, FragmentLength).ConfigureAwait(false) != FragmentLength ||
- !await SendAsync(Fin.More, Opcode.Cont, mask, buff, compressed).ConfigureAwait(false))
- return false;
-
- // End
- if (rem == 0)
- rem = FragmentLength;
- else
- buff = new byte[rem];
-
- return await stream.ReadAsync(buff, 0, rem).ConfigureAwait(false) == rem &&
- await SendAsync(Fin.Final, Opcode.Cont, mask, buff, compressed).ConfigureAwait(false);
- }
-
- private Task SendAsync(Fin fin, Opcode opcode, Mask mask, byte[] data, bool compressed)
- {
- lock (_forConn)
- {
- if (_readyState != WebSocketState.Open)
- {
- return Task.FromResult(false);
- }
-
- return WriteBytesAsync(
- WebSocketFrame.CreateWebSocketFrame(fin, opcode, mask, data, compressed).ToByteArray());
- }
- }
-
- // As server
- private Task SendHttpResponseAsync(HttpResponse response)
- => WriteBytesAsync(response.ToByteArray());
-
- private void startReceiving()
- {
- if (_messageEventQueue.Count > 0)
- {
- _messageEventQueue.Clear();
- }
-
- _exitReceiving = new AutoResetEvent(false);
- _receivePong = new AutoResetEvent(false);
-
- Action receive = null;
- receive = async () => await WebSocketFrame.ReadAsync(
- _stream,
- true,
- async frame =>
- {
- if (await ProcessWebSocketFrameAsync(frame).ConfigureAwait(false) && _readyState != WebSocketState.Closed)
- {
- receive();
-
- if (!frame.IsData)
- {
- return;
- }
-
- await _forEvent.WaitAsync().ConfigureAwait(false);
-
- try
- {
- var e = dequeueFromMessageEventQueue();
- if (e != null && _readyState == WebSocketState.Open)
- {
- OnMessage.Emit(this, e);
- }
- }
- catch (Exception ex)
- {
- await ProcessExceptionAsync(ex, "An exception has occurred while OnMessage.").ConfigureAwait(false);
- }
- finally
- {
- _forEvent.Release();
- }
-
- }
- else if (_exitReceiving != null)
- {
- _exitReceiving.Set();
- }
- },
- async ex => await ProcessExceptionAsync(ex, "An exception has occurred while receiving a message.")).ConfigureAwait(false);
-
- receive();
- }
-
- private async Task WriteBytesAsync(byte[] data)
- {
- try
- {
- await _stream.WriteAsync(data, 0, data.Length).ConfigureAwait(false);
- return true;
- }
- catch (Exception)
- {
- return false;
- }
- }
-
- #endregion
-
- #region Internal Methods
-
- // As server
- internal async Task CloseAsync(HttpResponse response)
- {
- _readyState = WebSocketState.CloseSent;
- await SendHttpResponseAsync(response).ConfigureAwait(false);
-
- closeServerResources();
-
- _readyState = WebSocketState.Closed;
- }
-
- // As server
- internal Task CloseAsync(HttpStatusCode code)
- => CloseAsync(createHandshakeCloseResponse(code));
-
- // As server
- public async Task ConnectAsServer()
- {
- try
- {
- _readyState = WebSocketState.Open;
- await OpenAsync().ConfigureAwait(false);
- }
- catch (Exception ex)
- {
- await ProcessExceptionAsync(ex, "An exception has occurred while connecting.").ConfigureAwait(false);
- }
- }
-
- #endregion
-
- #region Public Methods
-
- ///
- /// Closes the WebSocket connection, and releases all associated resources.
- ///
- public Task CloseAsync()
- {
- var msg = _readyState.CheckIfClosable();
- if (msg != null)
- {
- error(msg);
-
- return Task.CompletedTask;
- }
-
- var send = _readyState == WebSocketState.Open;
- return CloseAsync(new PayloadData(), send, send);
- }
-
- ///
- /// Closes the WebSocket connection with the specified
- /// and , and releases all associated resources.
- ///
- ///
- /// This method emits a event if the size
- /// of is greater than 123 bytes.
- ///
- ///
- /// One of the enum values, represents the status code
- /// indicating the reason for the close.
- ///
- ///
- /// A that represents the reason for the close.
- ///
- public async Task CloseAsync(CloseStatusCode code, string reason)
- {
- byte[] data = null;
- var msg = _readyState.CheckIfClosable() ??
- (data = await ((ushort)code).AppendAsync(reason).ConfigureAwait(false)).CheckIfValidControlData("reason");
-
- if (msg != null)
- {
- error(msg);
-
- return;
- }
-
- var send = _readyState == WebSocketState.Open && !code.IsReserved();
- await CloseAsync(new PayloadData(data), send, send).ConfigureAwait(false);
- }
-
- ///
- /// Sends a binary asynchronously using the WebSocket connection.
- ///
- ///
- /// This method doesn't wait for the send to be complete.
- ///
- ///
- /// An array of that represents the binary data to send.
- ///
- public Task SendAsync(byte[] data)
- {
- if (data == null)
- {
- throw new ArgumentNullException(nameof(data));
- }
-
- var msg = _readyState.CheckIfOpen();
- if (msg != null)
- {
- throw new Exception(msg);
- }
-
- return SendAsync(Opcode.Binary, new MemoryStream(data));
- }
-
- ///
- /// Sends a text asynchronously using the WebSocket connection.
- ///
- ///
- /// This method doesn't wait for the send to be complete.
- ///
- ///
- /// A that represents the text data to send.
- ///
- public Task SendAsync(string data)
- {
- if (data == null)
- {
- throw new ArgumentNullException(nameof(data));
- }
-
- var msg = _readyState.CheckIfOpen();
- if (msg != null)
- {
- throw new Exception(msg);
- }
-
- return SendAsync(Opcode.Text, new MemoryStream(Encoding.UTF8.GetBytes(data)));
- }
-
- #endregion
-
- #region Explicit Interface Implementation
-
- ///
- /// Closes the WebSocket connection, and releases all associated resources.
- ///
- ///
- /// This method closes the WebSocket connection with .
- ///
- void IDisposable.Dispose()
- {
- CloseAsync(CloseStatusCode.Away, null).GetAwaiter().GetResult();
- }
-
- #endregion
- }
-}
diff --git a/SocketHttpListener/WebSocketException.cs b/SocketHttpListener/WebSocketException.cs
deleted file mode 100644
index e86c46d0f..000000000
--- a/SocketHttpListener/WebSocketException.cs
+++ /dev/null
@@ -1,61 +0,0 @@
-using System;
-
-namespace SocketHttpListener
-{
- ///
- /// The exception that is thrown when a gets a fatal error.
- ///
- public class WebSocketException : Exception
- {
- #region Internal Constructors
-
- internal WebSocketException()
- : this(CloseStatusCode.Abnormal, null, null)
- {
- }
-
- internal WebSocketException(string message)
- : this(CloseStatusCode.Abnormal, message, null)
- {
- }
-
- internal WebSocketException(CloseStatusCode code)
- : this(code, null, null)
- {
- }
-
- internal WebSocketException(string message, Exception innerException)
- : this(CloseStatusCode.Abnormal, message, innerException)
- {
- }
-
- internal WebSocketException(CloseStatusCode code, string message)
- : this(code, message, null)
- {
- }
-
- internal WebSocketException(CloseStatusCode code, string message, Exception innerException)
- : base(message ?? code.GetMessage(), innerException)
- {
- Code = code;
- }
-
- #endregion
-
- #region Public Properties
-
- ///
- /// Gets the status code indicating the cause for the exception.
- ///
- ///
- /// One of the enum values, represents the status code indicating
- /// the cause for the exception.
- ///
- public CloseStatusCode Code
- {
- get; private set;
- }
-
- #endregion
- }
-}
diff --git a/SocketHttpListener/WebSocketFrame.cs b/SocketHttpListener/WebSocketFrame.cs
deleted file mode 100644
index 8ec64026b..000000000
--- a/SocketHttpListener/WebSocketFrame.cs
+++ /dev/null
@@ -1,432 +0,0 @@
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.IO;
-using System.Threading.Tasks;
-
-namespace SocketHttpListener
-{
- internal class WebSocketFrame : IEnumerable
- {
- #region Private Fields
-
- private byte[] _extPayloadLength;
- private Fin _fin;
- private Mask _mask;
- private byte[] _maskingKey;
- private Opcode _opcode;
- private PayloadData _payloadData;
- private byte _payloadLength;
- private Rsv _rsv1;
- private Rsv _rsv2;
- private Rsv _rsv3;
-
- #endregion
-
- #region Internal Fields
-
- internal static readonly byte[] EmptyUnmaskPingData;
-
- #endregion
-
- #region Static Constructor
-
- static WebSocketFrame()
- {
- EmptyUnmaskPingData = CreatePingFrame(Mask.Unmask).ToByteArray();
- }
-
- #endregion
-
- #region Private Constructors
-
- private WebSocketFrame()
- {
- }
-
- #endregion
-
- #region Internal Constructors
-
- internal WebSocketFrame(Opcode opcode, PayloadData payload)
- : this(Fin.Final, opcode, Mask.Mask, payload, false)
- {
- }
-
- internal WebSocketFrame(Opcode opcode, Mask mask, PayloadData payload)
- : this(Fin.Final, opcode, mask, payload, false)
- {
- }
-
- internal WebSocketFrame(Fin fin, Opcode opcode, Mask mask, PayloadData payload)
- : this(fin, opcode, mask, payload, false)
- {
- }
-
- internal WebSocketFrame(
- Fin fin, Opcode opcode, Mask mask, PayloadData payload, bool compressed)
- {
- _fin = fin;
- _rsv1 = isData(opcode) && compressed ? Rsv.On : Rsv.Off;
- _rsv2 = Rsv.Off;
- _rsv3 = Rsv.Off;
- _opcode = opcode;
- _mask = mask;
-
- var len = payload.Length;
- if (len < 126)
- {
- _payloadLength = (byte)len;
- _extPayloadLength = new byte[0];
- }
- else if (len < 0x010000)
- {
- _payloadLength = (byte)126;
- _extPayloadLength = ((ushort)len).ToByteArrayInternally(ByteOrder.Big);
- }
- else
- {
- _payloadLength = (byte)127;
- _extPayloadLength = len.ToByteArrayInternally(ByteOrder.Big);
- }
-
- if (mask == Mask.Mask)
- {
- _maskingKey = createMaskingKey();
- payload.Mask(_maskingKey);
- }
- else
- {
- _maskingKey = new byte[0];
- }
-
- _payloadData = payload;
- }
-
- #endregion
-
- #region Public Properties
-
- public byte[] ExtendedPayloadLength => _extPayloadLength;
-
- public Fin Fin => _fin;
-
- public bool IsBinary => _opcode == Opcode.Binary;
-
- public bool IsClose => _opcode == Opcode.Close;
-
- public bool IsCompressed => _rsv1 == Rsv.On;
-
- public bool IsContinuation => _opcode == Opcode.Cont;
-
- public bool IsControl => _opcode == Opcode.Close || _opcode == Opcode.Ping || _opcode == Opcode.Pong;
-
- public bool IsData => _opcode == Opcode.Binary || _opcode == Opcode.Text;
-
- public bool IsFinal => _fin == Fin.Final;
-
- public bool IsFragmented => _fin == Fin.More || _opcode == Opcode.Cont;
-
- public bool IsMasked => _mask == Mask.Mask;
-
- public bool IsPerMessageCompressed => (_opcode == Opcode.Binary || _opcode == Opcode.Text) && _rsv1 == Rsv.On;
-
- public bool IsPing => _opcode == Opcode.Ping;
-
- public bool IsPong => _opcode == Opcode.Pong;
-
- public bool IsText => _opcode == Opcode.Text;
-
- public ulong Length => 2 + (ulong)(_extPayloadLength.Length + _maskingKey.Length) + _payloadData.Length;
-
- public Mask Mask => _mask;
-
- public byte[] MaskingKey => _maskingKey;
-
- public Opcode Opcode => _opcode;
-
- public PayloadData PayloadData => _payloadData;
-
- public byte PayloadLength => _payloadLength;
-
- public Rsv Rsv1 => _rsv1;
-
- public Rsv Rsv2 => _rsv2;
-
- public Rsv Rsv3 => _rsv3;
-
- #endregion
-
- #region Private Methods
-
- private byte[] createMaskingKey()
- {
- var key = new byte[4];
- var rand = new Random();
- rand.NextBytes(key);
-
- return key;
- }
-
- private static bool isControl(Opcode opcode)
- {
- return opcode == Opcode.Close || opcode == Opcode.Ping || opcode == Opcode.Pong;
- }
-
- private static bool isData(Opcode opcode)
- {
- return opcode == Opcode.Text || opcode == Opcode.Binary;
- }
-
- private static async Task ReadAsync(byte[] header, Stream stream, bool unmask)
- {
- /* Header */
-
- // FIN
- var fin = (header[0] & 0x80) == 0x80 ? Fin.Final : Fin.More;
- // RSV1
- var rsv1 = (header[0] & 0x40) == 0x40 ? Rsv.On : Rsv.Off;
- // RSV2
- var rsv2 = (header[0] & 0x20) == 0x20 ? Rsv.On : Rsv.Off;
- // RSV3
- var rsv3 = (header[0] & 0x10) == 0x10 ? Rsv.On : Rsv.Off;
- // Opcode
- var opcode = (Opcode)(header[0] & 0x0f);
- // MASK
- var mask = (header[1] & 0x80) == 0x80 ? Mask.Mask : Mask.Unmask;
- // Payload Length
- var payloadLen = (byte)(header[1] & 0x7f);
-
- // Check if correct frame.
- var incorrect = isControl(opcode) && fin == Fin.More
- ? "A control frame is fragmented."
- : !isData(opcode) && rsv1 == Rsv.On
- ? "A non data frame is compressed."
- : null;
-
- if (incorrect != null)
- throw new WebSocketException(CloseStatusCode.IncorrectData, incorrect);
-
- // Check if consistent frame.
- if (isControl(opcode) && payloadLen > 125)
- throw new WebSocketException(
- CloseStatusCode.InconsistentData,
- "The length of payload data of a control frame is greater than 125 bytes.");
-
- var frame = new WebSocketFrame();
- frame._fin = fin;
- frame._rsv1 = rsv1;
- frame._rsv2 = rsv2;
- frame._rsv3 = rsv3;
- frame._opcode = opcode;
- frame._mask = mask;
- frame._payloadLength = payloadLen;
-
- /* Extended Payload Length */
-
- var size = payloadLen < 126
- ? 0
- : payloadLen == 126
- ? 2
- : 8;
-
- var extPayloadLen = size > 0 ? await stream.ReadBytesAsync(size).ConfigureAwait(false) : Array.Empty();
- if (size > 0 && extPayloadLen.Length != size)
- throw new WebSocketException(
- "The 'Extended Payload Length' of a frame cannot be read from the data source.");
-
- frame._extPayloadLength = extPayloadLen;
-
- /* Masking Key */
-
- var masked = mask == Mask.Mask;
- var maskingKey = masked ? await stream.ReadBytesAsync(4).ConfigureAwait(false) : Array.Empty();
- if (masked && maskingKey.Length != 4)
- throw new WebSocketException(
- "The 'Masking Key' of a frame cannot be read from the data source.");
-
- frame._maskingKey = maskingKey;
-
- /* Payload Data */
-
- ulong len = payloadLen < 126
- ? payloadLen
- : payloadLen == 126
- ? extPayloadLen.ToUInt16(ByteOrder.Big)
- : extPayloadLen.ToUInt64(ByteOrder.Big);
-
- byte[] data = null;
- if (len > 0)
- {
- // Check if allowable payload data length.
- if (payloadLen > 126 && len > PayloadData.MaxLength)
- throw new WebSocketException(
- CloseStatusCode.TooBig,
- "The length of 'Payload Data' of a frame is greater than the allowable length.");
-
- data = payloadLen > 126
- ? await stream.ReadBytesAsync((long)len, 1024).ConfigureAwait(false)
- : await stream.ReadBytesAsync((int)len).ConfigureAwait(false);
-
- //if (data.LongLength != (long)len)
- // throw new WebSocketException(
- // "The 'Payload Data' of a frame cannot be read from the data source.");
- }
- else
- {
- data = Array.Empty();
- }
-
- var payload = new PayloadData(data, masked);
- if (masked && unmask)
- {
- payload.Mask(maskingKey);
- frame._mask = Mask.Unmask;
- frame._maskingKey = Array.Empty();
- }
-
- frame._payloadData = payload;
- return frame;
- }
-
- #endregion
-
- #region Internal Methods
-
- internal static WebSocketFrame CreateCloseFrame(Mask mask, byte[] data)
- {
- return new WebSocketFrame(Opcode.Close, mask, new PayloadData(data));
- }
-
- internal static WebSocketFrame CreateCloseFrame(Mask mask, PayloadData payload)
- {
- return new WebSocketFrame(Opcode.Close, mask, payload);
- }
-
- internal static async Task CreateCloseFrameAsync(Mask mask, CloseStatusCode code, string reason)
- {
- return new WebSocketFrame(
- Opcode.Close, mask, new PayloadData(await ((ushort)code).AppendAsync(reason).ConfigureAwait(false)));
- }
-
- internal static WebSocketFrame CreatePingFrame(Mask mask)
- {
- return new WebSocketFrame(Opcode.Ping, mask, new PayloadData());
- }
-
- internal static WebSocketFrame CreatePingFrame(Mask mask, byte[] data)
- {
- return new WebSocketFrame(Opcode.Ping, mask, new PayloadData(data));
- }
-
- internal static WebSocketFrame CreatePongFrame(Mask mask, PayloadData payload)
- {
- return new WebSocketFrame(Opcode.Pong, mask, payload);
- }
-
- internal static WebSocketFrame CreateWebSocketFrame(
- Fin fin, Opcode opcode, Mask mask, byte[] data, bool compressed)
- {
- return new WebSocketFrame(fin, opcode, mask, new PayloadData(data), compressed);
- }
-
- internal static Task ReadAsync(Stream stream)
- => ReadAsync(stream, true);
-
- internal static async Task ReadAsync(Stream stream, bool unmask)
- {
- var header = await stream.ReadBytesAsync(2).ConfigureAwait(false);
- if (header.Length != 2)
- {
- throw new WebSocketException(
- "The header part of a frame cannot be read from the data source.");
- }
-
- return await ReadAsync(header, stream, unmask).ConfigureAwait(false);
- }
-
- internal static async Task ReadAsync(
- Stream stream, bool unmask, Action completed, Action error)
- {
- try
- {
- var header = await stream.ReadBytesAsync(2).ConfigureAwait(false);
- if (header.Length != 2)
- {
- throw new WebSocketException(
- "The header part of a frame cannot be read from the data source.");
- }
-
- var frame = await ReadAsync(header, stream, unmask).ConfigureAwait(false);
- completed?.Invoke(frame);
- }
- catch (Exception ex)
- {
- error.Invoke(ex);
- }
- }
-
- #endregion
-
- #region Public Methods
-
- public IEnumerator GetEnumerator()
- {
- foreach (var b in ToByteArray())
- yield return b;
- }
-
- public void Print(bool dumped)
- {
- //Console.WriteLine(dumped ? dump(this) : print(this));
- }
-
- public byte[] ToByteArray()
- {
- using (var buff = new MemoryStream())
- {
- var header = (int)_fin;
- header = (header << 1) + (int)_rsv1;
- header = (header << 1) + (int)_rsv2;
- header = (header << 1) + (int)_rsv3;
- header = (header << 4) + (int)_opcode;
- header = (header << 1) + (int)_mask;
- header = (header << 7) + (int)_payloadLength;
- buff.Write(((ushort)header).ToByteArrayInternally(ByteOrder.Big), 0, 2);
-
- if (_payloadLength > 125)
- buff.Write(_extPayloadLength, 0, _extPayloadLength.Length);
-
- if (_mask == Mask.Mask)
- buff.Write(_maskingKey, 0, _maskingKey.Length);
-
- if (_payloadLength > 0)
- {
- var payload = _payloadData.ToByteArray();
- if (_payloadLength < 127)
- buff.Write(payload, 0, payload.Length);
- else
- buff.WriteBytes(payload);
- }
-
- return buff.ToArray();
- }
- }
-
- public override string ToString()
- {
- return BitConverter.ToString(ToByteArray());
- }
-
- #endregion
-
- #region Explicitly Implemented Interface Members
-
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
-
- #endregion
- }
-}