diff --git a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
index fd7653a32d..7f620d666d 100644
--- a/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
+++ b/Emby.Server.Implementations/HttpServer/WebSocketConnection.cs
@@ -12,6 +12,7 @@ using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Net.WebSocketMessages;
using MediaBrowser.Controller.Net.WebSocketMessages.Outbound;
using MediaBrowser.Model.Session;
+using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
namespace Emby.Server.Implementations.HttpServer
@@ -43,14 +44,17 @@ namespace Emby.Server.Implementations.HttpServer
///
/// The logger.
/// The socket.
+ /// The authorization information.
/// The remote end point.
public WebSocketConnection(
ILogger logger,
WebSocket socket,
+ AuthorizationInfo authorizationInfo,
IPAddress? remoteEndPoint)
{
_logger = logger;
_socket = socket;
+ AuthorizationInfo = authorizationInfo;
RemoteEndPoint = remoteEndPoint;
_jsonOptions = JsonDefaults.Options;
@@ -60,30 +64,22 @@ namespace Emby.Server.Implementations.HttpServer
///
public event EventHandler? Closed;
- ///
- /// Gets the remote end point.
- ///
+ ///
+ public AuthorizationInfo AuthorizationInfo { get; }
+
+ ///
public IPAddress? RemoteEndPoint { get; }
- ///
- /// Gets or sets the receive action.
- ///
- /// The receive action.
+ ///
public Func? OnReceive { get; set; }
- ///
- /// Gets the last activity date.
- ///
- /// The last activity date.
+ ///
public DateTime LastActivityDate { get; private set; }
///
public DateTime LastKeepAliveDate { get; set; }
- ///
- /// Gets the state.
- ///
- /// The state.
+ ///
public WebSocketState State => _socket.State;
///
@@ -101,7 +97,7 @@ namespace Emby.Server.Implementations.HttpServer
}
///
- public async Task ProcessAsync(CancellationToken cancellationToken = default)
+ public async Task ReceiveAsync(CancellationToken cancellationToken = default)
{
var pipe = new Pipe();
var writer = pipe.Writer;
diff --git a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs
index ecfb242f6f..52f14b0b10 100644
--- a/Emby.Server.Implementations/HttpServer/WebSocketManager.cs
+++ b/Emby.Server.Implementations/HttpServer/WebSocketManager.cs
@@ -51,6 +51,7 @@ namespace Emby.Server.Implementations.HttpServer
using var connection = new WebSocketConnection(
_loggerFactory.CreateLogger(),
webSocket,
+ authorizationInfo,
context.GetNormalizedRemoteIP())
{
OnReceive = ProcessWebSocketMessageReceived
@@ -64,7 +65,7 @@ namespace Emby.Server.Implementations.HttpServer
await Task.WhenAll(tasks).ConfigureAwait(false);
- await connection.ProcessAsync().ConfigureAwait(false);
+ await connection.ReceiveAsync().ConfigureAwait(false);
_logger.LogInformation("WS {IP} closed", context.Connection.RemoteIpAddress);
}
catch (Exception ex) // Otherwise ASP.Net will ignore the exception
diff --git a/Emby.Server.Implementations/Session/SessionManager.cs b/Emby.Server.Implementations/Session/SessionManager.cs
index 5f6dc93fb3..03ff96b19a 100644
--- a/Emby.Server.Implementations/Session/SessionManager.cs
+++ b/Emby.Server.Implementations/Session/SessionManager.cs
@@ -24,6 +24,7 @@ using MediaBrowser.Controller.Drawing;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Events;
+using MediaBrowser.Controller.Events.Authentication;
using MediaBrowser.Controller.Events.Session;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
@@ -1462,7 +1463,7 @@ namespace Emby.Server.Implementations.Session
if (user is null)
{
- await _eventManager.PublishAsync(new GenericEventArgs(request)).ConfigureAwait(false);
+ await _eventManager.PublishAsync(new AuthenticationRequestEventArgs(request)).ConfigureAwait(false);
throw new AuthenticationException("Invalid username or password entered.");
}
@@ -1498,7 +1499,7 @@ namespace Emby.Server.Implementations.Session
ServerId = _appHost.SystemId
};
- await _eventManager.PublishAsync(new GenericEventArgs(returnResult)).ConfigureAwait(false);
+ await _eventManager.PublishAsync(new AuthenticationResultEventArgs(returnResult)).ConfigureAwait(false);
return returnResult;
}
diff --git a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
index 4a5e0ecd4f..5b90d65d84 100644
--- a/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
+++ b/Jellyfin.Api/WebSocketListeners/ActivityLogWebSocketListener.cs
@@ -1,6 +1,8 @@
using System;
using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
using Jellyfin.Data.Events;
+using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Net;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Session;
@@ -9,7 +11,7 @@ using Microsoft.Extensions.Logging;
namespace Jellyfin.Api.WebSocketListeners;
///
-/// Class SessionInfoWebSocketListener.
+/// Class ActivityLogWebSocketListener.
///
public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener
{
@@ -56,6 +58,20 @@ public class ActivityLogWebSocketListener : BasePeriodicWebSocketListener
+ /// Starts sending messages over an activity log web socket.
+ ///
+ /// The message.
+ protected override void Start(WebSocketMessageInfo message)
+ {
+ if (!message.Connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
+ {
+ throw new AuthenticationException("Only admin users can retrieve the activity log.");
+ }
+
+ base.Start(message);
+ }
+
private async void OnEntryCreated(object? sender, GenericEventArgs e)
{
await SendData(true).ConfigureAwait(false);
diff --git a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
index 0d8bf205c9..b403ff46d0 100644
--- a/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
+++ b/Jellyfin.Api/WebSocketListeners/SessionInfoWebSocketListener.cs
@@ -1,5 +1,7 @@
using System.Collections.Generic;
using System.Threading.Tasks;
+using Jellyfin.Data.Enums;
+using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Net;
using MediaBrowser.Controller.Session;
@@ -66,6 +68,20 @@ public class SessionInfoWebSocketListener : BasePeriodicWebSocketListener
+ /// Starts sending messages over a session info web socket.
+ ///
+ /// The message.
+ protected override void Start(WebSocketMessageInfo message)
+ {
+ if (!message.Connection.AuthorizationInfo.User.HasPermission(PermissionKind.IsAdministrator))
+ {
+ throw new AuthenticationException("Only admin users can subscribe to session information.");
+ }
+
+ base.Start(message);
+ }
+
private async void OnSessionManagerSessionActivity(object? sender, SessionEventArgs e)
{
await SendData(false).ConfigureAwait(false);
diff --git a/Jellyfin.Networking/Extensions/NetworkExtensions.cs b/Jellyfin.Networking/Extensions/NetworkExtensions.cs
index d55f78135b..e45fa3bcb7 100644
--- a/Jellyfin.Networking/Extensions/NetworkExtensions.cs
+++ b/Jellyfin.Networking/Extensions/NetworkExtensions.cs
@@ -104,7 +104,7 @@ public static partial class NetworkExtensions
Span bytes = stackalloc byte[mask.AddressFamily == AddressFamily.InterNetwork ? Network.IPv4MaskBytes : Network.IPv6MaskBytes];
if (!mask.TryWriteBytes(bytes, out var bytesWritten))
{
- Console.WriteLine("Unable to write address bytes, only {bytesWritten} bytes written.");
+ Console.WriteLine("Unable to write address bytes, only ${bytesWritten} bytes written.");
}
var zeroed = false;
diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationFailedLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationFailedLogger.cs
index f899b4497a..b5f18d9834 100644
--- a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationFailedLogger.cs
+++ b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationFailedLogger.cs
@@ -2,9 +2,8 @@
using System.Globalization;
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
-using Jellyfin.Data.Events;
using MediaBrowser.Controller.Events;
-using MediaBrowser.Controller.Session;
+using MediaBrowser.Controller.Events.Authentication;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Globalization;
using Microsoft.Extensions.Logging;
@@ -14,7 +13,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Security
///
/// Creates an entry in the activity log when there is a failed login attempt.
///
- public class AuthenticationFailedLogger : IEventConsumer>
+ public class AuthenticationFailedLogger : IEventConsumer
{
private readonly ILocalizationManager _localizationManager;
private readonly IActivityManager _activityManager;
@@ -31,13 +30,13 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Security
}
///
- public async Task OnEvent(GenericEventArgs eventArgs)
+ public async Task OnEvent(AuthenticationRequestEventArgs eventArgs)
{
await _activityManager.CreateAsync(new ActivityLog(
string.Format(
CultureInfo.InvariantCulture,
_localizationManager.GetLocalizedString("FailedLoginAttemptWithUserName"),
- eventArgs.Argument.Username),
+ eventArgs.Username),
"AuthenticationFailed",
Guid.Empty)
{
@@ -45,7 +44,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Security
ShortOverview = string.Format(
CultureInfo.InvariantCulture,
_localizationManager.GetLocalizedString("LabelIpAddressValue"),
- eventArgs.Argument.RemoteEndPoint),
+ eventArgs.RemoteEndPoint),
}).ConfigureAwait(false);
}
}
diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs
index 8b0bd84c66..2ee5b4e88d 100644
--- a/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs
+++ b/Jellyfin.Server.Implementations/Events/Consumers/Security/AuthenticationSucceededLogger.cs
@@ -2,8 +2,8 @@
using System.Threading.Tasks;
using Jellyfin.Data.Entities;
using Jellyfin.Data.Events;
-using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Events;
+using MediaBrowser.Controller.Events.Authentication;
using MediaBrowser.Model.Activity;
using MediaBrowser.Model.Globalization;
@@ -12,7 +12,7 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Security
///
/// Creates an entry in the activity log when there is a successful login attempt.
///
- public class AuthenticationSucceededLogger : IEventConsumer>
+ public class AuthenticationSucceededLogger : IEventConsumer
{
private readonly ILocalizationManager _localizationManager;
private readonly IActivityManager _activityManager;
@@ -29,20 +29,20 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Security
}
///
- public async Task OnEvent(GenericEventArgs eventArgs)
+ public async Task OnEvent(AuthenticationResultEventArgs eventArgs)
{
await _activityManager.CreateAsync(new ActivityLog(
string.Format(
CultureInfo.InvariantCulture,
_localizationManager.GetLocalizedString("AuthenticationSucceededWithUserName"),
- eventArgs.Argument.User.Name),
+ eventArgs.User.Name),
"AuthenticationSucceeded",
- eventArgs.Argument.User.Id)
+ eventArgs.User.Id)
{
ShortOverview = string.Format(
CultureInfo.InvariantCulture,
_localizationManager.GetLocalizedString("LabelIpAddressValue"),
- eventArgs.Argument.SessionInfo.RemoteEndPoint),
+ eventArgs.SessionInfo?.RemoteEndPoint),
}).ConfigureAwait(false);
}
}
diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs
index aeb62e814c..27726a57a6 100644
--- a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs
+++ b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStartLogger.cs
@@ -58,15 +58,18 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Session
var user = eventArgs.Users[0];
await _activityManager.CreateAsync(new ActivityLog(
- string.Format(
- CultureInfo.InvariantCulture,
- _localizationManager.GetLocalizedString("UserStartedPlayingItemWithValues"),
- user.Username,
- GetItemName(eventArgs.MediaInfo),
- eventArgs.DeviceName),
- GetPlaybackNotificationType(eventArgs.MediaInfo.MediaType),
- user.Id))
- .ConfigureAwait(false);
+ string.Format(
+ CultureInfo.InvariantCulture,
+ _localizationManager.GetLocalizedString("UserStartedPlayingItemWithValues"),
+ user.Username,
+ GetItemName(eventArgs.MediaInfo),
+ eventArgs.DeviceName),
+ GetPlaybackNotificationType(eventArgs.MediaInfo.MediaType),
+ user.Id)
+ {
+ ItemId = eventArgs.Item?.Id.ToString("N", CultureInfo.InvariantCulture),
+ })
+ .ConfigureAwait(false);
}
private static string GetItemName(BaseItemDto item)
diff --git a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs
index dd7290fb84..6b16477aa7 100644
--- a/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs
+++ b/Jellyfin.Server.Implementations/Events/Consumers/Session/PlaybackStopLogger.cs
@@ -73,7 +73,10 @@ namespace Jellyfin.Server.Implementations.Events.Consumers.Session
GetItemName(item),
eventArgs.DeviceName),
notificationType,
- user.Id))
+ user.Id)
+ {
+ ItemId = eventArgs.Item?.Id.ToString("N", CultureInfo.InvariantCulture),
+ })
.ConfigureAwait(false);
}
diff --git a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs
index 5d558189b1..9a473de52d 100644
--- a/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs
+++ b/Jellyfin.Server.Implementations/Events/EventingServiceCollectionExtensions.cs
@@ -8,12 +8,11 @@ using Jellyfin.Server.Implementations.Events.Consumers.System;
using Jellyfin.Server.Implementations.Events.Consumers.Updates;
using Jellyfin.Server.Implementations.Events.Consumers.Users;
using MediaBrowser.Common.Updates;
-using MediaBrowser.Controller.Authentication;
using MediaBrowser.Controller.Events;
+using MediaBrowser.Controller.Events.Authentication;
using MediaBrowser.Controller.Events.Session;
using MediaBrowser.Controller.Events.Updates;
using MediaBrowser.Controller.Library;
-using MediaBrowser.Controller.Session;
using MediaBrowser.Controller.Subtitles;
using MediaBrowser.Model.Tasks;
using Microsoft.Extensions.DependencyInjection;
@@ -35,8 +34,8 @@ namespace Jellyfin.Server.Implementations.Events
collection.AddScoped, SubtitleDownloadFailureLogger>();
// Security consumers
- collection.AddScoped>, AuthenticationFailedLogger>();
- collection.AddScoped>, AuthenticationSucceededLogger>();
+ collection.AddScoped, AuthenticationFailedLogger>();
+ collection.AddScoped, AuthenticationSucceededLogger>();
// Session consumers
collection.AddScoped, PlaybackStartLogger>();
diff --git a/MediaBrowser.Controller/Events/Authentication/AuthenticationRequestEventArgs.cs b/MediaBrowser.Controller/Events/Authentication/AuthenticationRequestEventArgs.cs
new file mode 100644
index 0000000000..2143c69986
--- /dev/null
+++ b/MediaBrowser.Controller/Events/Authentication/AuthenticationRequestEventArgs.cs
@@ -0,0 +1,60 @@
+using System;
+using MediaBrowser.Controller.Session;
+
+namespace MediaBrowser.Controller.Events.Authentication;
+
+///
+/// A class representing an authentication result event.
+///
+public class AuthenticationRequestEventArgs : EventArgs
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The .
+ public AuthenticationRequestEventArgs(AuthenticationRequest request)
+ {
+ Username = request.Username;
+ UserId = request.UserId;
+ App = request.App;
+ AppVersion = request.AppVersion;
+ DeviceId = request.DeviceId;
+ DeviceName = request.DeviceName;
+ RemoteEndPoint = request.RemoteEndPoint;
+ }
+
+ ///
+ /// Gets or sets the user name.
+ ///
+ public string? Username { get; set; }
+
+ ///
+ /// Gets or sets the user id.
+ ///
+ public Guid? UserId { get; set; }
+
+ ///
+ /// Gets or sets the app.
+ ///
+ public string? App { get; set; }
+
+ ///
+ /// Gets or sets the app version.
+ ///
+ public string? AppVersion { get; set; }
+
+ ///
+ /// Gets or sets the device id.
+ ///
+ public string? DeviceId { get; set; }
+
+ ///
+ /// Gets or sets the device name.
+ ///
+ public string? DeviceName { get; set; }
+
+ ///
+ /// Gets or sets the remote endpoint.
+ ///
+ public string? RemoteEndPoint { get; set; }
+}
diff --git a/MediaBrowser.Controller/Events/Authentication/AuthenticationResultEventArgs.cs b/MediaBrowser.Controller/Events/Authentication/AuthenticationResultEventArgs.cs
new file mode 100644
index 0000000000..357ef9406d
--- /dev/null
+++ b/MediaBrowser.Controller/Events/Authentication/AuthenticationResultEventArgs.cs
@@ -0,0 +1,38 @@
+using System;
+using MediaBrowser.Controller.Authentication;
+using MediaBrowser.Controller.Session;
+using MediaBrowser.Model.Dto;
+
+namespace MediaBrowser.Controller.Events.Authentication;
+
+///
+/// A class representing an authentication result event.
+///
+public class AuthenticationResultEventArgs : EventArgs
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The .
+ public AuthenticationResultEventArgs(AuthenticationResult result)
+ {
+ User = result.User;
+ SessionInfo = result.SessionInfo;
+ ServerId = result.ServerId;
+ }
+
+ ///
+ /// Gets or sets the user.
+ ///
+ public UserDto User { get; set; }
+
+ ///
+ /// Gets or sets the session information.
+ ///
+ public SessionInfo? SessionInfo { get; set; }
+
+ ///
+ /// Gets or sets the server id.
+ ///
+ public string? ServerId { get; set; }
+}
diff --git a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
index 8f38d4976b..e0942e490b 100644
--- a/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
+++ b/MediaBrowser.Controller/Net/BasePeriodicWebSocketListener.cs
@@ -96,7 +96,7 @@ namespace MediaBrowser.Controller.Net
/// Starts sending messages over a web socket.
///
/// The message.
- private void Start(WebSocketMessageInfo message)
+ protected virtual void Start(WebSocketMessageInfo message)
{
var vals = message.Data.Split(',');
diff --git a/MediaBrowser.Controller/Net/IWebSocketConnection.cs b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
index 79f0846b4a..bba5a6b851 100644
--- a/MediaBrowser.Controller/Net/IWebSocketConnection.cs
+++ b/MediaBrowser.Controller/Net/IWebSocketConnection.cs
@@ -1,5 +1,3 @@
-#pragma warning disable CS1591
-
using System;
using System.Net;
using System.Net.WebSockets;
@@ -9,6 +7,9 @@ using MediaBrowser.Controller.Net.WebSocketMessages;
namespace MediaBrowser.Controller.Net
{
+ ///
+ /// Interface for WebSocket connections.
+ ///
public interface IWebSocketConnection : IAsyncDisposable, IDisposable
{
///
@@ -40,6 +41,11 @@ namespace MediaBrowser.Controller.Net
/// The state.
WebSocketState State { get; }
+ ///
+ /// Gets the authorization information.
+ ///
+ public AuthorizationInfo AuthorizationInfo { get; }
+
///
/// Gets the remote end point.
///
@@ -65,6 +71,11 @@ namespace MediaBrowser.Controller.Net
/// The message is null.
Task SendAsync(OutboundWebSocketMessage message, CancellationToken cancellationToken);
- Task ProcessAsync(CancellationToken cancellationToken = default);
+ ///
+ /// Receives a message asynchronously.
+ ///
+ /// The cancellation token.
+ /// Task.
+ Task ReceiveAsync(CancellationToken cancellationToken = default);
}
}
diff --git a/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs b/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs
index f016118192..22667ee82d 100644
--- a/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs
+++ b/tests/Jellyfin.Server.Implementations.Tests/HttpServer/WebSocketConnectionTests.cs
@@ -13,7 +13,7 @@ namespace Jellyfin.Server.Implementations.Tests.HttpServer
[Fact]
public void DeserializeWebSocketMessage_SingleSegment_Success()
{
- var con = new WebSocketConnection(new NullLogger(), null!, null!);
+ var con = new WebSocketConnection(new NullLogger(), null!, null!, null!);
var bytes = File.ReadAllBytes("Test Data/HttpServer/ForceKeepAlive.json");
con.DeserializeWebSocketMessage(new ReadOnlySequence(bytes), out var bytesConsumed);
Assert.Equal(109, bytesConsumed);
@@ -23,7 +23,7 @@ namespace Jellyfin.Server.Implementations.Tests.HttpServer
public void DeserializeWebSocketMessage_MultipleSegments_Success()
{
const int SplitPos = 64;
- var con = new WebSocketConnection(new NullLogger(), null!, null!);
+ var con = new WebSocketConnection(new NullLogger(), null!, null!, null!);
var bytes = File.ReadAllBytes("Test Data/HttpServer/ForceKeepAlive.json");
var seg1 = new BufferSegment(new Memory(bytes, 0, SplitPos));
var seg2 = seg1.Append(new Memory(bytes, SplitPos, bytes.Length - SplitPos));
@@ -34,7 +34,7 @@ namespace Jellyfin.Server.Implementations.Tests.HttpServer
[Fact]
public void DeserializeWebSocketMessage_ValidPartial_Success()
{
- var con = new WebSocketConnection(new NullLogger(), null!, null!);
+ var con = new WebSocketConnection(new NullLogger(), null!, null!, null!);
var bytes = File.ReadAllBytes("Test Data/HttpServer/ValidPartial.json");
con.DeserializeWebSocketMessage(new ReadOnlySequence(bytes), out var bytesConsumed);
Assert.Equal(109, bytesConsumed);
@@ -43,7 +43,7 @@ namespace Jellyfin.Server.Implementations.Tests.HttpServer
[Fact]
public void DeserializeWebSocketMessage_Partial_ThrowJsonException()
{
- var con = new WebSocketConnection(new NullLogger(), null!, null!);
+ var con = new WebSocketConnection(new NullLogger(), null!, null!, null!);
var bytes = File.ReadAllBytes("Test Data/HttpServer/Partial.json");
Assert.Throws(() => con.DeserializeWebSocketMessage(new ReadOnlySequence(bytes), out var bytesConsumed));
}