Rewrite HdHomerunManager.ParseReturnMessage
This commit is contained in:
parent
e8b18e5f8f
commit
f9640f4366
|
@ -130,9 +130,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
|
|
||||||
int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
ParseReturnMessage(buffer, receivedBytes, out string returnVal);
|
return VerifyReturnValueOfGetSet(buffer.AsSpan(receivedBytes), "none");
|
||||||
|
|
||||||
return string.Equals(returnVal, "none", StringComparison.OrdinalIgnoreCase);
|
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -173,7 +171,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// parse response to make sure it worked
|
// parse response to make sure it worked
|
||||||
if (!ParseReturnMessage(buffer, receivedBytes, out _))
|
if (!TryGetReturnValueOfGetSet(buffer.AsSpan(0, receivedBytes), out _))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -185,7 +183,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// parse response to make sure it worked
|
// parse response to make sure it worked
|
||||||
if (!ParseReturnMessage(buffer, receivedBytes, out _))
|
if (!TryGetReturnValueOfGetSet(buffer.AsSpan(0, receivedBytes), out _))
|
||||||
{
|
{
|
||||||
await ReleaseLockkey(_tcpClient, lockKeyValue).ConfigureAwait(false);
|
await ReleaseLockkey(_tcpClient, lockKeyValue).ConfigureAwait(false);
|
||||||
continue;
|
continue;
|
||||||
|
@ -199,7 +197,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// parse response to make sure it worked
|
// parse response to make sure it worked
|
||||||
if (!ParseReturnMessage(buffer, receivedBytes, out _))
|
if (!TryGetReturnValueOfGetSet(buffer.AsSpan(0, receivedBytes), out _))
|
||||||
{
|
{
|
||||||
await ReleaseLockkey(_tcpClient, lockKeyValue).ConfigureAwait(false);
|
await ReleaseLockkey(_tcpClient, lockKeyValue).ConfigureAwait(false);
|
||||||
continue;
|
continue;
|
||||||
|
@ -239,7 +237,7 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
int receivedBytes = await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false);
|
||||||
|
|
||||||
// parse response to make sure it worked
|
// parse response to make sure it worked
|
||||||
if (!ParseReturnMessage(buffer, receivedBytes, out _))
|
if (!TryGetReturnValueOfGetSet(buffer.AsSpan(0, receivedBytes), out _))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -355,60 +353,65 @@ namespace Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun
|
||||||
return offset + 4;
|
return offset + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static bool ParseReturnMessage(byte[] buf, int numBytes, out string returnVal)
|
internal static bool VerifyReturnValueOfGetSet(ReadOnlySpan<byte> buffer, string expected)
|
||||||
{
|
{
|
||||||
returnVal = string.Empty;
|
return TryGetReturnValueOfGetSet(buffer, out var value)
|
||||||
|
&& string.Equals(Encoding.UTF8.GetString(value), expected, StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
if (numBytes < 4)
|
internal static bool TryGetReturnValueOfGetSet(ReadOnlySpan<byte> buffer, out ReadOnlySpan<byte> value)
|
||||||
|
{
|
||||||
|
value = ReadOnlySpan<byte>.Empty;
|
||||||
|
|
||||||
|
if (buffer.Length < 8)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var flipEndian = BitConverter.IsLittleEndian;
|
uint crc = BinaryPrimitives.ReadUInt32LittleEndian(buffer[^4..]);
|
||||||
int offset = 0;
|
if (crc != Crc32.Compute(buffer[..^4]))
|
||||||
byte[] msgTypeBytes = new byte[2];
|
|
||||||
Buffer.BlockCopy(buf, offset, msgTypeBytes, 0, msgTypeBytes.Length);
|
|
||||||
|
|
||||||
if (flipEndian)
|
|
||||||
{
|
|
||||||
Array.Reverse(msgTypeBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
var msgType = BitConverter.ToUInt16(msgTypeBytes, 0);
|
|
||||||
offset += 2;
|
|
||||||
|
|
||||||
if (msgType != GetSetReply)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] msgLengthBytes = new byte[2];
|
if (BinaryPrimitives.ReadUInt16BigEndian(buffer) != GetSetReply)
|
||||||
Buffer.BlockCopy(buf, offset, msgLengthBytes, 0, msgLengthBytes.Length);
|
|
||||||
if (flipEndian)
|
|
||||||
{
|
|
||||||
Array.Reverse(msgLengthBytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
var msgLength = BitConverter.ToUInt16(msgLengthBytes, 0);
|
|
||||||
offset += 2;
|
|
||||||
|
|
||||||
if (numBytes < msgLength + 8)
|
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
offset++; // Name Tag
|
var msgLength = BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(2));
|
||||||
|
if (buffer.Length != 2 + 2 + 4 + msgLength)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var nameLength = buf[offset++];
|
var offset = 4;
|
||||||
|
if (buffer[offset++] != GetSetName)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var nameLength = buffer[offset++];
|
||||||
|
if (buffer.Length < 4 + 1 + offset + nameLength)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// skip the name field to get to value for return
|
|
||||||
offset += nameLength;
|
offset += nameLength;
|
||||||
|
|
||||||
offset++; // Value Tag
|
if (buffer[offset++] != GetSetValue)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
var valueLength = buf[offset++];
|
var valueLength = buffer[offset++];
|
||||||
|
if (buffer.Length < 4 + offset + valueLength)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
returnVal = Encoding.UTF8.GetString(buf, offset, valueLength - 1); // remove null terminator
|
// remove null terminator
|
||||||
|
value = buffer.Slice(offset, valueLength - 1);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Text;
|
||||||
using Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun;
|
using Emby.Server.Implementations.LiveTv.TunerHosts.HdHomerun;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
|
@ -105,9 +106,9 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void ParseReturnMessage_Valid_Success()
|
public void TryGetReturnValueOfGetSet_Valid_Success()
|
||||||
{
|
{
|
||||||
ReadOnlySpan<byte> packet = stackalloc byte[]
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
{
|
{
|
||||||
0, 5,
|
0, 5,
|
||||||
0, 20,
|
0, 20,
|
||||||
|
@ -118,8 +119,208 @@ namespace Jellyfin.Server.Implementations.Tests.LiveTv
|
||||||
0x7d, 0xa3, 0xa3, 0xf3
|
0x7d, 0xa3, 0xa3, 0xf3
|
||||||
};
|
};
|
||||||
|
|
||||||
Assert.True(HdHomerunManager.ParseReturnMessage(packet.ToArray(), packet.Length, out var value));
|
Assert.True(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out var value));
|
||||||
Assert.Equal("value", value);
|
Assert.Equal("value", Encoding.UTF8.GetString(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetReturnValueOfGetSet_InvalidPacketType_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 4,
|
||||||
|
0, 20,
|
||||||
|
3,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0x7d, 0xa3, 0xa3, 0xf3
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetReturnValueOfGetSet_InvalidCrc_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 20,
|
||||||
|
3,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0x7d, 0xa3, 0xa3, 0xf4
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetReturnValueOfGetSet_InvalidPacket_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 20,
|
||||||
|
0x7d, 0xa3, 0xa3
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetReturnValueOfGetSet_TooSmallMessageLength_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 19,
|
||||||
|
3,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0x25, 0x25, 0x44, 0x9a
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetReturnValueOfGetSet_TooLargeMessageLength_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 21,
|
||||||
|
3,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0xe3, 0x20, 0x79, 0x6c
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetReturnValueOfGetSet_TooLargeNameLength_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 20,
|
||||||
|
3,
|
||||||
|
20, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0xe1, 0x8e, 0x9c, 0x74
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetReturnValueOfGetSet_InvalidGetSetNameTag_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 20,
|
||||||
|
4,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0xee, 0x05, 0xe7, 0x12
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetReturnValueOfGetSet_InvalidGetSetValueTag_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 20,
|
||||||
|
3,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
3,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0x64, 0xaa, 0x66, 0xf9
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void TryGetReturnValueOfGetSet_TooLargeValueLength_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 20,
|
||||||
|
3,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
7, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0xc9, 0xa8, 0xd4, 0x55
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.TryGetReturnValueOfGetSet(packet, out _));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void VerifyReturnValueOfGetSet_Valid_True()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 20,
|
||||||
|
3,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0x7d, 0xa3, 0xa3, 0xf3
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.True(HdHomerunManager.VerifyReturnValueOfGetSet(packet, "value"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void VerifyReturnValueOfGetSet_WrongValue_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 5,
|
||||||
|
0, 20,
|
||||||
|
3,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0x7d, 0xa3, 0xa3, 0xf3
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.VerifyReturnValueOfGetSet(packet, "none"));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void VerifyReturnValueOfGetSet_InvalidPacket_False()
|
||||||
|
{
|
||||||
|
ReadOnlySpan<byte> packet = new byte[]
|
||||||
|
{
|
||||||
|
0, 4,
|
||||||
|
0, 20,
|
||||||
|
3,
|
||||||
|
10, (byte)'/', (byte)'t', (byte)'u', (byte)'n', (byte)'e', (byte)'r', (byte)'0', (byte)'/', (byte)'N', 0,
|
||||||
|
4,
|
||||||
|
6, (byte)'v', (byte)'a', (byte)'l', (byte)'u', (byte)'e', 0,
|
||||||
|
0x7d, 0xa3, 0xa3, 0xf3
|
||||||
|
};
|
||||||
|
|
||||||
|
Assert.False(HdHomerunManager.VerifyReturnValueOfGetSet(packet, "value"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user