diff --git a/.gitea/workflows/demo.yaml b/.gitea/workflows/demo.yaml
index 5ba17c5..1ea1dff 100644
--- a/.gitea/workflows/demo.yaml
+++ b/.gitea/workflows/demo.yaml
@@ -33,7 +33,8 @@ jobs:
uses: akkuman/gitea-release-action@v1
with:
name: ${{ gitea.sha }}
- md5sum: true
- sha256sum: true
+ md5sum: false
+ sha256sum: false
+ tag_name: release_tag
files: |-
${{ gitea.workspace }}/skyscraper8-${{ gitea.sha }}.zip
\ No newline at end of file
diff --git a/skyscraper8.Manual/skyscraper8.Manual.tex b/skyscraper8.Manual/skyscraper8.Manual.tex
index f27f2a4..e30f9a0 100644
--- a/skyscraper8.Manual/skyscraper8.Manual.tex
+++ b/skyscraper8.Manual/skyscraper8.Manual.tex
@@ -177,6 +177,15 @@ This document was typeset in \LaTeX{}, using the TeX Live distribution, and whil
\subsection{Personal remarks and some useless bonus information}
+\subsubsection{How and why skyscraper8 began: A young man's dream}
+Ever since I was a child, I was fascinated by TV. But not actually watching it, rather understanding how it works. I grew up in the 90s, in an area where Cable TV was not really available, and terristial reception (yeah, those TVs with bunny ears!) only worked when it felt like it. So satellite was the best way to get my childish fix of cartoons! We can say the dish on my roof has always been a companion. Far more interesting than actually watching TV was scanning through the printed TV guides. I was curious. How did they make these? And how would I make one myself? I wondered. Of course my parents wouldn't know - they're not techies. \\
+
+Of course, as I got older, I eventually moved onto other things. Like programming, trading cards, and video games. But just like with the TV, I eventually got more interested in how these games work, instead of actually playing them. \\
+
+I got internet access much later in my life than my peers did, and when I found out that there are forums in which people discuss the technicalities about video games, it blew my mind. I used to be a frequent reader (and occasional contributor) of the XeNTaX\footnote{Unfortunately, that forum is long gone from the internet, but can still be experienced thanks to the amazing work of the people over at the Internet Archive: \url{https://web.archive.org/web/20230925120533/https://forum.xentax.com/ }} forum, from where I learned a lot! \\
+
+At the time, my circle of friends was crazy about Yu-Gi-Oh! Online 3, which was an excellent simulation of the trading card game by the same name.
+
\subsubsection{Music!}
Like a lot of programmers, I do enjoy listening to music while working. Some programmers even put song references in their software. Like how MKVToolnix' version names are actually song names, or how BSD developer fk even put \href{https://www.fabiankeil.de/nutzloseinfos.html}{a list of albums on his website} listing what albums he listened to while making it. Although this is absolutely useless, I'd liketo do this as well. Therefore, here follows a list of musical albums I listened to while developing skyscraper8 - no claim to completeness.
diff --git a/skyscraper8.sln.DotSettings.user b/skyscraper8.sln.DotSettings.user
index 33fbc3f..296c055 100644
--- a/skyscraper8.sln.DotSettings.user
+++ b/skyscraper8.sln.DotSettings.user
@@ -1,4 +1,12 @@
+ ForceIncluded
ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
ForceIncluded
+ ForceIncluded
<data><HostParameters type="LocalHostParameters" /><Argument type="StandaloneArgument"><Arguments IsNull="False"></Arguments><FileName IsNull="False"></FileName><WorkingDirectory IsNull="False"></WorkingDirectory><Scope><ProcessFilters /></Scope></Argument><Info type="TimelineInfo" /><CoreOptions type="CoreOptions"><CoreTempPath IsNull="False"></CoreTempPath><RemoteEndPoint IsNull="False"></RemoteEndPoint><AdditionalEnvironmentVariables /></CoreOptions><HostOptions type="HostOptions"><HostTempPath IsNull="False"></HostTempPath></HostOptions></data>
\ No newline at end of file
diff --git a/skyscraper8/Dvb/DataBroadcasting/MultiprotocolEncapsulationEventHandler.cs b/skyscraper8/Dvb/DataBroadcasting/MultiprotocolEncapsulationEventHandler.cs
index b99bdaf..09fb4cb 100644
--- a/skyscraper8/Dvb/DataBroadcasting/MultiprotocolEncapsulationEventHandler.cs
+++ b/skyscraper8/Dvb/DataBroadcasting/MultiprotocolEncapsulationEventHandler.cs
@@ -7,7 +7,7 @@ using skyscraper5.Ietf.Rfc971;
namespace skyscraper5.Dvb.DataBroadcasting
{
- interface IMultiprotocolEncapsulationEventHandler
+ public interface IMultiprotocolEncapsulationEventHandler
{
void OnIpv4PacketArrival(InternetHeader internetHeader, byte[] ipv4Packet);
void OnIpDatagram(int sourcePid, byte[] payload);
diff --git a/skyscraper8/GS/BBHeader.cs b/skyscraper8/GS/BBHeader.cs
index bd57e77..13228a3 100644
--- a/skyscraper8/GS/BBHeader.cs
+++ b/skyscraper8/GS/BBHeader.cs
@@ -27,12 +27,12 @@ public class BBHeader : Validatable
SyncByte = BbHeaderSpan[6];
SyncD = BbHeaderSpan[7] << 8 | BbHeaderSpan[8];
+ SyncD /= 8;
- ChecksumValid = DvbCrc8.Compute(BbHeaderSpan) == 0;
- Valid = ChecksumValid;
+ //ChecksumValid = DvbCrc8.Compute(BbHeaderSpan) == 0;
+ //Valid = ChecksumValid;
+ Valid = true;
}
-
- public bool ChecksumValid { get; private set; }
public int SyncD { get; private set; }
diff --git a/skyscraper8/GS/BBframeDeencapsulator3.cs b/skyscraper8/GS/BBframeDeencapsulator3.cs
index 791235c..afbbba8 100644
--- a/skyscraper8/GS/BBframeDeencapsulator3.cs
+++ b/skyscraper8/GS/BBframeDeencapsulator3.cs
@@ -1,9 +1,16 @@
using log4net;
+using skyscraper5.Dvb.DataBroadcasting;
namespace skyscraper8.GSE;
public class BbframeDeencapsulator3 : IBbframeDeencapsulator
{
+ public BbframeDeencapsulator3(IMultiprotocolEncapsulationEventHandler mpeEventHandler)
+ {
+ _mpeEventHandler = mpeEventHandler;
+ }
+
+ private readonly IMultiprotocolEncapsulationEventHandler _mpeEventHandler;
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private long numPushed;
public void PushPacket(byte[] bbframe)
@@ -20,8 +27,6 @@ public class BbframeDeencapsulator3 : IBbframeDeencapsulator
numPushed++;
BBHeader bbHeader = new BBHeader(bbframe, 1);
- if (!bbHeader.ChecksumValid)
- return;
if (!bbHeader.Valid)
return;
@@ -30,7 +35,10 @@ public class BbframeDeencapsulator3 : IBbframeDeencapsulator
if (mis[bbHeader.Matype2] == null)
{
logger.InfoFormat("Found a stream on MIS {0}",bbHeader.Matype2);
- mis[bbHeader.Matype2] = new GsTypeDetector();
+ mis[bbHeader.Matype2] = new GsTypeDetector(bbHeader.Matype2)
+ {
+ mpeEventHandler = this._mpeEventHandler
+ };
}
mis[bbHeader.Matype2].PushFrame(bbHeader, new ReadOnlySpan(bbframe, 11, bbframe.Length - 11));
diff --git a/skyscraper8/GS/GSE-HEM/GseHemReader.cs b/skyscraper8/GS/GSE-HEM/GseHemReader.cs
new file mode 100644
index 0000000..364e6b3
--- /dev/null
+++ b/skyscraper8/GS/GSE-HEM/GseHemReader.cs
@@ -0,0 +1,111 @@
+using log4net;
+using skyscraper5.Dvb.DataBroadcasting;
+using skyscraper5.Skyscraper.IO;
+using skyscraper8.GSE.GSE;
+
+namespace skyscraper8.GSE.GSE_HEM;
+
+public class GseHemReader : IMisHandler
+{
+ public GseHemReader(IMultiprotocolEncapsulationEventHandler mpeEventHandler)
+ {
+ rayBuffer = new RayBuffer();
+ this.mpeEventHandler = mpeEventHandler;
+ }
+
+ private IMultiprotocolEncapsulationEventHandler mpeEventHandler;
+ private GseLabel lastLabel;
+ private RayBuffer rayBuffer;
+ private const int BUFFER_THRESHOLD = 65536 * 2; //Twice the maximum PDU size of GSE. That way we can guarantee we have one full PDU in buffer.
+ private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
+
+ public void PushFrame(BBHeader bbHeader, ReadOnlySpan readOnlySpan)
+ {
+ MemoryStream ms = new MemoryStream(readOnlySpan.ToArray());
+ rayBuffer.Enqueue(ms, bbHeader.SyncD);
+
+ while (rayBuffer.AvailableBytes > BUFFER_THRESHOLD)
+ {
+ byte a = rayBuffer.ReadUInt8();
+ bool startIndicator = (a & 0x80) != 0;
+ bool endIndicator = (a & 0x40) != 0;
+ int labelTypeIndicator = (a & 0x30) >> 4;
+ if (!startIndicator && !endIndicator)
+ {
+ throw new NotImplementedException("I didn't expect a GSE Padding packet in GSE-HEM. Please share a sample of this stream, so I can implement this.");
+ }
+ else
+ {
+ GsePacket child = new GsePacket(startIndicator, endIndicator, labelTypeIndicator);
+
+ int gseLength = (a & 0x0f) << 8;
+ gseLength += rayBuffer.ReadUInt8();
+ if (!startIndicator || !endIndicator)
+ {
+ //According to ETSI TS 102 606-1 V1.2.1, HEM does not fragment packets. So we lost our sync!
+ rayBuffer.Resync();
+ return;
+ }
+
+ if (startIndicator && !endIndicator)
+ {
+ throw new NotImplementedException("I didn't expect an open-ended GSE Packet in GSE-HEM. Please share a sample of this stream, so I can implement this.");
+ }
+
+ if (startIndicator)
+ {
+ child.ProtocolType = rayBuffer.ReadUInt16BE();
+ gseLength -= 2;
+ switch (labelTypeIndicator)
+ {
+ case 0:
+ child.Label = new _6byteLabel(rayBuffer.ReadBytes(6));
+ gseLength -= 6;
+ lastLabel = child.Label;
+ break;
+ case 1:
+ child.Label = new _3byteLabel(rayBuffer.ReadBytes(3));
+ gseLength -= 3;
+ lastLabel = child.Label;
+ break;
+ case 2:
+ child.Label = BroadcastLabel.GetInstance();
+ break;
+ case 3:
+ child.Label = lastLabel;
+ break;
+ default:
+ throw new NotImplementedException(String.Format("Unknown label type indicator: {0}", labelTypeIndicator));
+ }
+ }
+
+ if (!startIndicator && endIndicator)
+ gseLength -= 4;
+
+ child.GseDataBytes = rayBuffer.ReadBytes(gseLength);
+
+ if (!startIndicator && endIndicator)
+ throw new NotImplementedException("I didn't expect a GSE packet with a missing head in GSE-HEM. Please share a sample of this stream, so I can implement this.");
+
+ HandlePacket(child);
+ }
+ }
+ }
+
+ private void HandlePacket(GsePacket packet)
+ {
+ if (packet.StartIndicator && packet.EndIndicator)
+ {
+ switch (packet.ProtocolType)
+ {
+ case 0x0800:
+ mpeEventHandler.OnIpDatagram(0x010e,packet.GseDataBytes);
+ return;
+ default:
+ logger.WarnFormat("This GSE-HEM stream contains traffic other than IP. IP is type 0x0800, but we got 0x{0:X4} here.", packet.ProtocolType);
+ return;
+ }
+ }
+ throw new NotImplementedException(packet.ToString());
+ }
+}
\ No newline at end of file
diff --git a/skyscraper8/GS/GSE-HEM/RayBuffer.cs b/skyscraper8/GS/GSE-HEM/RayBuffer.cs
new file mode 100644
index 0000000..4ddf0b9
--- /dev/null
+++ b/skyscraper8/GS/GSE-HEM/RayBuffer.cs
@@ -0,0 +1,111 @@
+using skyscraper5.Skyscraper.IO;
+
+namespace skyscraper8.GSE.GSE_HEM;
+
+public class RayBuffer
+{
+ private MemoryStream currentItem;
+ private Queue> queue;
+
+ public int QueuedItems
+ {
+ get
+ {
+ int result = 0;
+ if (currentItem != null)
+ result++;
+ if (queue != null)
+ result += queue.Count;
+ return result;
+ }
+ }
+
+ public void Enqueue(MemoryStream ms, int syncPoint)
+ {
+ if (currentItem == null)
+ {
+ currentItem = ms;
+ currentItem.Position = syncPoint;
+ return;
+ }
+ else
+ {
+ if (queue == null)
+ queue = new Queue>();
+ queue.Enqueue(new Tuple(ms, syncPoint));
+ }
+ }
+
+ public long AvailableBytes
+ {
+ get
+ {
+ if (currentItem == null)
+ return 0;
+
+ long result = currentItem.GetAvailableBytes();
+ if (queue != null)
+ {
+ result += queue.Select(x => x.Item1.GetAvailableBytes()).Sum();
+ }
+
+ return result;
+ }
+ }
+
+public byte ReadUInt8()
+ {
+ byte[] tmp = new byte[1];
+ if (Read(tmp, 0, 1) != 1)
+ throw new IOException("ReadUInt8 failed");
+ return tmp[0];
+ }
+
+ private int Read(byte[] outBuffer, int offset, int count)
+ {
+ int result = 0;
+ while (count > 0)
+ {
+ int stepSize = Math.Min(count, (int)currentItem.GetAvailableBytes());
+ int stepResult = currentItem.Read(outBuffer, offset, stepSize);
+ offset += stepResult;
+ count -= stepResult;
+ result += stepResult;
+ if (currentItem.GetAvailableBytes() == 0)
+ {
+ currentItem = queue.Dequeue().Item1;
+ }
+ }
+
+ return result;
+ }
+
+ public ushort ReadUInt16BE()
+ {
+ byte[] tmp = new byte[2];
+ if (Read(tmp, 0, 2) != 2)
+ throw new IOException("ReadUInt16BE failed");
+ if (BitConverter.IsLittleEndian)
+ (tmp[0], tmp[1]) = (tmp[1], tmp[0]);
+ return BitConverter.ToUInt16(tmp, 0);
+ }
+
+ public byte[] ReadBytes(int p0)
+ {
+ byte[] tmp = new byte[p0];
+ if (Read(tmp, 0, p0) != p0)
+ throw new IOException(String.Format("Reading {0} bytes failed.", p0));
+ return tmp;
+ }
+
+ public void Resync()
+ {
+ Tuple tuple = queue.Dequeue();
+ currentItem = tuple.Item1;
+ currentItem.Position = tuple.Item2;
+ if (currentItem.Position > currentItem.Length)
+ {
+ Resync();
+ }
+ }
+}
\ No newline at end of file
diff --git a/skyscraper8/GS/GSE/GseFragmentation.cs b/skyscraper8/GS/GSE/GseFragmentation.cs
new file mode 100644
index 0000000..838a65a
--- /dev/null
+++ b/skyscraper8/GS/GSE/GseFragmentation.cs
@@ -0,0 +1,44 @@
+namespace skyscraper8.GSE.GSE;
+
+public class GseFragmentation
+{
+ public GseFragmentation(GsePacket child)
+ {
+ this.ProtocolType = child.ProtocolType.Value;
+ this.Label = child.Label;
+ AddFragement(child);
+ }
+
+ private List fragments;
+
+ public void AddFragement(GsePacket packet)
+ {
+ if (fragments == null)
+ fragments = new List();
+
+ fragments.Add(packet.GseDataBytes);
+ }
+
+ public GseLabel Label { get; private set; }
+
+ public ushort ProtocolType { get; private set; }
+
+ public bool Validate()
+ {
+ //To be implemented...
+ return true;
+ }
+
+ public byte[] GetGseDataBytes()
+ {
+ int totalLength = fragments.Select(x => x.Length).Sum();
+ byte[] buffer = new byte[totalLength];
+ int offset = 0;
+ for (int i = 0; i < fragments.Count; i++)
+ {
+ Array.Copy(fragments[i],0,buffer,offset,fragments[i].Length);
+ offset += fragments[i].Length;
+ }
+ return buffer;
+ }
+}
\ No newline at end of file
diff --git a/skyscraper8/GS/GSE/GseLabel.cs b/skyscraper8/GS/GSE/GseLabel.cs
new file mode 100644
index 0000000..563c871
--- /dev/null
+++ b/skyscraper8/GS/GSE/GseLabel.cs
@@ -0,0 +1,65 @@
+using System.Net.NetworkInformation;
+
+namespace skyscraper8.GSE.GSE;
+
+public abstract class GseLabel
+{
+ public abstract int Length { get; }
+ public abstract string ToString();
+}
+
+public class _6byteLabel : GseLabel
+{
+ public _6byteLabel(byte[] buffer)
+ {
+ MAC = new PhysicalAddress(buffer);
+ }
+
+ public PhysicalAddress MAC { get; private set; }
+
+ override public string ToString()
+ {
+ return MAC.ToString();
+ }
+
+ public override int Length => 6;
+}
+
+public class _3byteLabel : GseLabel
+{
+ public _3byteLabel(byte[] buffer)
+ {
+ Label = buffer;
+ }
+
+ public byte[] Label { get; private set; }
+
+ override public string ToString()
+ {
+ return BitConverter.ToString(Label);
+ }
+
+ override public int Length => 3;
+}
+
+public class BroadcastLabel : GseLabel
+{
+ private BroadcastLabel() {}
+
+ override public string ToString()
+ {
+ return "";
+ }
+
+ override public int Length => 0;
+
+ private static BroadcastLabel _instance;
+ public static BroadcastLabel GetInstance()
+ {
+ if (_instance == null)
+ {
+ _instance = new BroadcastLabel();
+ }
+ return _instance;
+ }
+}
\ No newline at end of file
diff --git a/skyscraper8/GS/GSE/GsePacket.cs b/skyscraper8/GS/GSE/GsePacket.cs
new file mode 100644
index 0000000..0b1bdf5
--- /dev/null
+++ b/skyscraper8/GS/GSE/GsePacket.cs
@@ -0,0 +1,27 @@
+namespace skyscraper8.GSE.GSE;
+
+public class GsePacket
+{
+ public bool StartIndicator { get; }
+ public bool EndIndicator { get; }
+ public int LabelTypeIndicator { get; }
+ public byte? FragmentId { get; set; }
+ public ushort? TotalLength { get; set; }
+ public ushort? ProtocolType { get; set; }
+ public GseLabel Label { get; set; }
+ public byte[] GseDataBytes { get; set; }
+ public uint Crc32 { get; set; }
+
+ public GsePacket(bool startIndicator, bool endIndicator, int labelTypeIndicator)
+ {
+ StartIndicator = startIndicator;
+ EndIndicator = endIndicator;
+ LabelTypeIndicator = labelTypeIndicator;
+ }
+
+ public override string ToString()
+ {
+ return
+ $"{nameof(StartIndicator)}: {StartIndicator}, {nameof(EndIndicator)}: {EndIndicator}, {nameof(LabelTypeIndicator)}: {LabelTypeIndicator}, {nameof(FragmentId)}: {FragmentId}, {nameof(TotalLength)}: {TotalLength}, {nameof(ProtocolType)}: {ProtocolType}, {nameof(Label)}: {Label}";
+ }
+}
\ No newline at end of file
diff --git a/skyscraper8/GS/GSE/GseReader.cs b/skyscraper8/GS/GSE/GseReader.cs
new file mode 100644
index 0000000..e2272d1
--- /dev/null
+++ b/skyscraper8/GS/GSE/GseReader.cs
@@ -0,0 +1,145 @@
+using log4net;
+using skyscraper5.Dvb.DataBroadcasting;
+using skyscraper5.Skyscraper.IO;
+
+namespace skyscraper8.GSE.GSE;
+
+internal class GseReader : IMisHandler
+{
+ private GseLabel lastLabel;
+ public IMultiprotocolEncapsulationEventHandler mpeEventHandler { get; set; }
+ private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
+ public void PushFrame(BBHeader bbHeader, ReadOnlySpan readOnlySpan)
+ {
+ MemoryStream ms = new MemoryStream(readOnlySpan.ToArray());
+
+ while (ms.Position < ms.Length)
+ {
+ byte a = ms.ReadUInt8();
+ bool startIndicator = (a & 0x80) != 0;
+ bool endIndicator = (a & 0x40) != 0;
+ int labelTypeIndicator = (a & 0x30) >> 4;
+ if (!startIndicator && !endIndicator && labelTypeIndicator == 0)
+ {
+ //end of BBFrame
+ return;
+ }
+ else
+ {
+ int gseLength = (a & 0x0f);
+ gseLength <<= 8;
+ gseLength += ms.ReadUInt8();
+
+ GsePacket child = new GsePacket(startIndicator, endIndicator, labelTypeIndicator);
+ if (!startIndicator || !endIndicator)
+ {
+ child.FragmentId = ms.ReadUInt8();
+ gseLength--;
+ }
+
+ if (startIndicator && !endIndicator)
+ {
+ child.TotalLength = ms.ReadUInt16BE();
+ gseLength -= 2;
+ }
+
+ if (startIndicator)
+ {
+ child.ProtocolType = ms.ReadUInt16BE();
+ gseLength -= 2;
+ if (!endIndicator)
+ child.TotalLength -= 2;
+ switch (labelTypeIndicator)
+ {
+ case 0:
+ child.Label = new _6byteLabel(ms.ReadBytes(6));
+ gseLength -= 6;
+ if (!endIndicator)
+ child.TotalLength -= 6;
+ lastLabel = child.Label;
+ break;
+ case 1:
+ child.Label = new _3byteLabel(ms.ReadBytes(3));
+ gseLength -= 3;
+ if (!endIndicator)
+ child.TotalLength -= 3;
+ lastLabel = child.Label;
+ break;
+ case 2:
+ child.Label = BroadcastLabel.GetInstance();
+ break;
+ case 3:
+ child.Label = this.lastLabel;
+ break;
+ default:
+ throw new NotImplementedException(String.Format("Unknown label type: {0}", labelTypeIndicator));
+ }
+ }
+
+ if (!startIndicator && endIndicator)
+ gseLength -= 4; //for crc32
+
+ if (gseLength > ms.GetAvailableBytes())
+ return;
+ child.GseDataBytes = ms.ReadBytes(gseLength);
+
+ if (!startIndicator && endIndicator)
+ child.Crc32 = ms.ReadUInt32BE();
+
+ ProcessPacket(child);
+ }
+ }
+ }
+
+ private bool[] warnedEthertypes;
+ private GseFragmentation[] fragmentations;
+ private void ProcessPacket(GsePacket child)
+ {
+ if (!child.StartIndicator && child.EndIndicator)
+ {
+ if (fragmentations == null)
+ return;
+ GseFragmentation currentFragmentation = fragmentations[child.FragmentId.Value];
+ if (currentFragmentation == null)
+ return;
+ currentFragmentation.AddFragement(child);
+ if (currentFragmentation.Validate())
+ {
+ mpeEventHandler.OnIpDatagram(0x010e,currentFragmentation.GetGseDataBytes());
+ }
+
+ fragmentations[child.FragmentId.Value] = null;
+ return;
+ }
+
+ if (child.StartIndicator && !child.EndIndicator)
+ {
+ if (fragmentations == null)
+ fragmentations = new GseFragmentation[256];
+ fragmentations[child.FragmentId.Value] = new GseFragmentation(child);
+ return;
+ }
+
+ if (child.StartIndicator && child.EndIndicator)
+ {
+ switch (child.ProtocolType)
+ {
+ case 0x0800:
+ mpeEventHandler.OnIpDatagram(0x010e, child.GseDataBytes);
+ break;
+ default:
+ if (warnedEthertypes == null)
+ warnedEthertypes = new bool[0xffff];
+ if (!warnedEthertypes[child.ProtocolType.Value])
+ {
+ logger.WarnFormat("This GSE contains other traffic types (type {0:X4}) besides IP (type 0x0800). If it's not too much trouble, please consider submitting a sample.",child.ProtocolType.Value);
+ warnedEthertypes[child.ProtocolType.Value] = true;
+ }
+ break;
+ }
+
+ return;
+ }
+ throw new NotImplementedException(child.ToString());
+ }
+}
\ No newline at end of file
diff --git a/skyscraper8/GS/GsTypeDetector.cs b/skyscraper8/GS/GsTypeDetector.cs
index 3ef824d..bd67e56 100644
--- a/skyscraper8/GS/GsTypeDetector.cs
+++ b/skyscraper8/GS/GsTypeDetector.cs
@@ -1,9 +1,63 @@
+using log4net;
+using skyscraper5.Dvb.DataBroadcasting;
+using skyscraper8.GSE.GSE_HEM;
+using skyscraper8.GSE.GSE;
+
namespace skyscraper8.GSE;
public class GsTypeDetector : IMisHandler
{
+ public IMultiprotocolEncapsulationEventHandler mpeEventHandler { get; set; }
+ private readonly byte _misId;
+ private readonly ILog logger;
+ private HashSet> _postedStreamTypes;
+ public GsTypeDetector(byte misId)
+ {
+ _misId = misId;
+ logger = LogManager.GetLogger(String.Format("{0} MIS {1}",System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name,misId));
+ }
+
+ private GseReader gseReader;
+ private GseHemReader gseHemReader;
public void PushFrame(BBHeader bbHeader, ReadOnlySpan readOnlySpan)
{
- throw new NotImplementedException();
+ if (readOnlySpan.Length == 0)
+ {
+ return;
+ }
+
+ if (bbHeader.TsGs == 1 && bbHeader.SyncByte == 0)
+ {
+ //Looks like Continuous GSE.
+ if (gseReader == null)
+ {
+ gseReader = new GseReader();
+ gseReader.mpeEventHandler = mpeEventHandler;
+ }
+
+ gseReader.PushFrame(bbHeader, readOnlySpan);
+ return;
+ }
+
+ if (bbHeader.TsGs == 2 && bbHeader.SyncByte == 0)
+ {
+ //Looks like GSE-HEM
+ if (gseHemReader == null)
+ {
+ gseHemReader = new GseHemReader(mpeEventHandler);
+ }
+ gseHemReader.PushFrame(bbHeader, readOnlySpan);
+ return;
+ }
+
+ //We have no idea what this is.
+ Tuple streamTypeToPost = new Tuple(bbHeader.TsGs, bbHeader.SyncByte);
+ if (_postedStreamTypes == null)
+ _postedStreamTypes = new HashSet>();
+ 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);
+ }
}
}
\ No newline at end of file
diff --git a/skyscraper8/GS/POC/Pts2Bbf.cs b/skyscraper8/GS/POC/Pts2Bbf.cs
index e88fd63..8ebb6d8 100644
--- a/skyscraper8/GS/POC/Pts2Bbf.cs
+++ b/skyscraper8/GS/POC/Pts2Bbf.cs
@@ -44,7 +44,7 @@ public class Pts2Bbf
FileStream fileStream = file.OpenRead();
TsContext mpeg2 = new TsContext();
- mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(dumper));
+ mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(null, dumper));
DataStorage dataStorage = new InMemoryScraperStorage();
ObjectStorage objectStorage = new NullObjectStorage();
SkyscraperContext skyscraper = new SkyscraperContext(mpeg2, dataStorage, objectStorage);
diff --git a/skyscraper8/GS/POC/Stid135Test.cs b/skyscraper8/GS/POC/Stid135Test.cs
index 396c001..0ec03c7 100644
--- a/skyscraper8/GS/POC/Stid135Test.cs
+++ b/skyscraper8/GS/POC/Stid135Test.cs
@@ -1,6 +1,7 @@
using log4net;
using skyscraper5.Mpeg2;
using skyscraper5.Skyscraper.Scraper;
+using skyscraper5.Skyscraper.Scraper.Storage.Filesystem;
using skyscraper5.Skyscraper.Scraper.Storage.InMemory;
using skyscraper8.Skyscraper.Scraper.Storage;
@@ -13,13 +14,13 @@ public class Stid135Test
{
FileStream fileStream = file.OpenRead();
- BbframeDeencapsulator3 decap = new BbframeDeencapsulator3();
-
TsContext mpeg2 = new TsContext();
- mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(decap));
DataStorage dataStorage = new InMemoryScraperStorage();
- ObjectStorage objectStorage = new NullObjectStorage();
+ ObjectStorage objectStorage = new FilesystemStorage(new DirectoryInfo("nip"));
SkyscraperContext skyscraper = new SkyscraperContext(mpeg2, dataStorage, objectStorage);
+
+ mpeg2.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(skyscraper));
+
skyscraper.InitalizeFilterChain();
skyscraper.IngestFromStream(fileStream);
diff --git a/skyscraper8/GS/Stid135BbFrameReader.cs b/skyscraper8/GS/Stid135BbFrameReader.cs
index 0a1dba5..1859376 100644
--- a/skyscraper8/GS/Stid135BbFrameReader.cs
+++ b/skyscraper8/GS/Stid135BbFrameReader.cs
@@ -6,6 +6,7 @@ using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
+using skyscraper5.Dvb.DataBroadcasting;
namespace skyscraper8.GSE
{
@@ -13,10 +14,10 @@ namespace skyscraper8.GSE
{
private IBbframeDeencapsulator deencapsulator;
- public Stid135BbFrameReader(IBbframeDeencapsulator deencapsulator = null)
+ public Stid135BbFrameReader(IMultiprotocolEncapsulationEventHandler mpeEventHandler, IBbframeDeencapsulator deencapsulator = null)
{
if (deencapsulator == null)
- deencapsulator = new BbframeDeencapsulator3();
+ deencapsulator = new BbframeDeencapsulator3(mpeEventHandler);
this.deencapsulator = deencapsulator;
}
diff --git a/skyscraper8/GS/TsGsType.cs b/skyscraper8/GS/TsGsType.cs
new file mode 100644
index 0000000..94c69cc
--- /dev/null
+++ b/skyscraper8/GS/TsGsType.cs
@@ -0,0 +1,9 @@
+namespace skyscraper8.GSE;
+
+public enum TsGsType
+{
+ GenericPacketized,
+ GenericContinuous,
+ GseHem,
+ Transport
+}
\ No newline at end of file
diff --git a/skyscraper8/Mpeg2/PacketFilter/ScrambleFilter.cs b/skyscraper8/Mpeg2/PacketFilter/ScrambleFilter.cs
index f452b81..5a51573 100644
--- a/skyscraper8/Mpeg2/PacketFilter/ScrambleFilter.cs
+++ b/skyscraper8/Mpeg2/PacketFilter/ScrambleFilter.cs
@@ -17,7 +17,12 @@ namespace skyscraper5.src.Mpeg2.PacketFilter
{
protected override bool PassPacketEx(TsPacket packet)
{
- return packet.TSC == 0;
+ if (packet.TSC == 0)
+ return true;
+ else
+ {
+ return false;
+ }
}
}
}
diff --git a/skyscraper8/Program.cs b/skyscraper8/Program.cs
index 09db3be..5a9c125 100644
--- a/skyscraper8/Program.cs
+++ b/skyscraper8/Program.cs
@@ -41,7 +41,7 @@ namespace skyscraper5
class Program
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
- private const int PUBLIC_RELEASE = 9;
+ private const int PUBLIC_RELEASE = 10;
private static void IntegrationTest()
{
/*List ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs
index 0ecfeb2..e85b738 100644
--- a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs
+++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs
@@ -301,7 +301,7 @@ namespace skyscraper5.Skyscraper.Scraper
{
if (!DvbContext.IsPidProcessorPresent(0x010e))
{
- DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader());
+ DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(this));
UiJunction?.SetGseMode();
LogEvent(SkyscraperContextEvent.SpecialTsMode, "STiD135 encapsulated GS detected.");
SpecialTsType = 3;
@@ -356,7 +356,7 @@ namespace skyscraper5.Skyscraper.Scraper
{
if (!DvbContext.IsPidProcessorPresent(0x010e))
{
- DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader());
+ DvbContext.RegisterPacketProcessor(0x010e, new Stid135BbFrameReader(this));
UiJunction?.SetGseMode();
LogEvent(SkyscraperContextEvent.SpecialTsMode, "STiD135 encapsulated GS detected.");
SpecialTsType = 3;
diff --git a/skyscraper8/Skyscraper/Scraper/Storage/NullObjectStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/NullObjectStorage.cs
index 939af83..bad78b9 100644
--- a/skyscraper8/Skyscraper/Scraper/Storage/NullObjectStorage.cs
+++ b/skyscraper8/Skyscraper/Scraper/Storage/NullObjectStorage.cs
@@ -74,12 +74,11 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
public bool DvbNipTestForFile(string announcedFileContentLocation)
{
- throw new NotImplementedException();
+ return true;
}
public void DvbNipFileArrival(NipActualCarrierInformation carrier, FluteListener listener)
{
- throw new NotImplementedException();
}
public void StoreIqGraph(Guid jobGuid, long frequency, char polarity, IqChartData plot)
diff --git a/skyscraper8/log4net.config b/skyscraper8/log4net.config
index 9755f52..366341b 100644
--- a/skyscraper8/log4net.config
+++ b/skyscraper8/log4net.config
@@ -13,15 +13,15 @@
-
+
+
-
+ -->
\ No newline at end of file