mirror of
https://github.com/jellyfin/jellyfin.git
synced 2025-07-08 10:44:23 -04:00
commit
b7ae044e65
@ -94,7 +94,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts
|
|||||||
|
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
var _ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
|
_ = StartStreaming(response, taskCompletionSource, LiveStreamCancellationTokenSource.Token);
|
||||||
|
|
||||||
//OpenedMediaSource.Protocol = MediaProtocol.File;
|
//OpenedMediaSource.Protocol = MediaProtocol.File;
|
||||||
//OpenedMediaSource.Path = tempFile;
|
//OpenedMediaSource.Path = tempFile;
|
||||||
|
@ -282,7 +282,7 @@ namespace Jellyfin.Drawing.Skia
|
|||||||
var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack);
|
var bitmap = new SKBitmap(codec.Info.Width, codec.Info.Height, !requiresTransparencyHack);
|
||||||
|
|
||||||
// decode
|
// decode
|
||||||
var _ = codec.GetPixels(bitmap.Info, bitmap.GetPixels());
|
_ = codec.GetPixels(bitmap.Info, bitmap.GetPixels());
|
||||||
|
|
||||||
origin = codec.EncodedOrigin;
|
origin = codec.EncodedOrigin;
|
||||||
|
|
||||||
|
@ -18,6 +18,8 @@ namespace Jellyfin.Server
|
|||||||
|
|
||||||
public override bool CanSelfRestart => StartupOptions.RestartPath != null;
|
public override bool CanSelfRestart => StartupOptions.RestartPath != null;
|
||||||
|
|
||||||
|
protected override bool SupportsDualModeSockets => true;
|
||||||
|
|
||||||
protected override void RestartInternal() => Program.Restart();
|
protected override void RestartInternal() => Program.Restart();
|
||||||
|
|
||||||
protected override IEnumerable<Assembly> GetAssembliesWithPartsInternal()
|
protected override IEnumerable<Assembly> GetAssembliesWithPartsInternal()
|
||||||
@ -27,8 +29,6 @@ namespace Jellyfin.Server
|
|||||||
|
|
||||||
protected override void ShutdownInternal() => Program.Shutdown();
|
protected override void ShutdownInternal() => Program.Shutdown();
|
||||||
|
|
||||||
protected override bool SupportsDualModeSockets => true;
|
|
||||||
|
|
||||||
protected override IHttpListener CreateHttpListener()
|
protected override IHttpListener CreateHttpListener()
|
||||||
=> new WebSocketSharpListener(
|
=> new WebSocketSharpListener(
|
||||||
Logger,
|
Logger,
|
||||||
@ -39,7 +39,6 @@ namespace Jellyfin.Server
|
|||||||
CryptographyProvider,
|
CryptographyProvider,
|
||||||
SupportsDualModeSockets,
|
SupportsDualModeSockets,
|
||||||
FileSystemManager,
|
FileSystemManager,
|
||||||
EnvironmentInfo
|
EnvironmentInfo);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,11 +5,14 @@
|
|||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp2.1</TargetFramework>
|
<TargetFramework>netcoreapp2.1</TargetFramework>
|
||||||
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<!-- We need C# 7.1 for async main-->
|
<!-- We need C# 7.1 for async main-->
|
||||||
<LangVersion>latest</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
|
<!-- Disable documentation warnings (for now) -->
|
||||||
|
<NoWarn>SA1600;CS1591</NoWarn>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
@ -57,13 +57,28 @@ namespace Jellyfin.Server
|
|||||||
errs => Task.FromResult(0)).ConfigureAwait(false);
|
errs => Task.FromResult(0)).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void Shutdown()
|
||||||
|
{
|
||||||
|
if (!_tokenSource.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
_tokenSource.Cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Restart()
|
||||||
|
{
|
||||||
|
_restartOnShutdown = true;
|
||||||
|
|
||||||
|
Shutdown();
|
||||||
|
}
|
||||||
|
|
||||||
private static async Task StartApp(StartupOptions options)
|
private static async Task StartApp(StartupOptions options)
|
||||||
{
|
{
|
||||||
ServerApplicationPaths appPaths = CreateApplicationPaths(options);
|
ServerApplicationPaths appPaths = CreateApplicationPaths(options);
|
||||||
|
|
||||||
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
|
// $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
|
||||||
Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
|
Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);
|
||||||
await CreateLogger(appPaths);
|
await CreateLogger(appPaths).ConfigureAwait(false);
|
||||||
_logger = _loggerFactory.CreateLogger("Main");
|
_logger = _loggerFactory.CreateLogger("Main");
|
||||||
|
|
||||||
AppDomain.CurrentDomain.UnhandledException += (sender, e)
|
AppDomain.CurrentDomain.UnhandledException += (sender, e)
|
||||||
@ -76,6 +91,7 @@ namespace Jellyfin.Server
|
|||||||
{
|
{
|
||||||
return; // Already shutting down
|
return; // Already shutting down
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Cancel = true;
|
e.Cancel = true;
|
||||||
_logger.LogInformation("Ctrl+C, shutting down");
|
_logger.LogInformation("Ctrl+C, shutting down");
|
||||||
Environment.ExitCode = 128 + 2;
|
Environment.ExitCode = 128 + 2;
|
||||||
@ -89,6 +105,7 @@ namespace Jellyfin.Server
|
|||||||
{
|
{
|
||||||
return; // Already shutting down
|
return; // Already shutting down
|
||||||
}
|
}
|
||||||
|
|
||||||
_logger.LogInformation("Received a SIGTERM signal, shutting down");
|
_logger.LogInformation("Received a SIGTERM signal, shutting down");
|
||||||
Environment.ExitCode = 128 + 15;
|
Environment.ExitCode = 128 + 15;
|
||||||
Shutdown();
|
Shutdown();
|
||||||
@ -102,7 +119,7 @@ namespace Jellyfin.Server
|
|||||||
SQLitePCL.Batteries_V2.Init();
|
SQLitePCL.Batteries_V2.Init();
|
||||||
|
|
||||||
// Allow all https requests
|
// Allow all https requests
|
||||||
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; });
|
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(delegate { return true; } );
|
||||||
|
|
||||||
var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, null, appPaths.TempDirectory, true);
|
var fileSystem = new ManagedFileSystem(_loggerFactory, environmentInfo, null, appPaths.TempDirectory, true);
|
||||||
|
|
||||||
@ -115,18 +132,18 @@ namespace Jellyfin.Server
|
|||||||
new NullImageEncoder(),
|
new NullImageEncoder(),
|
||||||
new NetworkManager(_loggerFactory, environmentInfo)))
|
new NetworkManager(_loggerFactory, environmentInfo)))
|
||||||
{
|
{
|
||||||
await appHost.Init(new ServiceCollection());
|
await appHost.Init(new ServiceCollection()).ConfigureAwait(false);
|
||||||
|
|
||||||
appHost.ImageProcessor.ImageEncoder = GetImageEncoder(fileSystem, appPaths, appHost.LocalizationManager);
|
appHost.ImageProcessor.ImageEncoder = GetImageEncoder(fileSystem, appPaths, appHost.LocalizationManager);
|
||||||
|
|
||||||
await appHost.RunStartupTasks();
|
await appHost.RunStartupTasks().ConfigureAwait(false);
|
||||||
|
|
||||||
// TODO: read input for a stop command
|
// TODO: read input for a stop command
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Block main thread until shutdown
|
// Block main thread until shutdown
|
||||||
await Task.Delay(-1, _tokenSource.Token);
|
await Task.Delay(-1, _tokenSource.Token).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
catch (TaskCanceledException)
|
catch (TaskCanceledException)
|
||||||
{
|
{
|
||||||
@ -146,7 +163,7 @@ namespace Jellyfin.Server
|
|||||||
/// for everything else the XDG approach is followed:
|
/// for everything else the XDG approach is followed:
|
||||||
/// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
/// https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="options"></param>
|
/// <param name="options">StartupOptions</param>
|
||||||
/// <returns>ServerApplicationPaths</returns>
|
/// <returns>ServerApplicationPaths</returns>
|
||||||
private static ServerApplicationPaths CreateApplicationPaths(StartupOptions options)
|
private static ServerApplicationPaths CreateApplicationPaths(StartupOptions options)
|
||||||
{
|
{
|
||||||
@ -308,6 +325,7 @@ namespace Jellyfin.Server
|
|||||||
await rscstr.CopyToAsync(fstr).ConfigureAwait(false);
|
await rscstr.CopyToAsync(fstr).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var configuration = new ConfigurationBuilder()
|
var configuration = new ConfigurationBuilder()
|
||||||
.SetBasePath(appPaths.ConfigurationDirectoryPath)
|
.SetBasePath(appPaths.ConfigurationDirectoryPath)
|
||||||
.AddJsonFile("logging.json")
|
.AddJsonFile("logging.json")
|
||||||
@ -335,7 +353,7 @@ namespace Jellyfin.Server
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static IImageEncoder GetImageEncoder(
|
private static IImageEncoder GetImageEncoder(
|
||||||
IFileSystem fileSystem,
|
IFileSystem fileSystem,
|
||||||
IApplicationPaths appPaths,
|
IApplicationPaths appPaths,
|
||||||
ILocalizationManager localizationManager)
|
ILocalizationManager localizationManager)
|
||||||
@ -376,26 +394,12 @@ namespace Jellyfin.Server
|
|||||||
{
|
{
|
||||||
return MediaBrowser.Model.System.OperatingSystem.BSD;
|
return MediaBrowser.Model.System.OperatingSystem.BSD;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Exception($"Can't resolve OS with description: '{osDescription}'");
|
throw new Exception($"Can't resolve OS with description: '{osDescription}'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void Shutdown()
|
|
||||||
{
|
|
||||||
if (!_tokenSource.IsCancellationRequested)
|
|
||||||
{
|
|
||||||
_tokenSource.Cancel();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void Restart()
|
|
||||||
{
|
|
||||||
_restartOnShutdown = true;
|
|
||||||
|
|
||||||
Shutdown();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void StartNewInstance(StartupOptions options)
|
private static void StartNewInstance(StartupOptions options)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Starting new instance");
|
_logger.LogInformation("Starting new instance");
|
||||||
|
@ -13,7 +13,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
{
|
{
|
||||||
internal static string GetParameter(string header, string attr)
|
internal static string GetParameter(string header, string attr)
|
||||||
{
|
{
|
||||||
int ap = header.IndexOf(attr);
|
int ap = header.IndexOf(attr, StringComparison.Ordinal);
|
||||||
if (ap == -1)
|
if (ap == -1)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@ -82,9 +82,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//
|
|
||||||
// We use a substream, as in 2.x we will support large uploads streamed to disk,
|
// We use a substream, as in 2.x we will support large uploads streamed to disk,
|
||||||
//
|
|
||||||
var sub = new HttpPostedFile(e.Filename, e.ContentType, input, e.Start, e.Length);
|
var sub = new HttpPostedFile(e.Filename, e.ContentType, input, e.Start, e.Length);
|
||||||
files[e.Name] = sub;
|
files[e.Name] = sub;
|
||||||
}
|
}
|
||||||
@ -127,8 +125,12 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
|
|
||||||
public string Authorization => string.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"];
|
public string Authorization => string.IsNullOrEmpty(request.Headers["Authorization"]) ? null : request.Headers["Authorization"];
|
||||||
|
|
||||||
protected bool validate_cookies, validate_query_string, validate_form;
|
protected bool validate_cookies { get; set; }
|
||||||
protected bool checked_cookies, checked_query_string, checked_form;
|
protected bool validate_query_string { get; set; }
|
||||||
|
protected bool validate_form { get; set; }
|
||||||
|
protected bool checked_cookies { get; set; }
|
||||||
|
protected bool checked_query_string { get; set; }
|
||||||
|
protected bool checked_form { get; set; }
|
||||||
|
|
||||||
private static void ThrowValidationException(string name, string key, string value)
|
private static void ThrowValidationException(string name, string key, string value)
|
||||||
{
|
{
|
||||||
@ -138,8 +140,12 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
v = v.Substring(0, 16) + "...\"";
|
v = v.Substring(0, 16) + "...\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
string msg = string.Format("A potentially dangerous Request.{0} value was " +
|
string msg = string.Format(
|
||||||
"detected from the client ({1}={2}).", name, key, v);
|
CultureInfo.InvariantCulture,
|
||||||
|
"A potentially dangerous Request.{0} value was detected from the client ({1}={2}).",
|
||||||
|
name,
|
||||||
|
key,
|
||||||
|
v);
|
||||||
|
|
||||||
throw new Exception(msg);
|
throw new Exception(msg);
|
||||||
}
|
}
|
||||||
@ -179,6 +185,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
for (int idx = 1; idx < len; idx++)
|
for (int idx = 1; idx < len; idx++)
|
||||||
{
|
{
|
||||||
char next = val[idx];
|
char next = val[idx];
|
||||||
|
|
||||||
// See http://secunia.com/advisories/14325
|
// See http://secunia.com/advisories/14325
|
||||||
if (current == '<' || current == '\xff1c')
|
if (current == '<' || current == '\xff1c')
|
||||||
{
|
{
|
||||||
@ -256,6 +263,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
value.Append((char)c);
|
value.Append((char)c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
{
|
{
|
||||||
AddRawKeyValue(form, key, value);
|
AddRawKeyValue(form, key, value);
|
||||||
@ -271,6 +279,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
key.Append((char)c);
|
key.Append((char)c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c == -1)
|
if (c == -1)
|
||||||
{
|
{
|
||||||
AddRawKeyValue(form, key, value);
|
AddRawKeyValue(form, key, value);
|
||||||
@ -308,6 +317,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
result.Append(key);
|
result.Append(key);
|
||||||
result.Append('=');
|
result.Append('=');
|
||||||
}
|
}
|
||||||
|
|
||||||
result.Append(pair.Value);
|
result.Append(pair.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -429,13 +439,13 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
real = position + d;
|
real = position + d;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
throw new ArgumentException(nameof(origin));
|
throw new ArgumentException("Unknown SeekOrigin value", nameof(origin));
|
||||||
}
|
}
|
||||||
|
|
||||||
long virt = real - offset;
|
long virt = real - offset;
|
||||||
if (virt < 0 || virt > Length)
|
if (virt < 0 || virt > Length)
|
||||||
{
|
{
|
||||||
throw new ArgumentException();
|
throw new ArgumentException("Invalid position", nameof(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
position = s.Seek(real, SeekOrigin.Begin);
|
position = s.Seek(real, SeekOrigin.Begin);
|
||||||
@ -491,11 +501,6 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
public Stream InputStream => stream;
|
public Stream InputStream => stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Helpers
|
|
||||||
{
|
|
||||||
public static readonly CultureInfo InvariantCulture = CultureInfo.InvariantCulture;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class StrUtils
|
internal static class StrUtils
|
||||||
{
|
{
|
||||||
public static bool StartsWith(string str1, string str2, bool ignore_case)
|
public static bool StartsWith(string str1, string str2, bool ignore_case)
|
||||||
@ -533,12 +538,17 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
|
|
||||||
public class Element
|
public class Element
|
||||||
{
|
{
|
||||||
public string ContentType;
|
public string ContentType { get; set; }
|
||||||
public string Name;
|
|
||||||
public string Filename;
|
public string Name { get; set; }
|
||||||
public Encoding Encoding;
|
|
||||||
public long Start;
|
public string Filename { get; set; }
|
||||||
public long Length;
|
|
||||||
|
public Encoding Encoding { get; set; }
|
||||||
|
|
||||||
|
public long Start { get; set; }
|
||||||
|
|
||||||
|
public long Length { get; set; }
|
||||||
|
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
@ -547,15 +557,23 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Stream data;
|
private const byte LF = (byte)'\n';
|
||||||
private string boundary;
|
|
||||||
private byte[] boundary_bytes;
|
|
||||||
private byte[] buffer;
|
|
||||||
private bool at_eof;
|
|
||||||
private Encoding encoding;
|
|
||||||
private StringBuilder sb;
|
|
||||||
|
|
||||||
private const byte LF = (byte)'\n', CR = (byte)'\r';
|
private const byte CR = (byte)'\r';
|
||||||
|
|
||||||
|
private Stream data;
|
||||||
|
|
||||||
|
private string boundary;
|
||||||
|
|
||||||
|
private byte[] boundaryBytes;
|
||||||
|
|
||||||
|
private byte[] buffer;
|
||||||
|
|
||||||
|
private bool atEof;
|
||||||
|
|
||||||
|
private Encoding encoding;
|
||||||
|
|
||||||
|
private StringBuilder sb;
|
||||||
|
|
||||||
// See RFC 2046
|
// See RFC 2046
|
||||||
// In the case of multipart entities, in which one or more different
|
// In the case of multipart entities, in which one or more different
|
||||||
@ -570,18 +588,48 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
public HttpMultipart(Stream data, string b, Encoding encoding)
|
public HttpMultipart(Stream data, string b, Encoding encoding)
|
||||||
{
|
{
|
||||||
this.data = data;
|
this.data = data;
|
||||||
//DB: 30/01/11: cannot set or read the Position in HttpListener in Win.NET
|
|
||||||
//var ms = new MemoryStream(32 * 1024);
|
|
||||||
//data.CopyTo(ms);
|
|
||||||
//this.data = ms;
|
|
||||||
|
|
||||||
boundary = b;
|
boundary = b;
|
||||||
boundary_bytes = encoding.GetBytes(b);
|
boundaryBytes = encoding.GetBytes(b);
|
||||||
buffer = new byte[boundary_bytes.Length + 2]; // CRLF or '--'
|
buffer = new byte[boundaryBytes.Length + 2]; // CRLF or '--'
|
||||||
this.encoding = encoding;
|
this.encoding = encoding;
|
||||||
sb = new StringBuilder();
|
sb = new StringBuilder();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Element ReadNextElement()
|
||||||
|
{
|
||||||
|
if (atEof || ReadBoundary())
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var elem = new Element();
|
||||||
|
string header;
|
||||||
|
while ((header = ReadHeaders()) != null)
|
||||||
|
{
|
||||||
|
if (StrUtils.StartsWith(header, "Content-Disposition:", true))
|
||||||
|
{
|
||||||
|
elem.Name = GetContentDispositionAttribute(header, "name");
|
||||||
|
elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename"));
|
||||||
|
}
|
||||||
|
else if (StrUtils.StartsWith(header, "Content-Type:", true))
|
||||||
|
{
|
||||||
|
elem.ContentType = header.Substring("Content-Type:".Length).Trim();
|
||||||
|
elem.Encoding = GetEncoding(elem.ContentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
long start = data.Position;
|
||||||
|
elem.Start = start;
|
||||||
|
long pos = MoveToNextBoundary();
|
||||||
|
if (pos == -1)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
elem.Length = pos - start;
|
||||||
|
return elem;
|
||||||
|
}
|
||||||
|
|
||||||
private string ReadLine()
|
private string ReadLine()
|
||||||
{
|
{
|
||||||
// CRLF or LF are ok as line endings.
|
// CRLF or LF are ok as line endings.
|
||||||
@ -600,6 +648,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
got_cr = b == CR;
|
got_cr = b == CR;
|
||||||
sb.Append((char)b);
|
sb.Append((char)b);
|
||||||
}
|
}
|
||||||
@ -769,7 +818,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!CompareBytes(boundary_bytes, buffer))
|
if (!CompareBytes(boundaryBytes, buffer))
|
||||||
{
|
{
|
||||||
state = 0;
|
state = 0;
|
||||||
data.Position = retval + 2;
|
data.Position = retval + 2;
|
||||||
@ -785,7 +834,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
|
|
||||||
if (buffer[bl - 2] == '-' && buffer[bl - 1] == '-')
|
if (buffer[bl - 2] == '-' && buffer[bl - 1] == '-')
|
||||||
{
|
{
|
||||||
at_eof = true;
|
atEof = true;
|
||||||
}
|
}
|
||||||
else if (buffer[bl - 2] != CR || buffer[bl - 1] != LF)
|
else if (buffer[bl - 2] != CR || buffer[bl - 1] != LF)
|
||||||
{
|
{
|
||||||
@ -800,6 +849,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
c = data.ReadByte();
|
c = data.ReadByte();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
data.Position = retval + 2;
|
data.Position = retval + 2;
|
||||||
if (got_cr)
|
if (got_cr)
|
||||||
{
|
{
|
||||||
@ -818,42 +868,6 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Element ReadNextElement()
|
|
||||||
{
|
|
||||||
if (at_eof || ReadBoundary())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
var elem = new Element();
|
|
||||||
string header;
|
|
||||||
while ((header = ReadHeaders()) != null)
|
|
||||||
{
|
|
||||||
if (StrUtils.StartsWith(header, "Content-Disposition:", true))
|
|
||||||
{
|
|
||||||
elem.Name = GetContentDispositionAttribute(header, "name");
|
|
||||||
elem.Filename = StripPath(GetContentDispositionAttributeWithEncoding(header, "filename"));
|
|
||||||
}
|
|
||||||
else if (StrUtils.StartsWith(header, "Content-Type:", true))
|
|
||||||
{
|
|
||||||
elem.ContentType = header.Substring("Content-Type:".Length).Trim();
|
|
||||||
elem.Encoding = GetEncoding(elem.ContentType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
long start = 0;
|
|
||||||
start = data.Position;
|
|
||||||
elem.Start = start;
|
|
||||||
long pos = MoveToNextBoundary();
|
|
||||||
if (pos == -1)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
elem.Length = pos - start;
|
|
||||||
return elem;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string StripPath(string path)
|
private static string StripPath(string path)
|
||||||
{
|
{
|
||||||
if (path == null || path.Length == 0)
|
if (path == null || path.Length == 0)
|
||||||
|
@ -24,6 +24,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
|
|
||||||
private TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
|
private TaskCompletionSource<bool> _taskCompletionSource = new TaskCompletionSource<bool>();
|
||||||
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
|
private readonly CancellationTokenSource _cancellationTokenSource = new CancellationTokenSource();
|
||||||
|
private bool _disposed = false;
|
||||||
|
|
||||||
public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger)
|
public SharpWebSocket(SocketHttpListener.WebSocket socket, ILogger logger)
|
||||||
{
|
{
|
||||||
@ -40,9 +41,9 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
WebSocket = socket;
|
WebSocket = socket;
|
||||||
|
|
||||||
socket.OnMessage += socket_OnMessage;
|
socket.OnMessage += OnSocketMessage;
|
||||||
socket.OnClose += socket_OnClose;
|
socket.OnClose += OnSocketClose;
|
||||||
socket.OnError += socket_OnError;
|
socket.OnError += OnSocketError;
|
||||||
|
|
||||||
WebSocket.ConnectAsServer();
|
WebSocket.ConnectAsServer();
|
||||||
}
|
}
|
||||||
@ -52,29 +53,22 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
return _taskCompletionSource.Task;
|
return _taskCompletionSource.Task;
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_OnError(object sender, SocketHttpListener.ErrorEventArgs e)
|
private void OnSocketError(object sender, SocketHttpListener.ErrorEventArgs e)
|
||||||
{
|
{
|
||||||
_logger.LogError("Error in SharpWebSocket: {Message}", e.Message ?? string.Empty);
|
_logger.LogError("Error in SharpWebSocket: {Message}", e.Message ?? string.Empty);
|
||||||
//Closed?.Invoke(this, EventArgs.Empty);
|
|
||||||
|
// Closed?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_OnClose(object sender, SocketHttpListener.CloseEventArgs e)
|
private void OnSocketClose(object sender, SocketHttpListener.CloseEventArgs e)
|
||||||
{
|
{
|
||||||
_taskCompletionSource.TrySetResult(true);
|
_taskCompletionSource.TrySetResult(true);
|
||||||
|
|
||||||
Closed?.Invoke(this, EventArgs.Empty);
|
Closed?.Invoke(this, EventArgs.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
void socket_OnMessage(object sender, SocketHttpListener.MessageEventArgs e)
|
private void OnSocketMessage(object sender, SocketHttpListener.MessageEventArgs e)
|
||||||
{
|
{
|
||||||
//if (!string.IsNullOrEmpty(e.Data))
|
|
||||||
//{
|
|
||||||
// if (OnReceive != null)
|
|
||||||
// {
|
|
||||||
// OnReceive(e.Data);
|
|
||||||
// }
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
if (OnReceiveBytes != null)
|
if (OnReceiveBytes != null)
|
||||||
{
|
{
|
||||||
OnReceiveBytes(e.RawData);
|
OnReceiveBytes(e.RawData);
|
||||||
@ -117,6 +111,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -125,16 +120,23 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
/// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||||
protected virtual void Dispose(bool dispose)
|
protected virtual void Dispose(bool dispose)
|
||||||
{
|
{
|
||||||
|
if (_disposed)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (dispose)
|
if (dispose)
|
||||||
{
|
{
|
||||||
WebSocket.OnMessage -= socket_OnMessage;
|
WebSocket.OnMessage -= OnSocketMessage;
|
||||||
WebSocket.OnClose -= socket_OnClose;
|
WebSocket.OnClose -= OnSocketClose;
|
||||||
WebSocket.OnError -= socket_OnError;
|
WebSocket.OnError -= OnSocketError;
|
||||||
|
|
||||||
_cancellationTokenSource.Cancel();
|
_cancellationTokenSource.Cancel();
|
||||||
|
|
||||||
WebSocket.Close();
|
WebSocket.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -142,11 +144,5 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <value>The receive action.</value>
|
/// <value>The receive action.</value>
|
||||||
public Action<byte[]> OnReceiveBytes { get; set; }
|
public Action<byte[]> OnReceiveBytes { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the on receive.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>The on receive.</value>
|
|
||||||
public Action<string> OnReceive { get; set; }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,9 +34,16 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
|
private CancellationTokenSource _disposeCancellationTokenSource = new CancellationTokenSource();
|
||||||
private CancellationToken _disposeCancellationToken;
|
private CancellationToken _disposeCancellationToken;
|
||||||
|
|
||||||
public WebSocketSharpListener(ILogger logger, X509Certificate certificate, IStreamHelper streamHelper,
|
public WebSocketSharpListener(
|
||||||
INetworkManager networkManager, ISocketFactory socketFactory, ICryptoProvider cryptoProvider,
|
ILogger logger,
|
||||||
bool enableDualMode, IFileSystem fileSystem, IEnvironmentInfo environment)
|
X509Certificate certificate,
|
||||||
|
IStreamHelper streamHelper,
|
||||||
|
INetworkManager networkManager,
|
||||||
|
ISocketFactory socketFactory,
|
||||||
|
ICryptoProvider cryptoProvider,
|
||||||
|
bool enableDualMode,
|
||||||
|
IFileSystem fileSystem,
|
||||||
|
IEnvironmentInfo environment)
|
||||||
{
|
{
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_certificate = certificate;
|
_certificate = certificate;
|
||||||
@ -61,7 +68,9 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
public void Start(IEnumerable<string> urlPrefixes)
|
public void Start(IEnumerable<string> urlPrefixes)
|
||||||
{
|
{
|
||||||
if (_listener == null)
|
if (_listener == null)
|
||||||
|
{
|
||||||
_listener = new HttpListener(_logger, _cryptoProvider, _socketFactory, _networkManager, _streamHelper, _fileSystem, _environment);
|
_listener = new HttpListener(_logger, _cryptoProvider, _socketFactory, _networkManager, _streamHelper, _fileSystem, _environment);
|
||||||
|
}
|
||||||
|
|
||||||
_listener.EnableDualMode = _enableDualMode;
|
_listener.EnableDualMode = _enableDualMode;
|
||||||
|
|
||||||
@ -83,15 +92,18 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
|
|
||||||
private void ProcessContext(HttpListenerContext context)
|
private void ProcessContext(HttpListenerContext context)
|
||||||
{
|
{
|
||||||
var _ = Task.Run(async () => await InitTask(context, _disposeCancellationToken));
|
_ = Task.Run(async () => await InitTask(context, _disposeCancellationToken).ConfigureAwait(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LogRequest(ILogger logger, HttpListenerRequest request)
|
private static void LogRequest(ILogger logger, HttpListenerRequest request)
|
||||||
{
|
{
|
||||||
var url = request.Url.ToString();
|
var url = request.Url.ToString();
|
||||||
|
|
||||||
logger.LogInformation("{0} {1}. UserAgent: {2}",
|
logger.LogInformation(
|
||||||
request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod, url, request.UserAgent ?? string.Empty);
|
"{0} {1}. UserAgent: {2}",
|
||||||
|
request.IsWebSocketRequest ? "WS" : "HTTP " + request.HttpMethod,
|
||||||
|
url,
|
||||||
|
request.UserAgent ?? string.Empty);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task InitTask(HttpListenerContext context, CancellationToken cancellationToken)
|
private Task InitTask(HttpListenerContext context, CancellationToken cancellationToken)
|
||||||
@ -201,7 +213,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
}
|
}
|
||||||
catch (ObjectDisposedException)
|
catch (ObjectDisposedException)
|
||||||
{
|
{
|
||||||
//TODO Investigate and properly fix.
|
// TODO: Investigate and properly fix.
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@ -223,38 +235,39 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
public Task Stop()
|
public Task Stop()
|
||||||
{
|
{
|
||||||
_disposeCancellationTokenSource.Cancel();
|
_disposeCancellationTokenSource.Cancel();
|
||||||
|
_listener?.Close();
|
||||||
if (_listener != null)
|
|
||||||
{
|
|
||||||
_listener.Close();
|
|
||||||
}
|
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the unmanaged resources and disposes of the managed resources used.
|
||||||
|
/// </summary>
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
Dispose(true);
|
Dispose(true);
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool _disposed;
|
private bool _disposed;
|
||||||
private readonly object _disposeLock = new object();
|
|
||||||
|
/// <summary>
|
||||||
|
/// Releases the unmanaged resources and disposes of the managed resources used.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="disposing">Whether or not the managed resources should be disposed</param>
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
{
|
{
|
||||||
if (_disposed) return;
|
if (_disposed)
|
||||||
|
|
||||||
lock (_disposeLock)
|
|
||||||
{
|
{
|
||||||
if (_disposed) return;
|
return;
|
||||||
|
|
||||||
if (disposing)
|
|
||||||
{
|
|
||||||
Stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
//release unmanaged resources here...
|
|
||||||
_disposed = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (disposing)
|
||||||
|
{
|
||||||
|
Stop().GetAwaiter().GetResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
_disposed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Emby.Server.Implementations.HttpServer;
|
using Emby.Server.Implementations.HttpServer;
|
||||||
@ -24,7 +25,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
this.request = httpContext.Request;
|
this.request = httpContext.Request;
|
||||||
this.response = new WebSocketSharpResponse(logger, httpContext.Response, this);
|
this.response = new WebSocketSharpResponse(logger, httpContext.Response, this);
|
||||||
|
|
||||||
//HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes[0]);
|
// HandlerFactoryPath = GetHandlerPathIfAny(UrlPrefixes[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetHandlerPathIfAny(string listenerUrl)
|
private static string GetHandlerPathIfAny(string listenerUrl)
|
||||||
@ -41,7 +42,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
}
|
}
|
||||||
|
|
||||||
var startHostUrl = listenerUrl.Substring(pos + "://".Length);
|
var startHostUrl = listenerUrl.Substring(pos + "://".Length);
|
||||||
var endPos = startHostUrl.IndexOf('/');
|
var endPos = startHostUrl.IndexOf('/', StringComparison.Ordinal);
|
||||||
if (endPos == -1)
|
if (endPos == -1)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@ -69,9 +70,11 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
|
|
||||||
public string UserHostAddress => request.UserHostAddress;
|
public string UserHostAddress => request.UserHostAddress;
|
||||||
|
|
||||||
public string XForwardedFor => string.IsNullOrEmpty(request.Headers["X-Forwarded-For"]) ? null : request.Headers["X-Forwarded-For"];
|
public string XForwardedFor
|
||||||
|
=> string.IsNullOrEmpty(request.Headers["X-Forwarded-For"]) ? null : request.Headers["X-Forwarded-For"];
|
||||||
|
|
||||||
public int? XForwardedPort => string.IsNullOrEmpty(request.Headers["X-Forwarded-Port"]) ? (int?)null : int.Parse(request.Headers["X-Forwarded-Port"]);
|
public int? XForwardedPort
|
||||||
|
=> string.IsNullOrEmpty(request.Headers["X-Forwarded-Port"]) ? (int?)null : int.Parse(request.Headers["X-Forwarded-Port"], CultureInfo.InvariantCulture);
|
||||||
|
|
||||||
public string XForwardedProtocol => string.IsNullOrEmpty(request.Headers["X-Forwarded-Proto"]) ? null : request.Headers["X-Forwarded-Proto"];
|
public string XForwardedProtocol => string.IsNullOrEmpty(request.Headers["X-Forwarded-Proto"]) ? null : request.Headers["X-Forwarded-Proto"];
|
||||||
|
|
||||||
@ -107,6 +110,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
switch (crlf)
|
switch (crlf)
|
||||||
{
|
{
|
||||||
case 0:
|
case 0:
|
||||||
|
{
|
||||||
if (c == '\r')
|
if (c == '\r')
|
||||||
{
|
{
|
||||||
crlf = 1;
|
crlf = 1;
|
||||||
@ -121,29 +125,39 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
{
|
{
|
||||||
throw new ArgumentException("net_WebHeaderInvalidControlChars");
|
throw new ArgumentException("net_WebHeaderInvalidControlChars");
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
|
{
|
||||||
if (c == '\n')
|
if (c == '\n')
|
||||||
{
|
{
|
||||||
crlf = 2;
|
crlf = 2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException("net_WebHeaderInvalidCRLFChars");
|
throw new ArgumentException("net_WebHeaderInvalidCRLFChars");
|
||||||
|
}
|
||||||
|
|
||||||
case 2:
|
case 2:
|
||||||
|
{
|
||||||
if (c == ' ' || c == '\t')
|
if (c == ' ' || c == '\t')
|
||||||
{
|
{
|
||||||
crlf = 0;
|
crlf = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException("net_WebHeaderInvalidCRLFChars");
|
throw new ArgumentException("net_WebHeaderInvalidCRLFChars");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (crlf != 0)
|
if (crlf != 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("net_WebHeaderInvalidCRLFChars");
|
throw new ArgumentException("net_WebHeaderInvalidCRLFChars");
|
||||||
}
|
}
|
||||||
|
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,6 +170,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,6 +358,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
this.pathInfo = System.Net.WebUtility.UrlDecode(pathInfo);
|
this.pathInfo = System.Net.WebUtility.UrlDecode(pathInfo);
|
||||||
this.pathInfo = NormalizePathInfo(pathInfo, mode);
|
this.pathInfo = NormalizePathInfo(pathInfo, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.pathInfo;
|
return this.pathInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -444,7 +460,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
|
|
||||||
public string ContentType => request.ContentType;
|
public string ContentType => request.ContentType;
|
||||||
|
|
||||||
public Encoding contentEncoding;
|
private Encoding contentEncoding;
|
||||||
public Encoding ContentEncoding
|
public Encoding ContentEncoding
|
||||||
{
|
{
|
||||||
get => contentEncoding ?? request.ContentEncoding;
|
get => contentEncoding ?? request.ContentEncoding;
|
||||||
@ -502,6 +518,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return httpFiles;
|
return httpFiles;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,12 @@ using HttpListenerResponse = SocketHttpListener.Net.HttpListenerResponse;
|
|||||||
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
|
using IHttpResponse = MediaBrowser.Model.Services.IHttpResponse;
|
||||||
using IRequest = MediaBrowser.Model.Services.IRequest;
|
using IRequest = MediaBrowser.Model.Services.IRequest;
|
||||||
|
|
||||||
|
|
||||||
namespace Jellyfin.Server.SocketSharp
|
namespace Jellyfin.Server.SocketSharp
|
||||||
{
|
{
|
||||||
public class WebSocketSharpResponse : IHttpResponse
|
public class WebSocketSharpResponse : IHttpResponse
|
||||||
{
|
{
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
|
|
||||||
private readonly HttpListenerResponse _response;
|
private readonly HttpListenerResponse _response;
|
||||||
|
|
||||||
public WebSocketSharpResponse(ILogger logger, HttpListenerResponse response, IRequest request)
|
public WebSocketSharpResponse(ILogger logger, HttpListenerResponse response, IRequest request)
|
||||||
@ -30,7 +30,9 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
}
|
}
|
||||||
|
|
||||||
public IRequest Request { get; private set; }
|
public IRequest Request { get; private set; }
|
||||||
|
|
||||||
public Dictionary<string, object> Items { get; private set; }
|
public Dictionary<string, object> Items { get; private set; }
|
||||||
|
|
||||||
public object OriginalResponse => _response;
|
public object OriginalResponse => _response;
|
||||||
|
|
||||||
public int StatusCode
|
public int StatusCode
|
||||||
@ -51,7 +53,7 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
set => _response.ContentType = value;
|
set => _response.ContentType = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
//public ICookies Cookies { get; set; }
|
public QueryParamCollection Headers => _response.Headers;
|
||||||
|
|
||||||
public void AddHeader(string name, string value)
|
public void AddHeader(string name, string value)
|
||||||
{
|
{
|
||||||
@ -64,8 +66,6 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
_response.AddHeader(name, value);
|
_response.AddHeader(name, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public QueryParamCollection Headers => _response.Headers;
|
|
||||||
|
|
||||||
public string GetHeader(string name)
|
public string GetHeader(string name)
|
||||||
{
|
{
|
||||||
return _response.Headers[name];
|
return _response.Headers[name];
|
||||||
@ -114,9 +114,9 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
|
|
||||||
public void SetContentLength(long contentLength)
|
public void SetContentLength(long contentLength)
|
||||||
{
|
{
|
||||||
//you can happily set the Content-Length header in Asp.Net
|
// you can happily set the Content-Length header in Asp.Net
|
||||||
//but HttpListener will complain if you do - you have to set ContentLength64 on the response.
|
// but HttpListener will complain if you do - you have to set ContentLength64 on the response.
|
||||||
//workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header
|
// workaround: HttpListener throws "The parameter is incorrect" exceptions when we try to set the Content-Length header
|
||||||
_response.ContentLength64 = contentLength;
|
_response.ContentLength64 = contentLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,15 +147,12 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
{
|
{
|
||||||
sb.Append($";domain={cookie.Domain}");
|
sb.Append($";domain={cookie.Domain}");
|
||||||
}
|
}
|
||||||
//else if (restrictAllCookiesToDomain != null)
|
|
||||||
//{
|
|
||||||
// sb.Append($";domain={restrictAllCookiesToDomain}");
|
|
||||||
//}
|
|
||||||
|
|
||||||
if (cookie.Secure)
|
if (cookie.Secure)
|
||||||
{
|
{
|
||||||
sb.Append(";Secure");
|
sb.Append(";Secure");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cookie.HttpOnly)
|
if (cookie.HttpOnly)
|
||||||
{
|
{
|
||||||
sb.Append(";HttpOnly");
|
sb.Append(";HttpOnly");
|
||||||
@ -164,7 +161,6 @@ namespace Jellyfin.Server.SocketSharp
|
|||||||
return sb.ToString();
|
return sb.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool SendChunked
|
public bool SendChunked
|
||||||
{
|
{
|
||||||
get => _response.SendChunked;
|
get => _response.SendChunked;
|
||||||
|
@ -3,11 +3,19 @@
|
|||||||
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
|
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
|
||||||
<!-- disable warning SA1101: Prefix local calls with 'this.' -->
|
<!-- disable warning SA1101: Prefix local calls with 'this.' -->
|
||||||
<Rule Id="SA1101" Action="None" />
|
<Rule Id="SA1101" Action="None" />
|
||||||
|
<!-- disable warning SA1130: Use lambda syntax -->
|
||||||
|
<Rule Id="SA1130" Action="None" />
|
||||||
<!-- disable warning SA1200: 'using' directive must appear within a namespace declaration -->
|
<!-- disable warning SA1200: 'using' directive must appear within a namespace declaration -->
|
||||||
<Rule Id="SA1200" Action="None" />
|
<Rule Id="SA1200" Action="None" />
|
||||||
<!-- disable warning SA1309: Fields must not begin with an underscore -->
|
<!-- disable warning SA1309: Fields must not begin with an underscore -->
|
||||||
<Rule Id="SA1309" Action="None" />
|
<Rule Id="SA1309" Action="None" />
|
||||||
|
<!-- disable warning SA1512: Single-line comments must not be followed by blank line -->
|
||||||
|
<Rule Id="SA1512" Action="None" />
|
||||||
<!-- disable warning SA1633: The file header is missing or not located at the top of the file -->
|
<!-- disable warning SA1633: The file header is missing or not located at the top of the file -->
|
||||||
<Rule Id="SA1633" Action="None" />
|
<Rule Id="SA1633" Action="None" />
|
||||||
</Rules>
|
</Rules>
|
||||||
|
<Rules AnalyzerId="Microsoft.CodeAnalysis.FxCopAnalyzers" RuleNamespace="Microsoft.Design">
|
||||||
|
<!-- disable warning CA1054: Change the type of parameter url from string to System.Uri -->
|
||||||
|
<Rule Id="CA1054" Action="None" />
|
||||||
|
</Rules>
|
||||||
</RuleSet>
|
</RuleSet>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user