Detect broken GS encapsulation.
All checks were successful
🚀 Pack skyscraper8 / make-zip (push) Successful in 1m57s

This commit is contained in:
feyris-tan 2025-10-14 07:08:27 +02:00
parent fe66c643f8
commit a46e4ff556
5 changed files with 117 additions and 9 deletions

1
.gitignore vendored
View File

@ -129,3 +129,4 @@ imgui.ini
/skyscraper8.Manual/skyscraper8.Manual.out
/skyscraper8.Manual/skyscraper8.Manual.pdf
/skyscraper8.Manual/skyscraper8.Manual.synctex.gz
/.vs/skyscraper8/CopilotIndices/17.14.1231.31060

View File

@ -90,6 +90,11 @@ namespace skyscraper8.GSE
break;
}
if (!packet.Valid)
{
break;
}
if (packet.IsCompletePacket)
{
if (ValidateEthertype(packet.ProtocolType.Value))
@ -113,6 +118,25 @@ namespace skyscraper8.GSE
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();
}
}
@ -129,8 +153,8 @@ namespace skyscraper8.GSE
long availableBytes = ms.GetAvailableBytes();
byte[] readBytes = ms.ReadBytes(availableBytes);
GseAssemblyState assemblyState = ValidateGse(gseAssembler);
GseAssemblyState assemblyState = ValidateGse(gseAssembler, true);
if (assemblyState == GseAssemblyState.NOT_YET_BEGUN)
{
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?
}
private GseAssemblyState ValidateGse(MemoryStream ms)
private GseAssemblyState ValidateGse(MemoryStream ms, bool tryFix = false)
{
if (ms == null)
return GseAssemblyState.NOT_YET_BEGUN;
@ -204,6 +228,8 @@ namespace skyscraper8.GSE
ms.Position = 0;
while (ms.GetAvailableBytes() > 2)
{
long fixPosition = ms.Position;
//GSE-Header
byte byteA = ms.ReadUInt8();
bool startIndicator = (byteA & 0x80) != 0;
@ -224,6 +250,12 @@ namespace skyscraper8.GSE
//Console.WriteLine("GSE Length: {0}", gseLength);
if (gseLength > 9000)
{
if (tryFix)
{
ms.Position = fixPosition;
ms.WriteUInt8Repeat(0, (int)ms.GetAvailableBytes());
break;
}
ms.Position = backupPosition;
return GseAssemblyState.BROKEN_SUSPECT_LENGTH;
}
@ -236,6 +268,11 @@ namespace skyscraper8.GSE
if (startIndicator && !endIndicator)
{
if (2 > ms.GetAvailableBytes())
{
ms.Position = backupPosition;
return GseAssemblyState.NEED_MORE_DATA;
}
ushort totalLength = ms.ReadUInt16BE();
gseLength -= 2;
}
@ -250,6 +287,12 @@ namespace skyscraper8.GSE
ushort protocolType = ms.ReadUInt16BE();
if (!ValidateEthertype(protocolType))
{
if (tryFix)
{
ms.Position = fixPosition;
ms.WriteUInt8Repeat(0, (int)ms.GetAvailableBytes());
break;
}
ms.Position = backupPosition;
return GseAssemblyState.BROKEN_SUSPECT_ETHERTYPE;
}
@ -278,6 +321,12 @@ namespace skyscraper8.GSE
if (gseLength < 0)
{
if (tryFix)
{
ms.Position = fixPosition;
ms.WriteUInt8Repeat(0, (int)ms.GetAvailableBytes());
break;
}
ms.Position = backupPosition;
return GseAssemblyState.BROKEN_NEGATIVE_LENGTH;
}
@ -291,6 +340,11 @@ namespace skyscraper8.GSE
ms.Position += gseLength;
if (!startIndicator && endIndicator)
{
if (4 > ms.GetAvailableBytes())
{
ms.Position = backupPosition;
return GseAssemblyState.NEED_MORE_DATA;
}
uint crc32 = ms.ReadUInt32BE();
int endCrc32 = (int)ms.Position;
DvbCrc32.ValidateCrc(ms, startCrc32, endCrc32);

View File

@ -9,7 +9,7 @@ using skyscraper5.Skyscraper;
namespace skyscraper8.GSE
{
internal class GsePacket
internal class GsePacket : Validatable
{
public static GsePacket Read(MemoryStream ms)
{
@ -62,12 +62,23 @@ namespace skyscraper8.GSE
if (!packet.StartIndicator && packet.EndIndicator)
gseLength -= 4;
if (gseLength < 0)
{
packet.Valid = false;
return packet;
}
if (gseLength > ms.GetAvailableBytes())
{
packet.Valid = false;
return packet;
}
packet.GseData = ms.ReadBytes(gseLength);
if (!packet.StartIndicator && packet.EndIndicator)
packet.Crc32 = ms.ReadUInt32BE();
}
packet.Valid = true;
return packet;
}

View File

@ -1,15 +1,17 @@
using System;
using log4net;
using skyscraper5.Skyscraper;
using skyscraper5.src.Mpeg2.PacketFilter;
using System;
using System.Collections.Generic;
using System.Net;
using System.Runtime.CompilerServices;
using skyscraper5.Skyscraper;
using skyscraper5.src.Mpeg2.PacketFilter;
namespace skyscraper5.Mpeg2
{
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 ulong[] pidPackets;
@ -42,6 +44,8 @@ namespace skyscraper5.Mpeg2
if (FilterChain == null || FilterChain.Count == 0)
throw new InvalidOperationException("The filter chain has not been initialized.");
CheckBrokenEncapsulation(packet);
for (int i = 0; i < FilterChain.Count; i++)
{
if (FilterChain[i] == null)
@ -61,6 +65,44 @@ namespace skyscraper5.Mpeg2
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)
{
//Found in ISO 13818-1.pdf, page 38

View File

@ -2,7 +2,7 @@
"profiles": {
"skyscraper8": {
"commandName": "Project",
"commandLineArgs": "\"\\\\utena\\mergerfs\\Skyscraper\\ipProto253_eutelsat7_10803h-max-sx8.ts\"",
"commandLineArgs": "cscan tcp://172.20.20.203:6969",
"remoteDebugEnabled": false
},
"Container (Dockerfile)": {