Almost solved the SES-12 puzzle.
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 1m33s

This commit is contained in:
feyris-tan 2026-01-06 21:21:33 +01:00
parent 8fb8bc9b05
commit c999a9de4d
21 changed files with 524 additions and 227 deletions

View File

@ -1,5 +1,6 @@
using System;
using System.IO;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using skyscraper5.Skyscraper;
using skyscraper8.Skyscraper.Scraper.Storage.Tar;
@ -14,6 +15,8 @@ public class IntegrationTests
string filename = String.Format("{0}.tar", DateTime.Now.ToUnixTime());
FileInfo fi = new FileInfo(filename);
FileStream fileStream = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
fi.Refresh();
Assert.IsTrue(fi.Exists);
Random rng = new Random();

View File

@ -0,0 +1,19 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;
using skyscraper8.GS;
using skyscraper8.GS.GSE_RollingSyncByte;
using skyscraper8.GSE;
namespace skyscraper8.Tests.ResourceTests;
[TestClass]
public class Ses12GseTest
{
[TestMethod]
public void TestShortPdu()
{
byte[] datasource = Resources1.Frame00000357_TSGS1_MIS000_SYNC184;
GsContextDto dto = new GsContextDto();
GseWithRollingSyncByteReader reader = new GseWithRollingSyncByteReader(dto);
reader.PushFrame(new BBHeader(new byte[10], 0), datasource);
}
}

View File

