Clamp client reported ping in SyncPlay groups
This commit is contained in:
@@ -90,6 +90,18 @@ namespace Emby.Server.Implementations.SyncPlay
|
||||
/// <value>The default ping.</value>
|
||||
public long DefaultPing { get; } = 500;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum ping, in milliseconds, accepted from a session.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Pings are reported by clients and are scaled into the delays used to schedule playback,
|
||||
/// so an unbounded value lets a single session push the whole group's resume point
|
||||
/// arbitrarily far out, or overflow the arithmetic entirely. Anything above this is not a
|
||||
/// usable measurement for synchronisation.
|
||||
/// </remarks>
|
||||
/// <value>The maximum ping.</value>
|
||||
public long MaxPing { get; } = 10000;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the maximum time offset error accepted for dates reported by clients, in milliseconds.
|
||||
/// </summary>
|
||||
@@ -438,7 +450,7 @@ namespace Emby.Server.Implementations.SyncPlay
|
||||
{
|
||||
if (_participants.TryGetValue(session.Id, out GroupMember value))
|
||||
{
|
||||
value.Ping = ping;
|
||||
value.Ping = Math.Clamp(ping, 0, MaxPing);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -53,6 +53,34 @@ public class WaitingGroupStateTests
|
||||
$"expected a resume delay of at least {group.DefaultPing} ms, got {scheduledDelay.TotalMilliseconds} ms");
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(4_000_000_000L)]
|
||||
[InlineData(1_000_000_000_000_000L)]
|
||||
[InlineData(long.MaxValue)]
|
||||
[InlineData(-1L)]
|
||||
public void UpdatePing_ClientReportsAnUnusablePing_IsClampedAndCannotStallTheGroup(long reportedPing)
|
||||
{
|
||||
var harness = new GroupHarness();
|
||||
var group = harness.Group;
|
||||
|
||||
group.UpdatePing(harness.First, reportedPing);
|
||||
|
||||
Assert.InRange(group.GetHighestPing(), 0, group.MaxPing);
|
||||
|
||||
// The reported ping is scaled into the group's resume point, so an unclamped value either
|
||||
// pushes playback months out or overflows the arithmetic outright.
|
||||
var state = new PlayingGroupState(NullLoggerFactory.Instance);
|
||||
var before = DateTime.UtcNow;
|
||||
state.HandleRequest(
|
||||
new UnpauseGroupRequest(),
|
||||
group,
|
||||
GroupStateType.Paused,
|
||||
harness.First,
|
||||
CancellationToken.None);
|
||||
|
||||
Assert.InRange(group.LastActivity - before, TimeSpan.Zero, TimeSpan.FromMinutes(1));
|
||||
}
|
||||
|
||||
private sealed class GroupHarness
|
||||
{
|
||||
public GroupHarness()
|
||||
@@ -73,6 +101,10 @@ public class WaitingGroupStateTests
|
||||
.Setup(m => m.SendSyncPlayCommand(It.IsAny<string>(), It.IsAny<SendCommand>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
sessionManager
|
||||
.Setup(m => m.SendSyncPlayGroupUpdate(It.IsAny<string>(), It.IsAny<GroupUpdate<GroupStateUpdate>>(), It.IsAny<CancellationToken>()))
|
||||
.Returns(Task.CompletedTask);
|
||||
|
||||
Group = new SyncPlayGroup(
|
||||
NullLoggerFactory.Instance,
|
||||
userManager.Object,
|
||||
|
||||
Reference in New Issue
Block a user