diff --git a/DataTableStorages/skyscraper5.Data.PostgreSql/InteractionChannel.cs b/DataTableStorages/skyscraper5.Data.PostgreSql/InteractionChannel.cs index 5898e64..c9eccb3 100644 --- a/DataTableStorages/skyscraper5.Data.PostgreSql/InteractionChannel.cs +++ b/DataTableStorages/skyscraper5.Data.PostgreSql/InteractionChannel.cs @@ -11,6 +11,7 @@ using System.Diagnostics; using System.Linq; using System.Net.NetworkInformation; using System.Security.Cryptography; +using skyscraper8.InteractionChannel.Model; namespace skyscraper5.Data.PostgreSql { @@ -949,6 +950,21 @@ namespace skyscraper5.Data.PostgreSql return false; } + public bool TestForRcs2Nit(RcsNit nit) + { + throw new NotImplementedException(); + } + + public void InsertRcs2Nit(RcsNit nit) + { + throw new NotImplementedException(); + } + + public bool UpdateRcs2Tdt(ushort interactiveNetworkId, DateTime tdtTimestamp) + { + throw new NotImplementedException(); + } + private bool AreArraysEqual(byte[] l, byte[] r) { if (l.Length != r.Length) @@ -972,29 +988,6 @@ namespace skyscraper5.Data.PostgreSql command.ExecuteNonQuery(); } - public bool TestForTerminalBurstTimePlan2(ushort interactiveNetworkId, byte tbtp2GroupId, byte frameFrameNumber) - { - throw new NotImplementedException(); - } - public void StoreTerminalBurstTimePlan2(ushort interactiveNetworkId, byte tbtp2GroupId, Tbtp2.Frame frame) - { - throw new NotImplementedException(); - } - public bool TestForFrameComposition2(ushort networkId, Fct2.Frame fct2) - { - throw new NotImplementedException(); - } - public void InsertFct2Frame(ushort networkId, Fct2.Frame frame) - { - throw new NotImplementedException(); - } - public bool TestForBroadcastConfiguration(ushort networkId, byte txTypeTxType) - { - throw new NotImplementedException(); - } - public void InsertBroadcastConfiguration(ushort networkId, Bct.BroadcastConfiguration txType) - { - throw new NotImplementedException(); - } - } + + } } diff --git a/skyscraper8/Dvb/Descriptors/0x40_NetworkNameDescriptor.cs b/skyscraper8/Dvb/Descriptors/0x40_NetworkNameDescriptor.cs index e4e841c..11cbc2f 100644 --- a/skyscraper8/Dvb/Descriptors/0x40_NetworkNameDescriptor.cs +++ b/skyscraper8/Dvb/Descriptors/0x40_NetworkNameDescriptor.cs @@ -17,6 +17,7 @@ namespace skyscraper5.Dvb.Descriptors public NetworkNameDescriptor(byte[] buffer) { NetworkName = En300468AnnexATextDecoder.GetInstance().Decode(buffer); + Valid = true; } public string NetworkName { get; private set; } diff --git a/skyscraper8/Dvb/Descriptors/0x43_SatelliteDeliverySystemDescriptor.cs b/skyscraper8/Dvb/Descriptors/0x43_SatelliteDeliverySystemDescriptor.cs index 604ea09..c338d74 100644 --- a/skyscraper8/Dvb/Descriptors/0x43_SatelliteDeliverySystemDescriptor.cs +++ b/skyscraper8/Dvb/Descriptors/0x43_SatelliteDeliverySystemDescriptor.cs @@ -50,6 +50,8 @@ namespace skyscraper5.Dvb.Descriptors break; } } + + Valid = true; } public int ModulationType { get; private set; } @@ -100,5 +102,20 @@ namespace skyscraper5.Dvb.Descriptors NineOfTen = 9, NoConventionalCoding = 15 } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + sb.Append(this.OrbitalPosition); + sb.Append("°"); + sb.Append(this.East ? 'E' : 'W'); + sb.Append("/"); + sb.Append(Frequency / 100); + sb.Append("/"); + sb.Append(this.Polarization.ToString()[0]); + sb.Append("/"); + sb.Append(this.SymbolRate / 10); + return sb.ToString(); + } } } diff --git a/skyscraper8/Dvb/Descriptors/0x4A_LinkageDescriptor.cs b/skyscraper8/Dvb/Descriptors/0x4A_LinkageDescriptor.cs index 2af5419..1cb89bd 100644 --- a/skyscraper8/Dvb/Descriptors/0x4A_LinkageDescriptor.cs +++ b/skyscraper8/Dvb/Descriptors/0x4A_LinkageDescriptor.cs @@ -351,5 +351,10 @@ namespace skyscraper5.Dvb.Descriptors { return HashCode.Combine((int)LinkageType, ServiceId, OriginalNetworkId, TransportStreamId); } + + public override string ToString() + { + return String.Format("{0} on (0x{1:X4},0x{2:X4},0x{3:X4})", LinkageType, OriginalNetworkId, TransportStreamId, ServiceId); + } } } diff --git a/skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs b/skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs index 0281042..623c465 100644 --- a/skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs +++ b/skyscraper8/GS/GSE-BFBS/GseL2SHandler.cs @@ -7,6 +7,8 @@ using skyscraper5.src.InteractionChannel; using skyscraper5.src.InteractionChannel.Model; using skyscraper5.src.InteractionChannel.Model2; using skyscraper8.InteractionChannel; +using skyscraper8.InteractionChannel.Model; +using skyscraper8.InteractionChannel.Model2; namespace skyscraper8.GS.GSE_BFBS { @@ -31,6 +33,16 @@ namespace skyscraper8.GS.GSE_BFBS MemoryStream ms = new MemoryStream(gseTableStructure.TableContent, false); switch (gseTableStructure.TableId) { + case 0x40: + RcsNit nit = new RcsNit(ms); + if (!nit.Valid) + { + Context.Rcs2Output.OnInteractionChannelError(InteractionChannelErrorState.NitInvalid); + return; + } + + Context.Rcs2Output.OnRcs2Nit(gseTableStructure.InteractiveNetworkId, nit); + return; case 0x41: Rmt rmt = new Rmt(ms, true); if (!rmt.Valid) @@ -41,6 +53,26 @@ namespace skyscraper8.GS.GSE_BFBS Context.Rcs2Output.OnRcsMap(rmt); return; + case 0x70: + Rcs2Tdt tdt = new Rcs2Tdt(ms); + if (!tdt.Valid) + { + Context.Rcs2Output.OnInteractionChannelError(InteractionChannelErrorState.TdtInvalid); + return; + } + + Context.Rcs2Output.OnRcs2Tdt(gseTableStructure.InteractiveNetworkId, tdt); + return; + case 0xa0: + Sct sct = new Sct(ms); + if (!sct.Valid) + { + Context.Rcs2Output.OnInteractionChannelError(InteractionChannelErrorState.SctInvalid); + return; + } + + Context.Rcs2Output.OnSuperframeComposition(gseTableStructure.InteractiveNetworkId, sct); + return; case 0xa4: Cmt cmt = new Cmt(ms); if (!cmt.Valid) @@ -50,6 +82,24 @@ namespace skyscraper8.GS.GSE_BFBS } Context.Rcs2Output.OnCorrectionMessage(gseTableStructure.InteractiveNetworkId, cmt); return; + case 0xab: + Fct2 fct2 = new Fct2(ms); + if (!fct2.Valid) + { + Context.Rcs2Output.OnInteractionChannelError(InteractionChannelErrorState.Fct2Invalid); + return; + } + Context.Rcs2Output.OnFrameComposition2(gseTableStructure.InteractiveNetworkId, fct2); + return; + case 0xac: + Bct bct = new Bct(ms); + if (!bct.Valid) + { + Context.Rcs2Output.OnInteractionChannelError(InteractionChannelErrorState.BctInvalid); + return; + } + Context.Rcs2Output.OnBroadcastConfiguration(gseTableStructure.InteractiveNetworkId, bct); + return; case 0xad: Tbtp2 tbtp2 = new Tbtp2(ms); if (!tbtp2.Valid) diff --git a/skyscraper8/InteractionChannel/InteractionChannelErrorState.cs b/skyscraper8/InteractionChannel/InteractionChannelErrorState.cs index 73658b4..8b05d63 100644 --- a/skyscraper8/InteractionChannel/InteractionChannelErrorState.cs +++ b/skyscraper8/InteractionChannel/InteractionChannelErrorState.cs @@ -23,6 +23,8 @@ namespace skyscraper5.src.InteractionChannel Tbtp2Invalid, Tmst2Invalid, BctInvalid, - GseTableStructureInvalid + GseTableStructureInvalid, + NitInvalid, + TdtInvalid } } diff --git a/skyscraper8/InteractionChannel/InteractionChannelHandler.cs b/skyscraper8/InteractionChannel/InteractionChannelHandler.cs index 11f45c2..3330de2 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.Model; using skyscraper8.InteractionChannel.Model2; namespace skyscraper5.src.InteractionChannel @@ -33,5 +34,7 @@ namespace skyscraper5.src.InteractionChannel void OnTerminalBurstTimePlan2(ushort interactiveNetworkId, Tbtp2 tbtp2); void OnFrameComposition2(ushort networkId, Fct2 fct2); void OnBroadcastConfiguration(ushort networkId, Bct bct); + void OnRcs2Nit(ushort interactiveNetworkId, RcsNit nit); + void OnRcs2Tdt(ushort interactiveNetworkId, Rcs2Tdt tdt); } } diff --git a/skyscraper8/InteractionChannel/Model/RcsNit.cs b/skyscraper8/InteractionChannel/Model/RcsNit.cs new file mode 100644 index 0000000..92c44a4 --- /dev/null +++ b/skyscraper8/InteractionChannel/Model/RcsNit.cs @@ -0,0 +1,127 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using skyscraper5.Dvb.Descriptors; +using skyscraper5.Mpeg2; +using skyscraper5.Skyscraper; +using skyscraper5.Skyscraper.IO; + +namespace skyscraper8.InteractionChannel.Model +{ + public class RcsNit : Validatable + { + private static TsDescriptorUnpacker unpacker; + public RcsNit(MemoryStream ms) + { + byte byteA = ms.ReadUInt8(); + byteA &= 0x0f; + int networkDescriptorsLength = byteA << 8; + networkDescriptorsLength += ms.ReadUInt8(); + byte[] networkDescriptorsBytes = ms.ReadBytes(networkDescriptorsLength); + + if (unpacker == null) + unpacker = TsDescriptorUnpacker.GetInstance(); + if (!ParseNetworkDescriptors(unpacker.UnpackDescriptors(networkDescriptorsBytes, "NIT"))) + { + Valid = false; + return; + } + + byteA = ms.ReadUInt8(); + byteA &= 0x0f; + int multiplexStreamsSpecLength = byteA << 8; + multiplexStreamsSpecLength += ms.ReadUInt8(); + byte[] multiplexStreamsSpecBytes = ms.ReadBytes(multiplexStreamsSpecLength); + Valid = ParseMultiplexStreamsSpec(multiplexStreamsSpecBytes); + } + + private bool ParseNetworkDescriptors(IEnumerable descriptors) + { + foreach (TsDescriptor descriptor in descriptors) + { + if (!descriptor.Valid) + continue; + switch (descriptor) + { + case NetworkNameDescriptor nnd: + this.NetworkName = nnd.NetworkName; + break; + case LinkageDescriptor ld: + if (Linkages == null) + Linkages = new List(); + Linkages.Add(ld); + break; + default: + throw new NotImplementedException(String.Format( + "The RCS2-NIT Parser doesn't understand descriptors of type 0x{0:X2} yet. Please consider sharing a sample of this stream.", + descriptor.GetDescriptorId())); + } + } + + return true; + } + + public string NetworkName { get; set; } + + public List Linkages { get; private set; } + + private bool ParseMultiplexStreamsSpec(byte[] buffer) + { + MemoryStream ms = new MemoryStream(buffer, false); + ForwardMultiplex = ms.ReadUInt16BE(); + OriginalNetworkId = ms.ReadUInt16BE(); + + byte byteA = ms.ReadUInt8(); + byteA &= 0x0f; + int transportDescriptorsLength = byteA << 8; + transportDescriptorsLength += ms.ReadUInt8(); + IEnumerable descriptors = unpacker.UnpackDescriptors(ms.ReadBytes(transportDescriptorsLength), "NIT"); + foreach (TsDescriptor descriptor in descriptors) + { + if (!descriptor.Valid) + continue; + switch (descriptor) + { + case SatelliteDeliverySystemDescriptor sdsd: + this.SatelliteDeliverySystem = sdsd; + break; + default: + throw new NotImplementedException(String.Format( + "The RCS2-NIT Muliplex-Stream-Spec Parser doesn't understand descriptors of type 0x{0:X2} yet. Please consider sharing a sample of this stream.", + descriptor.GetDescriptorId())); + } + } + + return true; + } + + public SatelliteDeliverySystemDescriptor SatelliteDeliverySystem { get; set; } + + public ushort OriginalNetworkId { get; set; } + + public ushort ForwardMultiplex { get; set; } + + protected bool Equals(RcsNit other) + { + return OriginalNetworkId == other.OriginalNetworkId && ForwardMultiplex == other.ForwardMultiplex; + } + + public override bool Equals(object? obj) + { + if (ReferenceEquals(null, obj)) + return false; + if (ReferenceEquals(this, obj)) + return true; + if (obj.GetType() != this.GetType()) + return false; + return Equals((RcsNit)obj); + } + + public override int GetHashCode() + { + return HashCode.Combine(OriginalNetworkId, ForwardMultiplex); + } + } +} diff --git a/skyscraper8/InteractionChannel/Model2/Fct2.cs b/skyscraper8/InteractionChannel/Model2/Fct2.cs index a9c837a..b3002bc 100644 --- a/skyscraper8/InteractionChannel/Model2/Fct2.cs +++ b/skyscraper8/InteractionChannel/Model2/Fct2.cs @@ -14,7 +14,7 @@ namespace skyscraper5.src.InteractionChannel.Model2 public Fct2(MemoryStream ms) { byte frameTypeLoopCount = ms.ReadUInt8(); - frameTypeLoopCount--; + frameTypeLoopCount++; FrameTypes = new Frame[frameTypeLoopCount]; for (int i = 0; i < frameTypeLoopCount; i++) { @@ -40,9 +40,11 @@ namespace skyscraper5.src.InteractionChannel.Model2 } byte sectionLoopCount = ms.ReadUInt8(); + sectionLoopCount++; FrameTypes[i].SectionLoop = new SectionLoop[sectionLoopCount]; for (int j = 0; j < sectionLoopCount; j++) { + FrameTypes[i].SectionLoop[j] = new SectionLoop(); FrameTypes[i].SectionLoop[j].DefaultTxType = ms.ReadUInt8(); FrameTypes[i].SectionLoop[j].FixedAccessMethod = (ms.ReadUInt8() & 0x0f); FrameTypes[i].SectionLoop[j].RepeatCount = ms.ReadUInt16BE(); diff --git a/skyscraper8/InteractionChannel/Model2/Rcs2Tdt.cs b/skyscraper8/InteractionChannel/Model2/Rcs2Tdt.cs new file mode 100644 index 0000000..caeb669 --- /dev/null +++ b/skyscraper8/InteractionChannel/Model2/Rcs2Tdt.cs @@ -0,0 +1,28 @@ +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 +{ + public class Rcs2Tdt : Validatable + { + public Rcs2Tdt(MemoryStream ms) + { + DateTime? dateTime = ms.ReadEtsiEn300468AnnexCDateTime(); + if (!dateTime.HasValue) + { + Valid = false; + return; + } + + Timestamp = dateTime.Value; + Valid = true; + } + + public DateTime Timestamp { get; set; } + } +} diff --git a/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs b/skyscraper8/InteractionChannel/NullInteractionChannelHandler.cs index 0b2732d..785d564 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.Model; using skyscraper8.InteractionChannel.Model2; namespace skyscraper5.src.InteractionChannel @@ -37,6 +38,16 @@ namespace skyscraper5.src.InteractionChannel { } + public void OnRcs2Nit(ushort interactiveNetworkId, RcsNit nit) + { + + } + + public void OnRcs2Tdt(ushort interactiveNetworkId, Rcs2Tdt tdt) + { + + } + public void OnFrameComposition2(ushort? networkId, Fct2 fct2) { diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs index f342f2b..e7feccf 100644 --- a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs +++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs @@ -84,6 +84,7 @@ using skyscraper8.Experimentals.OtvSsu; using skyscraper8.GS; using skyscraper8.GSE; using skyscraper8.Ieee802_1AB; +using skyscraper8.InteractionChannel.Model; using skyscraper8.InteractionChannel.Model2; using skyscraper8.Skyscraper.Net; using skyscraper8.Skyscraper.Scraper; @@ -429,7 +430,7 @@ namespace skyscraper5.Skyscraper.Scraper { string loggerName = String.Format("{0}{1}", IsChild ? ChildName + ", " : "", eventType.ToString()); LogManager.GetLogger(loggerName).Info(name); - if (eventType != SkyscraperContextEvent.TdtTime && eventType != SkyscraperContextEvent.TotTime && eventType != SkyscraperContextEvent.Scte35TimeSignal) + if (eventType != SkyscraperContextEvent.TdtTime && eventType != SkyscraperContextEvent.TotTime && eventType != SkyscraperContextEvent.Scte35TimeSignal && eventType != SkyscraperContextEvent.Rcs2TdtTime) { lastEventTimestamp = DateTime.Now; } @@ -2488,6 +2489,21 @@ namespace skyscraper5.Skyscraper.Scraper } } + public void OnRcs2Nit(ushort interactiveNetworkId, RcsNit nit) + { + if (!DataStorage.TestForRcs2Nit(nit)) + { + LogEvent(SkyscraperContextEvent.Rcs2Network, String.Format("Network ID #{0}, ({1}) on {2}", nit.OriginalNetworkId, nit.NetworkName, nit.SatelliteDeliverySystem.ToString())); + DataStorage.InsertRcs2Nit(nit); + } + } + + public void OnRcs2Tdt(ushort interactiveNetworkId, Rcs2Tdt tdt) + { + LogEvent(SkyscraperContextEvent.Rcs2TdtTime, String.Format("Network ID #{0}, {1}", interactiveNetworkId, tdt.Timestamp)); + DataStorage.UpdateRcs2Tdt(interactiveNetworkId, tdt.Timestamp); + } + void InteractionChannelHandler.OnTimeslotComposition(ushort interactiveNetworkId, Tct tct) { throw new NotImplementedException(); diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs index cdb8139..f38530c 100644 --- a/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs +++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContextEvent.cs @@ -89,6 +89,8 @@ TerminalBurstTimePlan2, FrameComposition2, BroadcastConfiguration, - EthernetLinkLayerDiscovery + EthernetLinkLayerDiscovery, + Rcs2Network, + Rcs2TdtTime } } diff --git a/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/DataStorage.cs index 4fcd253..d85639f 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.Model; using skyscraper8.InteractionChannel.Model2; using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; @@ -201,5 +202,8 @@ namespace skyscraper8.Skyscraper.Scraper.Storage void InsertFct2Frame(ushort networkId, Fct2.Frame frame); bool TestForBroadcastConfiguration(ushort networkId, byte txTypeTxType); void InsertBroadcastConfiguration(ushort networkId, Bct.BroadcastConfiguration txType); + bool TestForRcs2Nit(RcsNit nit); + void InsertRcs2Nit(RcsNit nit); + bool UpdateRcs2Tdt(ushort interactiveNetworkId, DateTime tdtTimestamp); } } diff --git a/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs b/skyscraper8/Skyscraper/Scraper/Storage/Filesystem/FilesystemStorage.cs index f8a9599..2621892 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.Model; using skyscraper8.InteractionChannel.Model2; using skyscraper8.Ses; using skyscraper8.SimpleServiceDiscoveryProtocol; @@ -1187,6 +1188,21 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.Filesystem throw new NotImplementedException(); } + public bool TestForRcs2Nit(RcsNit nit) + { + throw new NotImplementedException(); + } + + public void InsertRcs2Nit(RcsNit nit) + { + throw new NotImplementedException(); + } + + public bool UpdateRcs2Tdt(ushort interactiveNetworkId, DateTime tdtTimestamp) + { + 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 4f59fcd..2376946 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.Model; using skyscraper8.InteractionChannel.Model2; using skyscraper8.Skyscraper.Scraper.Storage; using skyscraper8.Skyscraper.Scraper.Storage.Utilities; @@ -1025,6 +1026,38 @@ namespace skyscraper5.Skyscraper.Scraper.Storage.InMemory broadcastConfigurations.Add(key, txType); } + private HashSet _rcs2Nits; + public bool TestForRcs2Nit(RcsNit nit) + { + if (_rcs2Nits == null) + return false; + + return _rcs2Nits.Contains(nit); + } + + public void InsertRcs2Nit(RcsNit nit) + { + if (_rcs2Nits == null) + _rcs2Nits = new HashSet(); + + _rcs2Nits.Add(nit); + } + + private DateTime[] _rcs2Timestamps; + public bool UpdateRcs2Tdt(ushort interactiveNetworkId, DateTime tdtTimestamp) + { + if (_rcs2Timestamps == null) + _rcs2Timestamps = new DateTime[ushort.MaxValue + 1]; + + if (_rcs2Timestamps[interactiveNetworkId] < tdtTimestamp) + { + _rcs2Timestamps[interactiveNetworkId] = tdtTimestamp; + return true; + } + + return false; + } + 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 f341f06..9747e31 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.Model; using skyscraper8.InteractionChannel.Model2; namespace skyscraper5.src.Skyscraper.Scraper.StreamAutodetection.Contestants @@ -210,7 +211,17 @@ namespace skyscraper5.src.Skyscraper.Scraper.StreamAutodetection.Contestants } } - public void OnFrameComposition2(ushort? networkId, Fct2 fct2) + public void OnRcs2Nit(ushort interactiveNetworkId, RcsNit nit) + { + //TODO: put validation logic in here, important! + } + + public void OnRcs2Tdt(ushort interactiveNetworkId, Rcs2Tdt tdt) + { + //TODO: put validation logic in here, important! + } + + public void OnFrameComposition2(ushort? networkId, Fct2 fct2) { if (fct2.FrameTypes.Length > 0) { diff --git a/skyscraper8/Skyscraper/Validatable.cs b/skyscraper8/Skyscraper/Validatable.cs index 92cc786..1df18f1 100644 --- a/skyscraper8/Skyscraper/Validatable.cs +++ b/skyscraper8/Skyscraper/Validatable.cs @@ -18,7 +18,7 @@ namespace skyscraper5.Skyscraper { if (!_valid.HasValue) { - throw new InvalidOperationException(String.Format("{0} doesn't know whether it's valid.", this.GetType().FullName)); + throw new InvalidOperationException(String.Format("{0} doesn't know whether it's valid. This is a bug, please share a sample of a stream that reproduces this.", this.GetType().FullName)); } return _valid.Value;