From 4a90c8751fc9bc10d470733e56472d6d55ae1798 Mon Sep 17 00:00:00 2001
From: feyris-tan <4116042+feyris-tan@users.noreply.github.com>
Date: Sat, 18 Oct 2025 22:04:52 +0200
Subject: [PATCH] Added BCT parsing.
---
.../InteractionChannelErrorState.cs | 3 +-
.../InteractionChannelHandler.cs | 4 +-
.../InteractionChannelPsiGatherer.cs | 20 +++++++--
skyscraper8/InteractionChannel/Model2/Bct.cs | 43 +++++++++++++++++++
.../NullInteractionChannelHandler.cs | 12 +++++-
.../Skyscraper/Scraper/SkyscraperContext.cs | 21 +++++++--
.../Scraper/SkyscraperContextEvent.cs | 3 +-
.../Skyscraper/Scraper/Storage/DataStorage.cs | 3 ++
.../Storage/Filesystem/FilesystemStorage.cs | 11 +++++
.../InMemory/InMemoryScraperStorage.cs | 20 +++++++++
.../InteractionChannelContestant.cs | 22 +++++++++-
11 files changed, 150 insertions(+), 12 deletions(-)
create mode 100644 skyscraper8/InteractionChannel/Model2/Bct.cs
diff --git a/skyscraper8/InteractionChannel/InteractionChannelErrorState.cs b/skyscraper8/InteractionChannel/InteractionChannelErrorState.cs
index 1162d41..ac6faf3 100644
--- a/skyscraper8/InteractionChannel/InteractionChannelErrorState.cs
+++ b/skyscraper8/InteractionChannel/InteractionChannelErrorState.cs
@@ -21,6 +21,7 @@ namespace skyscraper5.src.InteractionChannel
TmstInvalid,
Fct2Invalid,
Tbtp2Invalid,
- Tmst2Invalid
+ Tmst2Invalid,
+ BctInvalid
}
}
diff --git a/skyscraper8/InteractionChannel/InteractionChannelHandler.cs b/skyscraper8/InteractionChannel/InteractionChannelHandler.cs
index 8a94a1e..11f45c2 100644
--- a/skyscraper8/InteractionChannel/InteractionChannelHandler.cs
+++ b/skyscraper8/InteractionChannel/InteractionChannelHandler.cs
@@ -8,6 +8,7 @@ using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.src.InteractionChannel.Model2;
+using skyscraper8.InteractionChannel.Model2;
namespace skyscraper5.src.InteractionChannel
{
@@ -30,6 +31,7 @@ namespace skyscraper5.src.InteractionChannel
void OnReturnTransmissionMOdes(PhysicalAddress macAddress, _0xb2_ReturnTransmissionModesDescriptor descriptor);
void OnConnectionControl(PhysicalAddress macAddress, _0xaf_ConnectionControlDescriptor descriptor);
void OnTerminalBurstTimePlan2(ushort interactiveNetworkId, Tbtp2 tbtp2);
- void OnFrameComposition2(ushort? networkId, Fct2 fct2);
+ void OnFrameComposition2(ushort networkId, Fct2 fct2);
+ void OnBroadcastConfiguration(ushort networkId, Bct bct);
}
}
diff --git a/skyscraper8/InteractionChannel/InteractionChannelPsiGatherer.cs b/skyscraper8/InteractionChannel/InteractionChannelPsiGatherer.cs
index 36b5564..11fb9a2 100644
--- a/skyscraper8/InteractionChannel/InteractionChannelPsiGatherer.cs
+++ b/skyscraper8/InteractionChannel/InteractionChannelPsiGatherer.cs
@@ -9,6 +9,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using skyscraper8.InteractionChannel.Model2;
namespace skyscraper5.src.InteractionChannel
{
@@ -205,11 +206,24 @@ namespace skyscraper5.src.InteractionChannel
return;
}
- Handler.OnFrameComposition2(NetworkId, fct2);
+ Handler.OnFrameComposition2(NetworkId.Value, fct2);
return;
case 0xAC: //BCT
- //see en_30154502v010401p.pdf, page 49
- throw new NotImplementedException("BCT");
+ InteractionChannelSiSectionHeader bctHeader = new InteractionChannelSiSectionHeader(ms);
+ if (!bctHeader.Valid)
+ {
+ _handler.OnInteractionChannelError(InteractionChannelErrorState.HeaderInvalid);
+ return;
+ }
+ NetworkId = bctHeader.InteractiveNetworkId;
+ Bct bct = new Bct(ms);
+ if (!bct.Valid)
+ {
+ _handler.OnInteractionChannelError(InteractionChannelErrorState.BctInvalid);
+ return;
+ }
+ Handler.OnBroadcastConfiguration(NetworkId.Value, bct);
+ return;
case 0xAD: //TBTP2
InteractionChannelSiSectionHeader tbtp2Header = new InteractionChannelSiSectionHeader(ms);
if (!tbtp2Header.Valid)
diff --git a/skyscraper8/InteractionChannel/Model2/Bct.cs b/skyscraper8/InteractionChannel/Model2/Bct.cs
new file mode 100644
index 0000000..586a81c
--- /dev/null
+++ b/skyscraper8/InteractionChannel/Model2/Bct.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using skyscraper5.Skyscraper;
+using skyscraper5.Skyscraper.IO;
+
+namespace skyscraper8.InteractionChannel.Model2
+{
+ ///
+ /// Broadcast Configuration Table as found on ETSI EN 301 545-2 V1.4.1, page 59
+ ///
+ public class Bct : Validatable
+ {
+ public Bct(MemoryStream ms)
+ {
+ byte loopCount = ms.ReadUInt8();
+ TxTypes = new BroadcastConfiguration[loopCount];
+ for (int i = 0; i < loopCount; i++)
+ {
+ TxTypes[i] = new BroadcastConfiguration();
+ TxTypes[i].TxType = ms.ReadUInt8();
+ TxTypes[i].TxContentType = ms.ReadUInt8();
+ TxTypes[i].TxFormatClass = ms.ReadUInt8();
+ byte txFormatDataLengnth = ms.ReadUInt8();
+ TxTypes[i].TxFormatData = ms.ReadBytes(txFormatDataLengnth);
+ }
+
+ Valid = true;
+ }
+
+ public BroadcastConfiguration[] TxTypes { get; private set; }
+
+ public class BroadcastConfiguration
+ {
+ public byte TxType { get; set; }
+ public byte TxContentType { get; set; }
+ public byte TxFormatClass { get; set; }
+ public byte[] TxFormatData { get; set; }
+ }
+ }
+}
diff --git a/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs b/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs
index 906a5f7..0b2732d 100644
--- a/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs
+++ b/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs
@@ -8,6 +8,7 @@ using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.src.InteractionChannel.Model2;
+using skyscraper8.InteractionChannel.Model2;
namespace skyscraper5.src.InteractionChannel
{
@@ -27,9 +28,18 @@ namespace skyscraper5.src.InteractionChannel
}
+ public void OnFrameComposition2(ushort networkId, Fct2 fct2)
+ {
+
+ }
+
+ public void OnBroadcastConfiguration(ushort networkId, Bct bct)
+ {
+ }
+
public void OnFrameComposition2(ushort? networkId, Fct2 fct2)
{
- throw new NotImplementedException();
+
}
public void OnContentionControl(PhysicalAddress macAddress, _0xab_ContentionControlDescriptor ccd)
diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs
index a929c5e..0977e3d 100644
--- a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs
+++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs
@@ -80,6 +80,7 @@ using skyscraper5.src.InteractionChannel.Model2;
using skyscraper8.Experimentals.NdsSsu;
using skyscraper8.Experimentals.OtvSsu;
using skyscraper8.GSE;
+using skyscraper8.InteractionChannel.Model2;
using skyscraper8.Skyscraper.Net;
using skyscraper8.Skyscraper.Scraper;
using Tsubasa.IO;
@@ -2413,14 +2414,26 @@ namespace skyscraper5.Skyscraper.Scraper
}
}
- public void OnFrameComposition2(ushort? networkId, Fct2 fct2)
+ public void OnFrameComposition2(ushort networkId, Fct2 fct2)
{
foreach (Fct2.Frame frame in fct2.FrameTypes)
{
- if (!DataStorage.TestForFrameComposition2(networkId.Value, frame))
+ if (!DataStorage.TestForFrameComposition2(networkId, frame))
{
- LogEvent(SkyscraperContextEvent.FrameComposition2,String.Format("Network ID = {0}, Frame Type = {1}",networkId.Value,frame.FrameType));
- DataStorage.InsertFct2Frame(networkId.Value, frame);
+ LogEvent(SkyscraperContextEvent.FrameComposition2,String.Format("Network ID = {0}, Frame Type = {1}",networkId,frame.FrameType));
+ DataStorage.InsertFct2Frame(networkId, frame);
+ }
+ }
+ }
+
+ public void OnBroadcastConfiguration(ushort networkId, Bct bct)
+ {
+ foreach (Bct.BroadcastConfiguration txType in bct.TxTypes)
+ {
+ if (!DataStorage.TestForBroadcastConfiguration(networkId, txType.TxType))
+ {
+ LogEvent(SkyscraperContextEvent.BroadcastConfiguration, String.Format("Network ID = {0}, Broadcast Configuration #{1}", networkId, txType.TxType));
+ DataStorage.InsertBroadcastConfiguration(networkId, txType);
}
}
}
diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs
index 30d04e2..8d3661a 100644
--- a/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs
+++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs
@@ -87,6 +87,7 @@
NdsSsuFileAnnounced,
NdsSsuProgress,
TerminalBurstTimePlan2,
- FrameComposition2
+ FrameComposition2,
+ BroadcastConfiguration
}
}
diff --git a/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs
index 7a9e3e2..4fcd253 100644
--- a/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs
+++ b/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs
@@ -28,6 +28,7 @@ using skyscraper8.Ses;
using System.Net;
using System.Net.NetworkInformation;
using skyscraper5.src.InteractionChannel.Model2;
+using skyscraper8.InteractionChannel.Model2;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
namespace skyscraper8.Skyscraper.Scraper.Storage
@@ -198,5 +199,7 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
void StoreTerminalBurstTimePlan2(ushort interactiveNetworkId, byte tbtp2GroupId, Tbtp2.Frame frame);
bool TestForFrameComposition2(ushort networkId, Fct2.Frame fct2);
void InsertFct2Frame(ushort networkId, Fct2.Frame frame);
+ bool TestForBroadcastConfiguration(ushort networkId, byte txTypeTxType);
+ void InsertBroadcastConfiguration(ushort networkId, Bct.BroadcastConfiguration txType);
}
}
diff --git a/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs
index 5f4af87..f8a9599 100644
--- a/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs
+++ b/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs
@@ -38,6 +38,7 @@ using skyscraper8.DvbI;
using skyscraper8.DvbNip;
using skyscraper8.Experimentals.NdsSsu;
using skyscraper8.Ietf.FLUTE;
+using skyscraper8.InteractionChannel.Model2;
using skyscraper8.Ses;
using skyscraper8.SimpleServiceDiscoveryProtocol;
using skyscraper8.Skyscraper.Drawing;
@@ -1176,6 +1177,16 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem
throw new NotImplementedException();
}
+ public bool TestForBroadcastConfiguration(ushort networkId, byte txTypeTxType)
+ {
+ throw new NotImplementedException();
+ }
+
+ public void InsertBroadcastConfiguration(ushort networkId, Bct.BroadcastConfiguration txType)
+ {
+ throw new NotImplementedException();
+ }
+
public IEnumerable> SelectAllPmt()
{
throw new NotImplementedException();
diff --git a/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs
index cbb1783..d5dbfde 100644
--- a/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs
+++ b/skyscraper8/Skyscraper/Scraper/Storage/InMemory/InMemoryScraperStorage.cs
@@ -38,6 +38,7 @@ using System.Net;
using System.Net.NetworkInformation;
using skyscraper5.src.InteractionChannel.Model2;
using skyscraper8.Ietf.FLUTE;
+using skyscraper8.InteractionChannel.Model2;
using skyscraper8.Skyscraper.Scraper.Storage;
using skyscraper8.Skyscraper.Scraper.Storage.Utilities;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
@@ -1005,6 +1006,25 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory
_fct2Frames.Add(key, frame);
}
+ private Dictionary, Bct.BroadcastConfiguration> broadcastConfigurations;
+ public bool TestForBroadcastConfiguration(ushort networkId, byte txTypeTxType)
+ {
+ if (broadcastConfigurations == null)
+ return false;
+
+ Tuple key = new Tuple(networkId, txTypeTxType);
+ return broadcastConfigurations.ContainsKey(key);
+ }
+
+ public void InsertBroadcastConfiguration(ushort networkId, Bct.BroadcastConfiguration txType)
+ {
+ if (broadcastConfigurations == null)
+ broadcastConfigurations = new Dictionary, Bct.BroadcastConfiguration>();
+
+ Tuple key = new Tuple(networkId, txType.TxType);
+ broadcastConfigurations.Add(key, txType);
+ }
+
public IEnumerable> SelectAllPmt()
{
for (int x = 0; x < pmtEntries.Length; x++)
diff --git a/skyscraper8/Skyscraper/Scraper/StreamAutodetection/Contestants/InteractionChannelContestant.cs b/skyscraper8/Skyscraper/Scraper/StreamAutodetection/Contestants/InteractionChannelContestant.cs
index 761ae6b..f341f06 100644
--- a/skyscraper8/Skyscraper/Scraper/StreamAutodetection/Contestants/InteractionChannelContestant.cs
+++ b/skyscraper8/Skyscraper/Scraper/StreamAutodetection/Contestants/InteractionChannelContestant.cs
@@ -12,6 +12,7 @@ using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper5.src.InteractionChannel.Model2;
+using skyscraper8.InteractionChannel.Model2;
namespace skyscraper5.src.Skyscraper.Scraper.StreamAutodetection.Contestants
{
@@ -193,9 +194,28 @@ namespace skyscraper5.src.Skyscraper.Scraper.StreamAutodetection.Contestants
}
}
+ public void OnFrameComposition2(ushort networkId, Fct2 fct2)
+ {
+ if (fct2.FrameTypes.Length > 0)
+ {
+ Score++;
+ }
+ }
+
+ public void OnBroadcastConfiguration(ushort networkId, Bct bct)
+ {
+ if (bct.TxTypes.Length > 0)
+ {
+ Score++;
+ }
+ }
+
public void OnFrameComposition2(ushort? networkId, Fct2 fct2)
{
- throw new NotImplementedException();
+ if (fct2.FrameTypes.Length > 0)
+ {
+ Score++;
+ }
}
}
}