@ -1,10 +1,9 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.42000
// This code was generated by a tool.
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
@ -12,46 +11,32 @@ namespace skyscraper8.Tests {
using System;
/// <summary>
/// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw.
/// </summary>
// Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert
// -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert.
// Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen
// mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources1 {
private static global::System.Resources.ResourceManager resourceMan;
private static System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
private static System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources1() {
}
/// <summary>
/// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("skyscraper8.Tests.Resources1", typeof(Resources1).Assembly);
if (object.Equals(null, resourceMan)) {
System.Resources.ResourceManager temp = new System.Resources.ResourceManager("skyscraper8.Tests.Resources1", typeof(Resources1).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle
/// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
internal static System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
@ -60,39 +45,6 @@ namespace skyscraper8.Tests {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] Frame00000008_TSGS1_MIS000_SYNC001 {
get {
object obj = ResourceManager.GetObject("Frame00000008_TSGS1_MIS000_SYNC001", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] Frame00000012_TSGS1_MIS000_SYNC001 {
get {
object obj = ResourceManager.GetObject("Frame00000012_TSGS1_MIS000_SYNC001", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] Frame00001343_TSGS1_MIS000_SYNC001 {
get {
object obj = ResourceManager.GetObject("Frame00001343_TSGS1_MIS000_SYNC001", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] ModemCapabilitiesEncodingTest {
get {
object obj = ResourceManager.GetObject("ModemCapabilitiesEncodingTest", resourceCulture);
@ -100,9 +52,6 @@ namespace skyscraper8.Tests {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] MultipartRegistrationResponseTest {
get {
object obj = ResourceManager.GetObject("MultipartRegistrationResponseTest", resourceCulture);
@ -110,19 +59,6 @@ namespace skyscraper8.Tests {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] MultipartRegistrationResponseTest2 {
get {
object obj = ResourceManager.GetObject("MultipartRegistrationResponseTest2", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] PushMacManagementMessage_Version4_Type45 {
get {
object obj = ResourceManager.GetObject("PushMacManagementMessage_Version4_Type45", resourceCulture);
@ -130,9 +66,6 @@ namespace skyscraper8.Tests {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] ranging_response_test {
get {
object obj = ResourceManager.GetObject("ranging_response_test", resourceCulture);
@ -140,19 +73,13 @@ namespace skyscraper8.Tests {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] sdpTest {
internal static byte[] MultipartRegistrationResponseTest2 {
get {
object obj = ResourceManager.GetObject("sdpTest", resourceCulture);
object obj = ResourceManager.GetObject("MultipartRegistrationResponseTest2", resourceCulture);
return ((byte[])(obj));
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] test_1packet_01 {
get {
object obj = ResourceManager.GetObject("test-1packet-01", resourceCulture);
@ -160,9 +87,6 @@ namespace skyscraper8.Tests {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] test_2packets_02_03 {
get {
object obj = ResourceManager.GetObject("test-2packets-02-03", resourceCulture);
@ -170,9 +94,6 @@ namespace skyscraper8.Tests {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] test_3packets_04_05_06 {
get {
object obj = ResourceManager.GetObject("test-3packets-04-05-06", resourceCulture);
@ -180,9 +101,6 @@ namespace skyscraper8.Tests {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] TransmitChannelConfigurationObject {
get {
object obj = ResourceManager.GetObject("TransmitChannelConfigurationObject", resourceCulture);
@ -190,14 +108,46 @@ namespace skyscraper8.Tests {
}
}
/// <summary>
/// Sucht eine lokalisierte Ressource vom Typ System.Byte[].
/// </summary>
internal static byte[] UpstreamChannelDescriptorTest {
get {
object obj = ResourceManager.GetObject("UpstreamChannelDescriptorTest", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] Frame00001343_TSGS1_MIS000_SYNC001 {
get {
object obj = ResourceManager.GetObject("Frame00001343_TSGS1_MIS000_SYNC001", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] Frame00000008_TSGS1_MIS000_SYNC001 {
get {
object obj = ResourceManager.GetObject("Frame00000008_TSGS1_MIS000_SYNC001", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] Frame00000012_TSGS1_MIS000_SYNC001 {
get {
object obj = ResourceManager.GetObject("Frame00000012_TSGS1_MIS000_SYNC001", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] sdpTest {
get {
object obj = ResourceManager.GetObject("sdpTest", resourceCulture);
return ((byte[])(obj));
}
}
internal static byte[] Frame00000357_TSGS1_MIS000_SYNC184 {
get {
object obj = ResourceManager.GetObject("Frame00000357_TSGS1_MIS000_SYNC184", resourceCulture);
return ((byte[])(obj));
}
}
}
}

View File

@ -160,4 +160,7 @@
<data name="sdpTest" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\sdpTest.sdp;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="Frame00000357_TSGS1_MIS000_SYNC184" type="System.Resources.ResXFileRef, System.Windows.Forms">
<value>Resources\Frame00000357_TSGS1_MIS000_SYNC184.bbframe;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
</root>

View File

@ -1,6 +1,7 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAllureContext_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003Fc09614b59cc98c343d268f55e356aaafe85d13755cd5ca217988e9c5362ff_003FAllureContext_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAllureFeatureAttribute_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FSourcesCache_003F405349a6f42433abaa8b1d6d06bb6f21c66899533fa9f9648cb1cde8755143_003FAllureFeatureAttribute_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AArgumentNullException_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F57d616db882b441b8c50720b4477e03db2e200_003Ff2_003F6872d84e_003FArgumentNullException_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AArray_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F57d616db882b441b8c50720b4477e03db2e200_003F6e_003Fd247db11_003FArray_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAssert_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F053cba69424c47858472194d509c3cdc12bb0_003F37_003F58cc70f4_003FAssert_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AAssert_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003F_002Econfig_003FJetBrains_003FRider2025_002E1_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003Fa840692e98b74557bc005b38213a22c72dad0_003Fc8_003F58c2e0c9_003FAssert_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
@ -39,7 +40,7 @@
&lt;Assembly Path="/home/schiemas/.nuget/packages/allure.net.commons/2.14.1/lib/netstandard2.0/Allure.Net.Commons.dll" /&gt;
&lt;/AssemblyExplorer&gt;</s:String>
<s:String x:Key="/Default/Environment/Highlighting/HighlightingSourceSnapshotLocation/@EntryValue">/home/schiemas/.cache/JetBrains/Rider2025.1/resharper-host/temp/Rider/vAny/CoverageData/_skyscraper8.1808907683/Snapshot/snapshot.utdcvr</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=145b05c0_002D83b0_002D4386_002Db9fb_002De55ec3152557/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &amp;lt;skyscraper8.Tests&amp;gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=145b05c0_002D83b0_002D4386_002Db9fb_002De55ec3152557/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="All tests from &amp;lt;skyscraper8.Tests&amp;gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;And&gt;&#xD;
&lt;Namespace&gt;skyscraper8.Tests&lt;/Namespace&gt;&#xD;
&lt;Project Location="\home\schiemas\RiderProjects\skyscraper8\skyscraper8.Tests" Presentation="&amp;lt;skyscraper8.Tests&amp;gt;" /&gt;&#xD;
@ -59,4 +60,5 @@
<s:String x:Key="/Default/Profiling/Configurations/=1/@EntryIndexedValue">&lt;data&gt;&lt;HostParameters type="LocalHostParameters" /&gt;&lt;Argument type="StandaloneArgument"&gt;&lt;Arguments IsNull="False"&gt;&lt;/Arguments&gt;&lt;FileName IsNull="False"&gt;&lt;/FileName&gt;&lt;WorkingDirectory IsNull="False"&gt;&lt;/WorkingDirectory&gt;&lt;Scope&gt;&lt;ProcessFilters /&gt;&lt;/Scope&gt;&lt;/Argument&gt;&lt;Info type="TimelineInfo" /&gt;&lt;CoreOptions type="CoreOptions"&gt;&lt;CoreTempPath IsNull="False"&gt;&lt;/CoreTempPath&gt;&lt;RemoteEndPoint IsNull="False"&gt;&lt;/RemoteEndPoint&gt;&lt;AdditionalEnvironmentVariables /&gt;&lt;/CoreOptions&gt;&lt;HostOptions type="HostOptions"&gt;&lt;HostTempPath IsNull="False"&gt;&lt;/HostTempPath&gt;&lt;/HostOptions&gt;&lt;/data&gt;</s:String>
<s:Boolean x:Key="/Default/ResxEditorPersonal/CheckedGroups/=skyscraper8_002ETests_002FResources1/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
<s:Boolean x:Key="/Default/ResxEditorPersonal/Initialized/@EntryValue">True</s:Boolean>
<s:Boolean x:Key="/Default/ResxEditorPersonal/ShowOnlyErrors/@EntryValue">False</s:Boolean></wpf:ResourceDictionary>

View File

@ -79,4 +79,9 @@ public class BBHeader : Validatable
/// 3 = Transport
/// </summary>
public int TsGs { get; private set; }
public override string ToString()
{
return String.Format("TsGs: {0}, SyncByte: {1}, UPL: {2}", TsGs, SyncByte,UserPacketLength);
}
}

View File

@ -22,7 +22,7 @@ class BbframeDeencapsulator3 : IBbframeDeencapsulator
{
if (numPushed == 0)
{
logger.InfoFormat("The stream started in the middle of a BBFrame, let's skip to the start of the next one.");
logger.InfoFormat("The stream started in the middle of a BBFrame, let's wait for the next one to start.");
}
return;
}
@ -36,8 +36,7 @@ class BbframeDeencapsulator3 : IBbframeDeencapsulator
mis = new IMisHandler[256];
if (mis[bbHeader.Matype2] == null)
{
logger.InfoFormat("Found a stream on MIS {0}",bbHeader.Matype2);
mis[bbHeader.Matype2] = new GsTypeDetector(context.MisClone(bbHeader.Matype2));
mis[bbHeader.Matype2] = new MisHandlerProxy(context.MisClone(bbHeader.Matype2));
}
mis[bbHeader.Matype2].PushFrame(bbHeader, new ReadOnlySpan<byte>(bbframe, 11, bbframe.Length - 11));

View File

@ -0,0 +1,185 @@
using log4net;
using skyscraper5.Skyscraper.IO;
using skyscraper8.GSE;
using skyscraper8.GSE.GSE;
namespace skyscraper8.GS.GSE_RollingSyncByte;
public class GseWithRollingSyncByteReader : IMisHandler
{
public GsContextDto Context { get; set; }
private ulong packetSerial;
private GseLabel reuse;
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
{
packetSerial++;
byte[] array = readOnlySpan.ToArray();
MemoryStream ms = new MemoryStream(array, 0, array.Length - 4);
while (ms.GetAvailableBytes() > 0)
{
byte a = ms.ReadUInt8();
bool startIndicator = (a & 0x80) != 0;
bool endIndicator = (a & 0x40) != 0;
int labelTypeIndicator = (a & 0x30) >> 4;
GsePacket gsePacket = new GsePacket(startIndicator, endIndicator, labelTypeIndicator);
if (!startIndicator && !endIndicator && labelTypeIndicator == 0)
{
return;
}
else
{
byte b = ms.ReadUInt8();
int gseLength = (a & 0x0f) << 8;
gseLength += b;
int gseRemain = gseLength - 2;
if (!startIndicator || !endIndicator)
{
gsePacket.FragmentId = ms.ReadUInt8();
gseRemain--;
}
if (startIndicator && !endIndicator)
{
gsePacket.TotalLength = ms.ReadUInt16BE();
gseRemain -= 2;
}
if (startIndicator)
{
gsePacket.ProtocolType = ms.ReadUInt16BE();
gseRemain -= 2;
switch (labelTypeIndicator)
{
case 0:
if (ms.GetAvailableBytes() < 6)
return; //The MAC address is sliced in half. I have my doubts that this is even allowed.
gsePacket.Label = new _6byteLabel(ms.ReadBytes(6));
reuse = gsePacket.Label;
gseRemain -= 6;
break;
case 1:
gsePacket.Label = new _3byteLabel(ms.ReadBytes(3));
reuse = gsePacket.Label;
gseRemain -= 3;
break;
case 2:
gsePacket.Label = BroadcastLabel.GetInstance();
break;
case 3:
gsePacket.Label = reuse;
break;
}
}
int payloadSize = gseRemain;
if (!startIndicator && endIndicator)
payloadSize -= 4;
gsePacket.GseDataBytes = ms.ReadBytes(payloadSize);
gseRemain -= payloadSize;
if (!startIndicator && endIndicator)
{
gsePacket.Crc32 = ms.ReadUInt32BE();
gseRemain -= 4;
}
}
ProcessPacket(gsePacket);
}
}
private bool[] warnedEthertypes;
private GseFragmentation[] fragments;
public GseWithRollingSyncByteReader(GsContextDto context)
{
this.Context = context;
}
private void ProcessPacket(GsePacket gsePacket)
{
if (gsePacket.LabelTypeIndicator == 3 && gsePacket.Label == null)
return;
if (!gsePacket.StartIndicator && gsePacket.EndIndicator)
{
if (fragments == null)
return;
if (fragments[gsePacket.FragmentId.Value] == null)
return;
if (fragments[gsePacket.FragmentId.Value].Validate())
{
byte[] gseDataBytes = fragments[gsePacket.FragmentId.Value].GetGseDataBytes();
HandleAssembledFrame(fragments[gsePacket.FragmentId.Value].ProtocolType, gseDataBytes, fragments[gsePacket.FragmentId.Value].Label);
}
}
if (gsePacket.StartIndicator && gsePacket.EndIndicator)
{
Context.InformTrafficType(gsePacket.ProtocolType.Value);
HandleAssembledFrame(gsePacket.ProtocolType.Value, gsePacket.GseDataBytes, gsePacket.Label);
return;
}
if (gsePacket.StartIndicator && !gsePacket.EndIndicator)
{
if (fragments == null)
fragments = new GseFragmentation[256];
fragments[gsePacket.FragmentId.Value] = new GseFragmentation(gsePacket);
return;
}
if (!gsePacket.StartIndicator && !gsePacket.EndIndicator)
{
if (fragments == null)
return;
if (fragments[gsePacket.FragmentId.Value] == null)
return;
fragments[gsePacket.FragmentId.Value].AddFragement(gsePacket);
return;
}
throw new NotImplementedException();
}
private ulong aolSerial;
private void HandleProprietaryAolJunk(byte[] buffer, ushort protocolType)
{
aolSerial++;
string dumpPath = String.Format("{0}{1}{2}.bin", protocolType, Path.DirectorySeparatorChar, aolSerial);
FileInfo dumpFile = new FileInfo(dumpPath);
dumpFile.Directory.EnsureExists();
File.WriteAllBytes(dumpFile.FullName, buffer);
}
private void HandleAssembledFrame(ushort protocolType, byte[] buffer, GseLabel label)
{
switch (protocolType)
{
case 0x0002:
case 0x0004:
HandleProprietaryAolJunk(buffer,protocolType);
return;
case 0x0091:
//according to https://www.iana.org/assignments/ule-next-headers/ule-next-headers.xhtml it's private
return;
case 0x0800:
Context.IpOutput.OnIpDatagram(0x010e, buffer);
return;
default:
if (warnedEthertypes == null)
warnedEthertypes = new bool[ushort.MaxValue];
if (!warnedEthertypes[protocolType])
{
logger.WarnFormat("This GSE contains other traffic types (type 0x{0:X4}) besides IP (type 0x0800). If it's not too much trouble, please consider submitting a sample.",protocolType);
warnedEthertypes[protocolType] = true;
}
return;
}
}
}

View File

@ -7,6 +7,10 @@ namespace skyscraper8.GSE.GSE;
internal class GseReader : IMisHandler
{
public GseReader(GsContextDto dto)
{
this.Context = dto;
}
private GseLabel lastLabel;
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);

View File

@ -10,7 +10,7 @@ using skyscraper8.Skyscraper.Scraper;
namespace skyscraper8.GS
{
internal class GsContextDto
public class GsContextDto
{
public GsContextMisDto MisClone(byte mis)
{
@ -39,9 +39,21 @@ namespace skyscraper8.GS
public IMultiprotocolEncapsulationEventHandler IpOutput { get; set; }
public InteractionChannelHandler Rcs2Output { get; set; }
private Dictionary<ushort, ulong> trafficTypes;
public void InformTrafficType(ushort trafficType)
{
if (trafficTypes == null)
trafficTypes = new Dictionary<ushort, ulong>();
if (!trafficTypes.ContainsKey(trafficType))
trafficTypes.Add(trafficType, 1);
else
trafficTypes[trafficType]++;
}
}
internal class GsContextMisDto : GsContextDto
public class GsContextMisDto : GsContextDto
{
public byte Mis { get; }

View File

@ -1,109 +0,0 @@
using log4net;
using skyscraper5.Dvb.DataBroadcasting;
using skyscraper8.GS;
using skyscraper8.GS.GSE_BFBS;
using skyscraper8.GS.SiminnRadiomidun;
using skyscraper8.GSE.GSE_HEM;
using skyscraper8.GSE.GSE;
using skyscraper8.Skyscraper.Scraper;
namespace skyscraper8.GSE;
class GsTypeDetector : IMisHandler
{
public GsContextDto Context { get; set; }
private readonly ILog logger;
private HashSet<Tuple<int, byte>> _postedStreamTypes;
public GsTypeDetector(GsContextMisDto context)
{
this.logger = LogManager.GetLogger(String.Format("{0} MIS {1}",System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name,context.Mis));
this.Context = context;
}
private GseReader gseReader;
private GseHemReader gseHemReader;
private SiminnRadiomidunReader siminnRadiomidunReader;
private BfbsGseReader bfbsGseReader;
private int simminRadiomidunScore;
private int bfbsScore;
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
{
if (readOnlySpan.Length == 0)
{
return;
}
if (bbHeader.TsGs == 1 && bbHeader.SyncByte == 0)
{
//Looks like Continuous GSE.
if (gseReader == null)
{
gseReader = new GseReader();
gseReader.Context = Context;
}
gseReader.PushFrame(bbHeader, readOnlySpan);
return;
}
if (bbHeader.TsGs == 2 && bbHeader.SyncByte == 0)
{
//Looks like GSE-HEM
if (gseHemReader == null)
{
gseHemReader = new GseHemReader(Context);
}
gseHemReader.PushFrame(bbHeader, readOnlySpan);
return;
}
if (bbHeader.TsGs == 0 && bbHeader.SyncByte == 71 && bbHeader.UserPacketLength == 188)
{
simminRadiomidunScore++;
if (simminRadiomidunScore > 10)
{
//Looks like a Simmin Radiomidun-like stream.
if (siminnRadiomidunReader == null)
{
//These behave similar to T2-MI. Interesting.
siminnRadiomidunReader = new SiminnRadiomidunReader(Context);
}
siminnRadiomidunReader.PushFrame(bbHeader, readOnlySpan);
return;
}
return;
}
else
{
if (simminRadiomidunScore < 10)
{
simminRadiomidunScore = 0;
}
}
if (bbHeader.TsGs == 1 && bbHeader.SyncByte == 1 && bbHeader.UserPacketLength == 0)
{
if (bfbsGseReader == null)
{
bfbsGseReader = new BfbsGseReader(Context);
}
bfbsGseReader.PushFrame(bbHeader, readOnlySpan);
return;
}
//We have no idea what this is.
Tuple<int, byte> streamTypeToPost = new Tuple<int, byte>(bbHeader.TsGs, bbHeader.SyncByte);
if (_postedStreamTypes == null)
_postedStreamTypes = new HashSet<Tuple<int, byte>>();
if (!_postedStreamTypes.Contains(streamTypeToPost))
{
logger.WarnFormat("This GS contains packets of type {0} ({2}) with a sync byte of {1}. This is not supported yet. If it isn't too much trouble, please consider sharing a sample of this stream.",streamTypeToPost.Item1,streamTypeToPost.Item2, (TsGsType)streamTypeToPost.Item1);
_postedStreamTypes.Add(streamTypeToPost);
}
}
}

View File

@ -0,0 +1,190 @@
using log4net;
using skyscraper5.Mpeg2;
using skyscraper8.GS;
using skyscraper8.GS.GSE_BFBS;
using skyscraper8.GS.GSE_RollingSyncByte;
using skyscraper8.GS.SiminnRadiomidun;
using skyscraper8.GSE.GSE_HEM;
using skyscraper8.GSE.GSE;
namespace skyscraper8.GSE;
class MisHandlerProxy : IMisHandler
{
public GsContextDto Context { get; set; }
private readonly ILog logger;
private HashSet<Tuple<int, byte>> _postedStreamTypes;
public MisHandlerProxy(GsContextMisDto context)
{
this.logger = LogManager.GetLogger(String.Format("{0} MIS {1}",System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name,context.Mis));
this.Context = context;
}
private int state;
private Queue<Tuple<BBHeader, byte[]>> waitingPackets;
private DateTime lastWaitingTimePrinted;
private IMisHandler misHandler;
private bool unknownStateError;
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
{
if (readOnlySpan.Length == 0)
{
return;
}
switch (state)
{
case 0: //No packets collected yet.
waitingPackets = new Queue<Tuple<BBHeader, byte[]>>();
logger.InfoFormat("Attempting to detect the stream type of MIS {0}...",bbHeader.Matype2);
waitingPackets.Enqueue(new Tuple<BBHeader, byte[]>(bbHeader, readOnlySpan.ToArray()));
lastWaitingTimePrinted = DateTime.Now;
state = 1;
break;
case 1:
DateTime currentTime = DateTime.Now;
if (currentTime - lastWaitingTimePrinted > TimeSpan.FromSeconds(1))
{
logger.InfoFormat("Waiting for {0} more packets on MIS {1}...",100 - waitingPackets.Count,bbHeader.Matype2);
lastWaitingTimePrinted = currentTime;
}
waitingPackets.Enqueue(new Tuple<BBHeader, byte[]>(bbHeader, readOnlySpan.ToArray()));
if (waitingPackets.Count == 100)
{
state = 2;
}
break;
case 2:
RunDetection();
DrainQueue();
misHandler.PushFrame(bbHeader, readOnlySpan);
state = 3;
break;
case 3:
misHandler.PushFrame(bbHeader, readOnlySpan);
break;
default:
if (!unknownStateError)
{
logger.FatalFormat("The Finite-state machine of the MIS Handler reached an impossible state. This is a bug in skyscraper8. It would be great if you could share a sample of this stream to reproduce this, so I can fix this.");
unknownStateError = true;
}
break;
}
}
private enum DetectedGsType
{
ContinuousGSE,
GSE_HEM,
SimminRadiomidun,
BfbsGSE,
GseWithRollingSyncByte
}
private void SucessfulDetection(DetectedGsType detectedGsType)
{
logger.InfoFormat("MIS {0} looks like {1}, will try to treat it as such.",Context.GetMisId(),detectedGsType);
switch (detectedGsType)
{
case DetectedGsType.ContinuousGSE: misHandler = new GseReader(Context); break;
case DetectedGsType.GSE_HEM: misHandler = new GseHemReader(Context); break;
case DetectedGsType.SimminRadiomidun: misHandler = new SiminnRadiomidunReader(Context); break;
case DetectedGsType.BfbsGSE: misHandler = new BfbsGseReader(Context); break;
case DetectedGsType.GseWithRollingSyncByte: misHandler = new GseWithRollingSyncByteReader(Context); break;
default:
logger.FatalFormat("However, {0} is not implemented yet, sorry...", detectedGsType);
misHandler = new NullMisHandler();
break;
}
}
private bool RunDetection()
{
//bbHeader.TsGs == 1 && bbHeader.SyncByte == 0
int continuousGseScore = waitingPackets.Count(x => x.Item1.TsGs == 1 && x.Item1.SyncByte == 0);
if (continuousGseScore == 100)
{
SucessfulDetection(DetectedGsType.ContinuousGSE);
return true;
}
//bbHeader.TsGs == 2 && bbHeader.SyncByte == 0
int gseHemScore = waitingPackets.Count(x => x.Item1.TsGs == 2 && x.Item1.SyncByte == 0);
if (gseHemScore == 100)
{
SucessfulDetection(DetectedGsType.GSE_HEM);
return true;
}
//bbHeader.TsGs == 0 && bbHeader.SyncByte == 71 && bbHeader.UserPacketLength == 188
int simminRadiomidunScore = waitingPackets.Count(x => x.Item1.TsGs == 0 && x.Item1.SyncByte == 71 && x.Item1.UserPacketLength == 188);
if (simminRadiomidunScore == 100)
{
SucessfulDetection(DetectedGsType.SimminRadiomidun);
return true;
}
//bbHeader.TsGs == 1 && bbHeader.SyncByte == 1 && bbHeader.UserPacketLength == 0
int bfbsGseScore = waitingPackets.Count(x => x.Item1.TsGs == 1 && x.Item1.SyncByte == 1 && x.Item1.UserPacketLength == 0);
if (bfbsGseScore == 100)
{
SucessfulDetection(DetectedGsType.BfbsGSE);
return true;
}
bool allPacketsHaveValidCrc32 = AnalyzeCrc32Values();
if (!allPacketsHaveValidCrc32)
{
if (StatisticalAnalysis_Ses12_11476v())
{
SucessfulDetection(DetectedGsType.GseWithRollingSyncByte);
return true;
}
}
return false;
}
private void DrainQueue()
{
while (waitingPackets.Count > 0)
{
Tuple<BBHeader, byte[]> dequeue = waitingPackets.Dequeue();
misHandler.PushFrame(dequeue.Item1, dequeue.Item2);
}
waitingPackets = null;
}
private bool AnalyzeCrc32Values()
{
foreach (Tuple<BBHeader, byte[]> waitingPacket in waitingPackets)
{
bool validateCrc = DvbCrc32.ValidateCrc(waitingPacket.Item2);
if (!validateCrc)
return false;
}
return true;
}
private bool StatisticalAnalysis_Ses12_11476v()
{
byte[] syncBytes = new byte[256];
foreach (Tuple<BBHeader, byte[]> dequeue in waitingPackets)
{
syncBytes[dequeue.Item1.SyncByte]++;
if (syncBytes[dequeue.Item1.SyncByte] > 3)
return false;
if (dequeue.Item1.DataFieldLength != dequeue.Item2.Length)
return false;
}
return true;
}
}

View File

@ -0,0 +1,12 @@
using skyscraper8.GSE;
namespace skyscraper8.GS;
class NullMisHandler : IMisHandler
{
public GsContextDto Context { get; set; }
public void PushFrame(BBHeader bbHeader, ReadOnlySpan<byte> readOnlySpan)
{
}
}

View File

@ -9,6 +9,7 @@ namespace skyscraper5.src.Id3
internal enum Id3ErrorState
{
InvalidMagic,
PacketTooShort
PacketTooShort,
NullPacket
}
}

View File

@ -22,6 +22,12 @@ namespace skyscraper5.src.Id3
public void ProcessPesPacket(PesPacket packet)
{
if (packet.Payload == null)
{
handler.OnId3Error(Id3ErrorState.NullPacket);
return;
}
MemoryStream ms = new MemoryStream(packet.Payload, false);
if (ms.ReadUInt8() != 'I')
{

View File

@ -6,7 +6,7 @@ using System.Threading.Tasks;
namespace skyscraper5.src.InteractionChannel
{
internal enum InteractionChannelErrorState
public enum InteractionChannelErrorState
{
UnexpectedTable,
HeaderInvalid,

View File

@ -15,7 +15,7 @@ using skyscraper8.InteractionChannel.Model2.Descriptors;
namespace skyscraper5.src.InteractionChannel
{
internal interface InteractionChannelHandler
public interface InteractionChannelHandler
{
void OnCorrectionMessage(ushort interactiveNetworkId, Cmt cmt);
void OnFrameComposition(ushort interactiveNetworkId, Fct fct);

View File

@ -9,7 +9,7 @@ using System.Threading.Tasks;
namespace skyscraper5.src.InteractionChannel.Model
{
internal class Tmst : Validatable
public class Tmst : Validatable
{
public Tmst(MemoryStream ms)
{

View File

@ -126,6 +126,20 @@ namespace skyscraper5.Mpeg2
return crc == 0;
}
public static uint CreateCrc(ReadOnlySpan<byte> data)
{
uint crc = 0xffffffff;
for (int i = 0; i < data.Length; i++)
{
uint b = (crc >> 24) & 0xff;
int c = (data[i]) & 0xff;
crc = (crc << 8) ^ table[b ^ c];
}
return crc;
}
public static uint CreateCrc(MemoryStream ms, int offset, int end)
{
long restorePosition = ms.Position;

View File

@ -39,8 +39,9 @@ namespace skyscraper5
private static void IntegrationTest()
{
SoftcamTestProgram softcamTestProgram = new SoftcamTestProgram();
softcamTestProgram.Run();
//SoftcamTestProgram softcamTestProgram = new SoftcamTestProgram();
//softcamTestProgram.Run();
/*List<SsdpDevice> ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
foreach (SsdpDevice ssdpDevice in ssdpDevices)
{