Detect broken GS encapsulation.
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 1m57s
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 1m57s
This commit is contained in:
parent
fe66c643f8
commit
a46e4ff556
1
.gitignore
vendored
1
.gitignore
vendored
@ -129,3 +129,4 @@ imgui.ini
|
|||||||
/skyscraper8.Manual/skyscraper8.Manual.out
|
/skyscraper8.Manual/skyscraper8.Manual.out
|
||||||
/skyscraper8.Manual/skyscraper8.Manual.pdf
|
/skyscraper8.Manual/skyscraper8.Manual.pdf
|
||||||
/skyscraper8.Manual/skyscraper8.Manual.synctex.gz
|
/skyscraper8.Manual/skyscraper8.Manual.synctex.gz
|
||||||
|
/.vs/skyscraper8/CopilotIndices/17.14.1231.31060
|
||||||
|
|||||||
@ -90,6 +90,11 @@ namespace skyscraper8.GSE
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!packet.Valid)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (packet.IsCompletePacket)
|
if (packet.IsCompletePacket)
|
||||||
{
|
{
|
||||||
if (ValidateEthertype(packet.ProtocolType.Value))
|
if (ValidateEthertype(packet.ProtocolType.Value))
|
||||||
@ -113,6 +118,25 @@ namespace skyscraper8.GSE
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!packet.StartIndicator && packet.EndIndicator)
|
||||||
|
{
|
||||||
|
if (gseFragmentations == null)
|
||||||
|
continue;
|
||||||
|
if (gseFragmentations[packet.FragmentId.Value] == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
gseFragmentations[packet.FragmentId.Value].AddPacket(packet);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!packet.StartIndicator && !packet.EndIndicator)
|
||||||
|
{
|
||||||
|
if (gseFragmentations == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,8 +153,8 @@ namespace skyscraper8.GSE
|
|||||||
|
|
||||||
long availableBytes = ms.GetAvailableBytes();
|
long availableBytes = ms.GetAvailableBytes();
|
||||||
byte[] readBytes = ms.ReadBytes(availableBytes);
|
byte[] readBytes = ms.ReadBytes(availableBytes);
|
||||||
|
|
||||||
GseAssemblyState assemblyState = ValidateGse(gseAssembler);
|
GseAssemblyState assemblyState = ValidateGse(gseAssembler, true);
|
||||||
if (assemblyState == GseAssemblyState.NOT_YET_BEGUN)
|
if (assemblyState == GseAssemblyState.NOT_YET_BEGUN)
|
||||||
{
|
{
|
||||||
if ((syncByte & 0xc0) == 0xc0)
|
if ((syncByte & 0xc0) == 0xc0)
|
||||||
@ -195,7 +219,7 @@ namespace skyscraper8.GSE
|
|||||||
VALID_NULL_PACKET, //somehow these only show up on TBS6903x, not DD Max SX8?
|
VALID_NULL_PACKET, //somehow these only show up on TBS6903x, not DD Max SX8?
|
||||||
}
|
}
|
||||||
|
|
||||||
private GseAssemblyState ValidateGse(MemoryStream ms)
|
private GseAssemblyState ValidateGse(MemoryStream ms, bool tryFix = false)
|
||||||
{
|
{
|
||||||
if (ms == null)
|
if (ms == null)
|
||||||
return GseAssemblyState.NOT_YET_BEGUN;
|
return GseAssemblyState.NOT_YET_BEGUN;
|
||||||
@ -204,6 +228,8 @@ namespace skyscraper8.GSE
|
|||||||
ms.Position = 0;
|
ms.Position = 0;
|
||||||
while (ms.GetAvailableBytes() > 2)
|
while (ms.GetAvailableBytes() > 2)
|
||||||
{
|
{
|
||||||
|
long fixPosition = ms.Position;
|
||||||
|
|
||||||
//GSE-Header
|
//GSE-Header
|
||||||
byte byteA = ms.ReadUInt8();
|
byte byteA = ms.ReadUInt8();
|
||||||
bool startIndicator = (byteA & 0x80) != 0;
|
bool startIndicator = (byteA & 0x80) != 0;
|
||||||
@ -224,6 +250,12 @@ namespace skyscraper8.GSE
|
|||||||
//Console.WriteLine("GSE Length: {0}", gseLength);
|
//Console.WriteLine("GSE Length: {0}", gseLength);
|
||||||
if (gseLength > 9000)
|
if (gseLength > 9000)
|
||||||
{
|
{
|
||||||
|
if (tryFix)
|
||||||
|
{
|
||||||
|
ms.Position = fixPosition;
|
||||||
|
ms.WriteUInt8Repeat(0, (int)ms.GetAvailableBytes());
|
||||||
|
break;
|
||||||
|
}
|
||||||
ms.Position = backupPosition;
|
ms.Position = backupPosition;
|
||||||
return GseAssemblyState.BROKEN_SUSPECT_LENGTH;
|
return GseAssemblyState.BROKEN_SUSPECT_LENGTH;
|
||||||
}
|
}
|
||||||
@ -236,6 +268,11 @@ namespace skyscraper8.GSE
|
|||||||
|
|
||||||
if (startIndicator && !endIndicator)
|
if (startIndicator && !endIndicator)
|
||||||
{
|
{
|
||||||
|
if (2 > ms.GetAvailableBytes())
|
||||||
|
{
|
||||||
|
ms.Position = backupPosition;
|
||||||
|
return GseAssemblyState.NEED_MORE_DATA;
|
||||||
|
}
|
||||||
ushort totalLength = ms.ReadUInt16BE();
|
ushort totalLength = ms.ReadUInt16BE();
|
||||||
gseLength -= 2;
|
gseLength -= 2;
|
||||||
}
|
}
|
||||||
@ -250,6 +287,12 @@ namespace skyscraper8.GSE
|
|||||||
ushort protocolType = ms.ReadUInt16BE();
|
ushort protocolType = ms.ReadUInt16BE();
|
||||||
if (!ValidateEthertype(protocolType))
|
if (!ValidateEthertype(protocolType))
|
||||||
{
|
{
|
||||||
|
if (tryFix)
|
||||||
|
{
|
||||||
|
ms.Position = fixPosition;
|
||||||
|
ms.WriteUInt8Repeat(0, (int)ms.GetAvailableBytes());
|
||||||
|
break;
|
||||||
|
}
|
||||||
ms.Position = backupPosition;
|
ms.Position = backupPosition;
|
||||||
return GseAssemblyState.BROKEN_SUSPECT_ETHERTYPE;
|
return GseAssemblyState.BROKEN_SUSPECT_ETHERTYPE;
|
||||||
}
|
}
|
||||||
@ -278,6 +321,12 @@ namespace skyscraper8.GSE
|
|||||||
|
|
||||||
if (gseLength < 0)
|
if (gseLength < 0)
|
||||||
{
|
{
|
||||||
|
if (tryFix)
|
||||||
|
{
|
||||||
|
ms.Position = fixPosition;
|
||||||
|
ms.WriteUInt8Repeat(0, (int)ms.GetAvailableBytes());
|
||||||
|
break;
|
||||||
|
}
|
||||||
ms.Position = backupPosition;
|
ms.Position = backupPosition;
|
||||||
return GseAssemblyState.BROKEN_NEGATIVE_LENGTH;
|
return GseAssemblyState.BROKEN_NEGATIVE_LENGTH;
|
||||||
}
|
}
|
||||||
@ -291,6 +340,11 @@ namespace skyscraper8.GSE
|
|||||||
ms.Position += gseLength;
|
ms.Position += gseLength;
|
||||||
if (!startIndicator && endIndicator)
|
if (!startIndicator && endIndicator)
|
||||||
{
|
{
|
||||||
|
if (4 > ms.GetAvailableBytes())
|
||||||
|
{
|
||||||
|
ms.Position = backupPosition;
|
||||||
|
return GseAssemblyState.NEED_MORE_DATA;
|
||||||
|
}
|
||||||
uint crc32 = ms.ReadUInt32BE();
|
uint crc32 = ms.ReadUInt32BE();
|
||||||
int endCrc32 = (int)ms.Position;
|
int endCrc32 = (int)ms.Position;
|
||||||
DvbCrc32.ValidateCrc(ms, startCrc32, endCrc32);
|
DvbCrc32.ValidateCrc(ms, startCrc32, endCrc32);
|
||||||
|
|||||||
@ -9,7 +9,7 @@ using skyscraper5.Skyscraper;
|
|||||||
|
|
||||||
namespace skyscraper8.GSE
|
namespace skyscraper8.GSE
|
||||||
{
|
{
|
||||||
internal class GsePacket
|
internal class GsePacket : Validatable
|
||||||
{
|
{
|
||||||
public static GsePacket Read(MemoryStream ms)
|
public static GsePacket Read(MemoryStream ms)
|
||||||
{
|
{
|
||||||
@ -62,12 +62,23 @@ namespace skyscraper8.GSE
|
|||||||
if (!packet.StartIndicator && packet.EndIndicator)
|
if (!packet.StartIndicator && packet.EndIndicator)
|
||||||
gseLength -= 4;
|
gseLength -= 4;
|
||||||
|
|
||||||
|
if (gseLength < 0)
|
||||||
|
{
|
||||||
|
packet.Valid = false;
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
|
if (gseLength > ms.GetAvailableBytes())
|
||||||
|
{
|
||||||
|
packet.Valid = false;
|
||||||
|
return packet;
|
||||||
|
}
|
||||||
packet.GseData = ms.ReadBytes(gseLength);
|
packet.GseData = ms.ReadBytes(gseLength);
|
||||||
|
|
||||||
if (!packet.StartIndicator && packet.EndIndicator)
|
if (!packet.StartIndicator && packet.EndIndicator)
|
||||||
packet.Crc32 = ms.ReadUInt32BE();
|
packet.Crc32 = ms.ReadUInt32BE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
packet.Valid = true;
|
||||||
return packet;
|
return packet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,15 +1,17 @@
|
|||||||
using System;
|
using log4net;
|
||||||
|
using skyscraper5.Skyscraper;
|
||||||
|
using skyscraper5.src.Mpeg2.PacketFilter;
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using skyscraper5.Skyscraper;
|
|
||||||
using skyscraper5.src.Mpeg2.PacketFilter;
|
|
||||||
|
|
||||||
namespace skyscraper5.Mpeg2
|
namespace skyscraper5.Mpeg2
|
||||||
{
|
{
|
||||||
public class TsContext : ITsPacketProcessor
|
public class TsContext : ITsPacketProcessor
|
||||||
{
|
{
|
||||||
private ITsPacketProcessor[] processors;
|
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
|
||||||
|
private ITsPacketProcessor[] processors;
|
||||||
private uint[] continuities;
|
private uint[] continuities;
|
||||||
private ulong[] pidPackets;
|
private ulong[] pidPackets;
|
||||||
|
|
||||||
@ -42,6 +44,8 @@ namespace skyscraper5.Mpeg2
|
|||||||
if (FilterChain == null || FilterChain.Count == 0)
|
if (FilterChain == null || FilterChain.Count == 0)
|
||||||
throw new InvalidOperationException("The filter chain has not been initialized.");
|
throw new InvalidOperationException("The filter chain has not been initialized.");
|
||||||
|
|
||||||
|
CheckBrokenEncapsulation(packet);
|
||||||
|
|
||||||
for (int i = 0; i < FilterChain.Count; i++)
|
for (int i = 0; i < FilterChain.Count; i++)
|
||||||
{
|
{
|
||||||
if (FilterChain[i] == null)
|
if (FilterChain[i] == null)
|
||||||
@ -61,6 +65,44 @@ namespace skyscraper5.Mpeg2
|
|||||||
processors[packet.PID].PushPacket(packet);
|
processors[packet.PID].PushPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool encapsulationBrokenConfirmed;
|
||||||
|
private bool CheckBrokenEncapsulation(TsPacket packet)
|
||||||
|
{
|
||||||
|
if (encapsulationBrokenConfirmed)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
switch (packet.PID)
|
||||||
|
{
|
||||||
|
case 0x0000:
|
||||||
|
case 0x0001:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int occupiedPids = CountOccupiedPids();
|
||||||
|
if (occupiedPids < 1000)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (packet.TSC == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
logger.WarnFormat("It looks like you're either having bad reception or this is a GS with broken encapsulation. This means that you either have FrameMode enabled, or are not using a STiD135.");
|
||||||
|
encapsulationBrokenConfirmed = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private int CountOccupiedPids()
|
||||||
|
{
|
||||||
|
int result = 0;
|
||||||
|
for (int i = 0; i < pidPackets.Length; i++)
|
||||||
|
{
|
||||||
|
if (pidPackets[i] > 0)
|
||||||
|
result++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
private bool EnsureContinuity(TsPacket packet)
|
private bool EnsureContinuity(TsPacket packet)
|
||||||
{
|
{
|
||||||
//Found in ISO 13818-1.pdf, page 38
|
//Found in ISO 13818-1.pdf, page 38
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
"profiles": {
|
"profiles": {
|
||||||
"skyscraper8": {
|
"skyscraper8": {
|
||||||
"commandName": "Project",
|
"commandName": "Project",
|
||||||
"commandLineArgs": "\"\\\\utena\\mergerfs\\Skyscraper\\ipProto253_eutelsat7_10803h-max-sx8.ts\"",
|
"commandLineArgs": "cscan tcp://172.20.20.203:6969",
|
||||||
"remoteDebugEnabled": false
|
"remoteDebugEnabled": false
|
||||||
},
|
},
|
||||||
"Container (Dockerfile)": {
|
"Container (Dockerfile)": {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user