From f094503f206422581d14f2971c7c8cbcec694286 Mon Sep 17 00:00:00 2001 From: Fey Date: Wed, 17 Dec 2025 08:10:46 +0100 Subject: [PATCH] Bunch 'o DOCSIS Tests. --- skyscraper8.Tests/CapturedTests.cs | 109 ++++ skyscraper8.Tests/Feyllure.cs | 67 ++ skyscraper8.Tests/RootTests/DocsisTests.cs | 615 ++++++++++++++++++ skyscraper8.sln.DotSettings.user | 31 +- skyscraper8/Docsis/DocsisEnvironment.cs | 16 +- skyscraper8/Docsis/IDocsisEventHandler.cs | 3 + .../5_AuthReply.cs | 12 +- .../8_KeyReply.cs | 2 +- .../T13_V1_PrivacyKeyManagementResponse.cs | 8 +- .../MacManagement/T5_V1_RangingResponse.cs | 25 +- skyscraper8/Docsis/NullDocsisEventHandler.cs | 62 +- .../Experimentals/NdsSsu/NdsSsuDetector.cs | 2 +- .../Skyscraper/Scraper/SkyscraperContext.cs | 13 +- 13 files changed, 917 insertions(+), 48 deletions(-) create mode 100644 skyscraper8.Tests/CapturedTests.cs diff --git a/skyscraper8.Tests/CapturedTests.cs b/skyscraper8.Tests/CapturedTests.cs new file mode 100644 index 0000000..8831c35 --- /dev/null +++ b/skyscraper8.Tests/CapturedTests.cs @@ -0,0 +1,109 @@ +using System.IO; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using skyscraper5.Mpeg2; +using skyscraper5.Skyscraper.Scraper; +using skyscraper5.Skyscraper.Scraper.Storage.InMemory; +using skyscraper8.Skyscraper.Scraper.Storage; + +namespace skyscraper8.Tests; + +[TestClass] +public class CapturedTests : Feyllure +{ + [TestMethod] + public void RussianT2Mi() + { + FileStream streamSample = GetStreamSample("express_3928L_t2mi.ts"); + ProcessSample(streamSample); + streamSample.Close(); + //42931 uncovered + } + + [TestMethod] + public void Simmin() + { + FileStream streamSample = GetStreamSample("thor_11049v_simmin-radiomidun.ts"); + ProcessSample(streamSample); + streamSample.Close(); + //36611 uncovered + } + + [TestMethod] + public void GseDab() + { + FileStream streamSample = GetStreamSample("thor_10717v_gse-dab.ts"); + ProcessSample(streamSample); + streamSample.Close(); + //36446 uncovered + } + + [TestMethod] + public void SouthAmericanNip() + { + FileStream streamSample = GetStreamSample("argentinian-dvb-nip-000000.ts"); + ProcessSample(streamSample); + streamSample.Close(); + //35222 + } + + [TestMethod] + public void GseNip() + { + FileStream streamSample = GetStreamSample("astra1_12441v_gse-nip.ts"); + ProcessSample(streamSample); + streamSample.Close(); + //34545 + } + + [TestMethod] + public void GseNip2() + { + FileStream streamSample = GetStreamSample("astra1_11141h_gse_nip.ts"); + ProcessSample(streamSample); + streamSample.Close(); + //34462 + } + + [TestMethod] + public void TsNipIncludingLegacyChannel() + { + FileStream streamSample = GetStreamSample("hotbird_12380v_nip.ts"); + ProcessSample(streamSample); + streamSample.Close(); + //33518 + } + + [TestMethod] + public void TsNip() + { + FileStream streamSample = GetStreamSample("hotbird_12226v_nip.ts"); + ProcessSample(streamSample); + streamSample.Close(); + //33518 + } + + [TestMethod] + public void Rcs2Nip() + { + FileStream streamSample = GetStreamSample("telstar12v-bfbs-000000.ts"); + ProcessSample(streamSample); + streamSample.Close(); + //32559 + } + + + + private void ProcessSample(Stream sample) + { + TsContext ts = new TsContext(); + + InMemoryScraperStorageFactory inMemoryStorageFactory = new InMemoryScraperStorageFactory(); + DataStorage dataStorage = inMemoryStorageFactory.CreateDataStorage(); + + NullObjectStorage nullObjectStorage = new NullObjectStorage(); + + SkyscraperContext context = new SkyscraperContext(ts, dataStorage, nullObjectStorage); + context.InitalizeFilterChain(); + context.IngestFromStream(sample); + } +} diff --git a/skyscraper8.Tests/Feyllure.cs b/skyscraper8.Tests/Feyllure.cs index 70c77a5..a9433e3 100644 --- a/skyscraper8.Tests/Feyllure.cs +++ b/skyscraper8.Tests/Feyllure.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.IO; +using System.Reflection; using System.Runtime.InteropServices; using Allure.Net.Commons; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -94,6 +95,10 @@ public class Feyllure case UnitTestOutcome.Failed: Allure.UpdateTestCase(tc => tc.status = Status.failed); break; + case UnitTestOutcome.Inconclusive: + Allure.UpdateTestCase(tc => tc.status = Status.skipped); + Print("\n\n" + TestContext.TestException.ToString()); + break; default: StepResult stepResult = new StepResult(); stepResult.name = String.Format("Current Test Outcome: {0}", TestContext.CurrentTestOutcome);; @@ -123,4 +128,66 @@ public class Feyllure Console.WriteLine(formattedMessage); descriptionWriter.WriteLine(formattedMessage); } + + private DirectoryInfo testsuitePath; + protected DirectoryInfo GetTestsuitePath() + { + Print("Checking whether skyscraper-testsuite exists..."); + if (Directory.Exists("skyscraper-testsuite")) + { + testsuitePath = new DirectoryInfo("skyscraper8-testsuite"); + return testsuitePath; + } + + Print("Checking TESTSUITE_PATH..."); + string directory = Environment.GetEnvironmentVariable("TESTSUITE_PATH"); + if (!string.IsNullOrEmpty(directory)) + { + testsuitePath = new DirectoryInfo(directory); + return testsuitePath; + } + + FileInfo pointerFile = new FileInfo("skyscraper8-testsuite-path.txt"); + Print("Checking {0}...",pointerFile.FullName); + if (File.Exists(pointerFile.FullName)) + { + string readAllText = File.ReadAllText(pointerFile.FullName); + readAllText = readAllText.Trim(); + testsuitePath = new DirectoryInfo(readAllText); + return testsuitePath; + } + + Assert.Inconclusive("Could not find the test suite path."); + return null; + } + + protected FileStream GetStreamSample(string streamName) + { + DirectoryInfo testsuitePath = GetTestsuitePath(); + string combine = Path.Combine(testsuitePath.FullName, streamName); + FileInfo result = new FileInfo(combine); + if (!result.Exists) + { + Assert.Inconclusive(String.Format("Could not find {0}",result.FullName)); + return null; + } + + return result.OpenRead(); + } + + protected void AssertTargetInvocation(Action action) + where T: Exception + { + Assert.Throws(() => + { + try + { + action(); + } + catch (TargetInvocationException tie) + { + throw tie.InnerException; + } + }); + } } diff --git a/skyscraper8.Tests/RootTests/DocsisTests.cs b/skyscraper8.Tests/RootTests/DocsisTests.cs index 3d83f90..e711a2b 100644 --- a/skyscraper8.Tests/RootTests/DocsisTests.cs +++ b/skyscraper8.Tests/RootTests/DocsisTests.cs @@ -1,9 +1,12 @@ using System; +using System.Collections.Generic; using System.IO; using System.Net.NetworkInformation; using Microsoft.VisualStudio.TestTools.UnitTesting; using skyscraper5.Docsis; using skyscraper5.Docsis.AnnexC; +using skyscraper5.Docsis.MacManagement; +using skyscraper5.Docsis.MacManagement.BaselinePrivacyKeyManagementMessages; namespace skyscraper8.Tests.RootTests; @@ -597,4 +600,616 @@ public class DocsisTests : Feyllure UntestableMacManagementMessage ummm = new UntestableMacManagementMessage(srcAddr, dstAddr, dataBuffer); Assert.IsNull(ummm.MessageType); } + + [TestMethod] + public void UpstreamChannelDescriptorTests() + { + byte[] buffer = new byte[] + { + 1,1,1,1, //header + 1,1,1, //modulation rate + 2,4,0,0,0,1, //frequency + 3,1,1, //preamble pattern + 5,1,1, //Burst descriptor + 6,1,1, + 7,1,1, + 15,0, + 16,1,3, + 23,1,2, + 24,2,0,2, + 25,5,0,0,0,0,2, + 26,1,2, + 27,1,2, + 28,1,2, + 29,4,0,0,0,2, + 30,4,0,3,0,3, + 32,1,3, + 33,3,0,0,3 + }; + Random rng = new Random(); + byte[] srcBuffer = new byte[6]; + byte[] dstBuffer = new byte[6]; + PhysicalAddress srcAddr = new PhysicalAddress(srcBuffer); + PhysicalAddress dstAddr = new PhysicalAddress(dstBuffer); + UpstreamChannelDescriptor ucd = new UpstreamChannelDescriptor(srcAddr, dstAddr, buffer); + Assert.AreEqual((byte)1, ucd.ModulationRate); + Assert.AreEqual(1u, ucd.Frequency.Value); + Assert.AreEqual((byte)1, ucd.PreamblePattern[0]); + Assert.IsNotEmpty(ucd.BurstDescriptors); + Assert.AreEqual((byte)1, ucd.ExtendedPreamblePattern[0]); + Assert.IsTrue(ucd.S_CDMAMode.Value); + Assert.AreEqual(UpstreamChannelDescriptor.RangingRequiredEnum.ProbingRequired, ucd.RangingRequired); + Assert.IsNotNull(ucd.UcdChangeIndicator); + Assert.AreNotEqual(2,ucd.OfdmaTimestampSnapshot.Value); + Assert.AreEqual(2, ucd.OfdmaTimestampSnapshotDivideBy20.Value); + Assert.AreEqual((byte)2, ucd.OfdmaCyclicPrefixSize); + Assert.AreEqual((byte)2, ucd.OfdmaRolloffPeriodSize); + Assert.AreEqual((byte)2, ucd.SubcarrierSpacing); + Assert.AreEqual((uint)2, ucd.CenterFrequencyOfSubcarrier0); + Assert.AreEqual((ushort)3, ucd.SubcarrierExclusionBand[0].Item2); + Assert.AreEqual(3, ucd.SymbolsInOfdmaFrame.Value); + Assert.AreEqual(3u, ucd.RandomizationSeed); + + buffer = new byte[] + { + 0, 0, 0, 0, + 31,1,1 + }; + Assert.Throws(() => new UpstreamChannelDescriptor(srcAddr, dstAddr, buffer)); + + buffer = new byte[] + { + 3, 3, 42, 101, + 7, 1, 3 + }; + ucd = new UpstreamChannelDescriptor(srcAddr, dstAddr, buffer); + Assert.IsNull(ucd.S_CDMAMode); + Assert.AreEqual(101,ucd.DownstreamChannelId); + Assert.AreEqual(42, ucd.MinislotSize); + Assert.AreEqual(3, ucd.ConfigurationChangeCount); + Assert.AreEqual(3, ucd.UpstreamChannelID); + } + + [TestMethod] + public void BurstDescriptorTests() + { + byte[] buffer = new byte[] + { + 1, + 1,1,1, + 2,1,1, + 3,2,0,1, + 4,2,0,1, + 5,1,1, + 6,1,1, + 7,2,0,1, + 8,1,1, + 9,1,1, + 10,1,2, + 11,1,1, + 12,1,1, + 13,2,0,1, + 14,1,2, + 19,2,0,1, + 20,2,0,2, + 21,2,0x8f,255, + 22,2,10,4 + }; + UpstreamChannelDescriptor.BurstDescriptor bd = new UpstreamChannelDescriptor.BurstDescriptor(buffer); + Assert.AreEqual(1, bd.ModulationType.Value); + Assert.IsTrue(bd.DifferentialEncoding.Value); + Assert.AreEqual(1, bd.PreambleLength.Value); + Assert.AreEqual(1, bd.PreambleValueOffset.Value); + Assert.AreEqual(1, bd.FecErrorCorrection.Value); + Assert.AreEqual(1, bd.FecCodewordInformationBytes.Value); + Assert.AreEqual(1, bd.ScramblerSeed.Value); + Assert.AreEqual(1, bd.MaximumBurstSize.Value); + Assert.AreEqual(1, bd.GuardTimeSize.Value); + Assert.AreEqual(UpstreamChannelDescriptor.BurstDescriptor.CodewordLength.Shortened,bd.LastCodewordLength.Value); + Assert.IsTrue(bd.Scrambler.Value); + Assert.AreEqual(1, bd.RsInterleaverDepth.Value); + Assert.AreEqual(1, bd.RsInterleaverBlockSize.Value); + Assert.AreEqual(1, bd.SubcarriersInitialRanging.Value); + Assert.AreEqual(2, bd.SubcarriersFineRanging.Value); + Assert.IsNotEmpty(bd.OfdmaDataProfiles); + Assert.AreEqual(255, bd.OfdmaDataProfiles[0].NumberOfMinisolts); + Assert.AreEqual(0x0f, bd.OfdmaDataProfiles[0].PilotPatternIndex); + Assert.AreEqual(UpstreamChannelDescriptor.OfdmaDataProfile.ModulationOrderIndex._256QAM, bd.OfdmaDataProfiles[0].Modulation); + Assert.AreEqual(16.0,bd.OfdmaBroadcastIrStartingPowerLevel.Value); + Assert.AreEqual(1.0, bd.OfdmaBroadcastIrStartingPowerLevelIncrease.Value); + Assert.AreEqual(UpstreamChannelDescriptor.BurstDescriptor.PreambleTypeEnum.QPSK1,bd.PreambleType.Value); + Assert.AreEqual(1, bd.IntervalUsageCode); + //TO BE CONTINUED... + + buffer = new byte[] + { + 2, + 2, 1, 2, + 11,1, 2, + }; + bd = new UpstreamChannelDescriptor.BurstDescriptor(buffer); + Assert.IsFalse(bd.DifferentialEncoding.Value); + Assert.IsFalse(bd.Scrambler.Value); + + buffer = new byte[] + { + 3, + 2, 1, 3, + 11,1, 3, + }; + bd = new UpstreamChannelDescriptor.BurstDescriptor(buffer); + Assert.IsNull(bd.DifferentialEncoding); + Assert.IsNull(bd.Scrambler); + + buffer = new byte[] + { + 4, + 42, 1, 0 + }; + Assert.Throws(() => new UpstreamChannelDescriptor.BurstDescriptor(buffer)); + } + + [TestMethod] + public void UcdChangeIndicatorBitmaskTest() + { + UpstreamChannelDescriptor.UcdChangeIndicatorBitmask ucdcib = + new UpstreamChannelDescriptor.UcdChangeIndicatorBitmask(0xffff); + Assert.IsTrue(ucdcib.ChangeIuc14); + Assert.IsTrue(ucdcib.ChangeIuc13); + Assert.IsTrue(ucdcib.ChangeIuc12); + Assert.IsTrue(ucdcib.ChangeIuc11); + Assert.IsTrue(ucdcib.ChangeIuc10); + Assert.IsTrue(ucdcib.ChangeIuc9); + Assert.IsTrue(ucdcib.ChangeIuc6); + Assert.IsTrue(ucdcib.ChangeIuc5); + Assert.IsTrue(ucdcib.ChangeOtherParameters); + Assert.IsTrue(ucdcib.ChangeUnusedSubcarrierSpecification); + Assert.IsTrue(ucdcib.ChangeSubcarrierExclusionBand); + Assert.AreEqual(0xffff,ucdcib.GetRawValue()); + } + + [TestMethod] + public void MultipartRegistrationResponse() + { + Random rng = new Random(); + byte[] srcBuffer = new byte[6]; + byte[] dstBuffer = new byte[6]; + PhysicalAddress srcAddr = new PhysicalAddress(srcBuffer); + PhysicalAddress dstAddr = new PhysicalAddress(dstBuffer); + + byte[] payload = new byte[] + { + 0,1, //SID + 1, //Response + 1, //Number of Fragments + 1, //Fragment Sequence Number + 0, //TLV encoded information + }; + + T45_V4_MultipartRegistrationResponse mrr = new T45_V4_MultipartRegistrationResponse(srcAddr, dstAddr, payload); + Assert.AreEqual(1, mrr.SID); + Assert.AreEqual(1, mrr.Response); + Assert.AreEqual(1, mrr.NumberOfFragments); + Assert.AreEqual(1, mrr.FragmentSequenceNumber); + Assert.IsNotNull(mrr.TlvEncodedInformation); + } + + [TestMethod] + public void RangingResponseTest() + { + Random rng = new Random(); + byte[] srcBuffer = new byte[6]; + byte[] dstBuffer = new byte[6]; + PhysicalAddress srcAddr = new PhysicalAddress(srcBuffer); + PhysicalAddress dstAddr = new PhysicalAddress(dstBuffer); + + byte[] payload = new byte[] + { + 0,1, //SID + 1, //Upstream Channel ID + 1,4,0,0,0,1, + 2,1,1, + 3,2,0,1, + 4,1,1, + 5,1,3, + 6,4,0,0,0,1, + 7,1,1, + 9,1,1, + 11,1,1, + 12,3,7,7,3, + 13,1,1, + 14,1,1, + 15,0, 7, 1,1,1,0,1,0,1, + 16,0, 7, 1,1,1,0,1,0,1, + 17,6, 1,1,1, 2,1,1, + 18,3, 2,1,1, + 8,1,1, + 10,1,1 + }; + RangingResponse rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.AreEqual(1, rr.SID.Value); + Assert.AreEqual(1, rr.UpstreamChannelId.Value); + Assert.AreEqual(1u, rr.TimingAdjust.Value); + Assert.AreEqual(1, rr.PowerLevelAdjust.Value); + Assert.AreEqual(1, rr.OffsetFrequencyAdjust.Value); + Assert.AreEqual(1, rr.TxEqualizationData[0]); + Assert.AreEqual(RangingResponse.RangingStatusEnum.Success, rr.RangingStatus); + Assert.AreEqual(1u, rr.DownstreamFrequencyOverride.Value); + Assert.AreEqual(1, rr.UpstreamChannelIdOverride.Value); + Assert.AreEqual(1, rr.T4TimeoutMultiplier.Value); + Assert.AreEqual(1.0, rr.TransmitEqualizationAdjustForOfdmaChannels.Coefficients[0].Imaginary); + Assert.AreEqual(1.0,rr.TransmitEqualizationSetForOfdmaChannels.Coefficients[0].Imaginary); + Assert.AreEqual(1, rr.TransmitEqualizationSet[0]); + Assert.AreEqual(0.25, rr.DynamicRangeWindowUpperEdge.Value); + Assert.IsTrue(rr.CommandPower.Valid); + Assert.AreEqual(1, rr.CommandPower.DynamicRangeWindow.Value); + Assert.AreEqual(1, rr.CommandPower.TransmitPowerLevels[0]); + Assert.AreEqual(1, rr.SCdmaPowerHeadroom.Value); + Assert.IsNotNull(rr.FdxCommandedPower); + Assert.AreEqual(1, rr.TimingAdjustFractionalPart.Value); + Assert.AreEqual(1, rr.SCdmaMaximumScheduledCodes.Value); + + payload = new byte[] + { + 0, 1, + 1, + 3, 1, 0 + }; + rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.IsFalse(rr.Valid); + + payload = new byte[] + { + 0, 1, + 1, + 1, 1, 0 + }; + rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.IsFalse(rr.Valid); + + payload = new byte[] + { + 0, 1, + 1, + 12, 3, 7, 1, 1 + }; + rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.IsFalse(rr.UpstreamChannelAdjustments.Valid); + + payload = new byte[] + { + 0, 1, + 1, + 12, 3, 5, 1, 1 + }; + Assert.Throws(() => new RangingResponse(srcAddr, dstAddr, payload)); + + payload = new byte[] + { + 0, 1, + 1, + 12, 1,0 + }; + rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.IsTrue(rr.UpstreamChannelAdjustments.Valid); + + payload = new byte[] + { + 0, 1, + 1, + 3, 4, 0, 0 + }; + rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.IsFalse(rr.Valid); + + payload = new byte[] + { + 0, 1, + 1, + 0, 1, 1, + 3, 0, + 4, 1, 1 + }; + rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.IsFalse(rr.Valid); + + payload = new byte[] + { + 0, 1, + 1, + 6, 3, 0, 0, 0 + }; + rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.IsFalse(rr.Valid); + + payload = new byte[] + { + 0, 1, + 1, + 17, 1, 1 + }; + rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.IsFalse(rr.Valid); + + payload = new byte[] + { + 0, 1, + 1, + 18, 1, 1 + }; + rr = new RangingResponse(srcAddr, dstAddr, payload); + Assert.IsFalse(rr.Valid); + + payload = new byte[] + { + 0, 1, + 1, + 42, 1, 1 + }; + Assert.Throws(() => new RangingResponse(srcAddr, dstAddr, payload)); + + } + + [TestMethod] + public void CommandPowerObjectTest() + { + byte[] payload = new byte[] + { + 0 + }; + + RangingResponse.CommandPowerObject commandPower = new RangingResponse.CommandPowerObject(payload); + Assert.IsFalse(commandPower.Valid); + + payload = new byte[] + { + 1, 4, 0, 0, 0 + }; + commandPower = new RangingResponse.CommandPowerObject(payload); + Assert.IsFalse(commandPower.Valid); + + payload = new byte[] + { + 3, 1, 1 + }; + commandPower = new RangingResponse.CommandPowerObject(payload); + Assert.IsFalse(commandPower.Valid); + } + + [TestMethod] + public void PrivacyKeyManagementResponseTest() + { + NullDocsisEventHandler nullDocsisEventHandler = new NullDocsisEventHandler(); + DocsisEnvironment docsisEnvironment = new DocsisEnvironment(nullDocsisEventHandler); + Random rng = new Random(); + byte[] srcBuffer = new byte[6]; + byte[] dstBuffer = new byte[6]; + PhysicalAddress srcAddr = new PhysicalAddress(srcBuffer); + PhysicalAddress dstAddr = new PhysicalAddress(dstBuffer); + + byte[] payload = new byte[] + { + 5, //Code + 1, //Identifier + 0, 4 + 7 + 4 + 3 + 5 + 5 + 5, //Length (von der darauf folgenden Message) + + //Hier beginnt die Message (length sind immer zwei bytes) + 7, 0, 1, 1, + 9, 0, 4, 0, 0, 0, 1, + 10, 0, 1, 1, + + 23, 0, 5 + 5 + 5, //length für den SA descriptor + + //Hier fängt der SA descriptor an + 12, 0, 2, 0, 1, + 20, 0, 2, 2, 0, + 24, 0, 1, 0, 2, + }; + docsisEnvironment.PushMacManagementMessage(null, 1, 13, srcAddr, dstAddr, payload); + + //Falsche Länge der Message + payload = new byte[] + { + 5, //Code + 1, //Identifier + 0, 2, //Length (von der darauf folgenden Message) + + //Hier beginnt die Message + 0, + }; + docsisEnvironment.PushMacManagementMessage(null, 1, 13, srcAddr, dstAddr, payload); + + //Unimplementierter message type + payload = new byte[] + { + 42, //Code + 1, //Identifier + 0, 1, //Length (von der darauf folgenden Message) + + //Hier beginnt die Message + 0, + }; + docsisEnvironment.PushMacManagementMessage(null, 1, 13, srcAddr, dstAddr, payload); + + //Auth Reply NotImplemented + payload = new byte[] + { + 5, + 1, + 0, 4, + + 255, 0, 1, 1 + }; + AssertTargetInvocation(() => docsisEnvironment.PushMacManagementMessage(null, 1, 13, srcAddr, dstAddr, payload)); + + //Privacy Key Management Response Unimplemented Message Type + payload = new byte[] + { + 10, + 1, + 0, 3, + + 255, 255, 255 + }; + AssertTargetInvocation(() => docsisEnvironment.PushMacManagementMessage(null, 1, 13, srcAddr, dstAddr, payload)); + + //Sa Descriptor Unimplemented TLV + payload = new byte[] + { + 5, + 1, + 0, 7, //Länge für darauffolgendes + + 23, + 0, 4, //Länge für darauffolgendes + 8, 0, 1, 1 + }; + AssertTargetInvocation(() => docsisEnvironment.PushMacManagementMessage(null, 1, 13, srcAddr, dstAddr, payload)); + + payload = new byte[] + { + 8, //Code + 1, //Identifier + 0, 4 + 7 + 5 + 1 + 2 + 4 + 7 + 4 + 4, //Length für alles darauf folgende + + 10, 0, 1, 1, + 11, 0, 4, 0, 0, 0, 1, + 12, 0, 2, 0, 1, + 13, //TEK parameters + 0, 4 + 7 + 4 + 4, //Length für alles darauf folgende + 8, 0, 1, 1, + 9, 0, 4, 0, 0, 0, 1, + 10, 0, 1, 1, + 15, 0, 1, 1, + }; + docsisEnvironment.PushMacManagementMessage(null, 1, 13, srcAddr, dstAddr, payload); + + Queue queue = nullDocsisEventHandler.GetQueue(); + while (queue.Count > 0) + { + PrivacyKeyManagementResponse dequeue = queue.Dequeue() as PrivacyKeyManagementResponse; + Assert.AreEqual(1,dequeue.Identifier); + switch (dequeue.BpkmMessage) + { + case AuthReply ar: + Assert.AreNotEqual(255,ar.KeySequenceNumber); + Assert.AreNotEqual(255u,ar.KeyLifetime); + if (ar.SaDescriptor != null) + { + Assert.AreNotEqual(255, ar.SaDescriptor.SAID); + Assert.AreNotEqual(AuthReply.SaDescriptorObject.SaTypeEnum.Dynamic, ar.SaDescriptor.SaType); + Assert.AreNotEqual(AuthReply.SaDescriptorObject.DataEncryptionAlgorithmIdentifiers.Cbc128Aes, ar.SaDescriptor.DataEncryptionAlgorithm); + Assert.AreEqual(AuthReply.SaDescriptorObject.DataAuthenticationIdentifiers.NoDataAuthentication, ar.SaDescriptor.DataAuthenticationAlgorithm); + } + + if (ar.AuthKey != null) + { + Assert.IsNotNull(ar.AuthKey); + } + break; + case KeyReply kr: + Assert.AreNotEqual(255, kr.KeySequenceNumber.Value); + Assert.IsNotNull(kr.HmacDigest); + Assert.AreNotEqual(255, kr.SAID.Value); + if (kr.TekParameters.Count > 0) + { + KeyReply.TekParameter krTekParameter = kr.TekParameters[0]; + Assert.IsNotNull(krTekParameter.KeyLifetime); + Assert.IsNotNull(krTekParameter.CbcIv); + Assert.IsNotNull(krTekParameter.TekKeySequenceNumber); + Assert.IsNotNull(krTekParameter.TEK); + } + break; + case null: + break; + default: + throw new NotImplementedException(dequeue.BpkmMessage.ToString()); + } + } + } + + [TestMethod] + public void KeyReplyTest() + { + byte[] payload = new byte[] + { + 254, 0, 1, 0 + }; + Assert.Throws(() => new KeyReply(payload)); + } + + [TestMethod] + public void TekParameterTest() + { + byte[] payload = new byte[] + { + 254, 0, 1, 0 + }; + Assert.Throws(() => new KeyReply.TekParameter(payload)); + + payload = new byte[] + { + 10, 0, 1, 1, + 8, 0, 1, 2 + }; + KeyReply.TekParameter tekParameter = new KeyReply.TekParameter(payload); + Print(tekParameter.ToString()); + } + + [TestMethod] + public void DynamicServiceAdditionResponseTest() + { + NullDocsisEventHandler nullDocsisEventHandler = new NullDocsisEventHandler(); + DocsisEnvironment docsisEnvironment = new DocsisEnvironment(nullDocsisEventHandler); + Random rng = new Random(); + byte[] srcBuffer = new byte[6]; + byte[] dstBuffer = new byte[6]; + PhysicalAddress srcAddr = new PhysicalAddress(srcBuffer); + PhysicalAddress dstAddr = new PhysicalAddress(dstBuffer); + + byte[] payload = new byte[] + { + 0, 1, //Transaction ID + 1, //Confirmation Code + }; + + docsisEnvironment.PushMacManagementMessage(null, 2, 16, srcAddr, dstAddr, payload); + } + + [TestMethod] + public void NullDocsisEventHandlerTest() + { + NullDocsisEventHandler nullDocsisEventHandler = new NullDocsisEventHandler(); + Random rng = new Random(); + byte[] srcBuffer = new byte[6]; + rng.NextBytes(srcBuffer); + PhysicalAddress srcAddr = new PhysicalAddress(srcBuffer); + + nullDocsisEventHandler.OnParticipantDetected(srcAddr); + HashSet physicalAddresses = nullDocsisEventHandler.GetParticipants(); + Assert.Contains(srcAddr, physicalAddresses); + + rng.NextBytes(srcBuffer); + srcAddr = new PhysicalAddress(srcBuffer); + nullDocsisEventHandler.OnCmtsTimestamp(srcAddr, 1); + Assert.Contains(srcAddr, physicalAddresses); + Assert.AreEqual(1u, nullDocsisEventHandler.GetTiming()); + + byte[] ucdPayload = new byte[] + { + 1, + 0, + 0, + 1 + }; + byte[] dstBuffer = new byte[6]; + rng.NextBytes(dstBuffer); + PhysicalAddress dstAddr = new PhysicalAddress(dstBuffer); + UpstreamChannelDescriptor ucd = new UpstreamChannelDescriptor(srcAddr, dstAddr, ucdPayload); + nullDocsisEventHandler.OnUpstreamChannel(ucd); + object dequeue = nullDocsisEventHandler.GetQueue().Dequeue(); + Assert.AreEqual(ucd, dequeue); + + + } } diff --git a/skyscraper8.sln.DotSettings.user b/skyscraper8.sln.DotSettings.user index 5796cc7..8c7cd78 100644 --- a/skyscraper8.sln.DotSettings.user +++ b/skyscraper8.sln.DotSettings.user @@ -4,19 +4,32 @@ ForceIncluded ForceIncluded ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded ForceIncluded + ForceIncluded + ForceIncluded ForceIncluded + ForceIncluded ForceIncluded ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded ForceIncluded ForceIncluded ForceIncluded @@ -26,12 +39,22 @@ <Assembly Path="/home/schiemas/.nuget/packages/allure.net.commons/2.14.1/lib/netstandard2.0/Allure.Net.Commons.dll" /> </AssemblyExplorer> /home/schiemas/.cache/JetBrains/Rider2025.1/resharper-host/temp/Rider/vAny/CoverageData/_skyscraper8.1808907683/Snapshot/snapshot.utdcvr - <SessionState ContinuousTestingMode="0" Name="All tests from &lt;skyscraper8.Tests&gt; #2" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> - <Project Location="\home\schiemas\RiderProjects\skyscraper8\skyscraper8.Tests" Presentation="&lt;skyscraper8.Tests&gt;" /> + <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &lt;skyscraper8.Tests&gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <And> + <Namespace>skyscraper8.Tests</Namespace> + <Project Location="/home/schiemas/RiderProjects/skyscraper8/skyscraper8.Tests" Presentation="&lt;skyscraper8.Tests&gt;" /> + </And> </SessionState> - <SessionState ContinuousTestingMode="0" IsActive="True" Name="All tests from &lt;skyscraper8.Tests&gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> - <Project Location="\home\schiemas\RiderProjects\skyscraper8\skyscraper8.Tests" Presentation="&lt;skyscraper8.Tests&gt;" /> + <SessionState ContinuousTestingMode="0" IsActive="True" Name="Continuous Testing" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Project Location="/home/schiemas/RiderProjects/skyscraper8/skyscraper8.Tests" Presentation="&lt;skyscraper8.Tests&gt;" /> </SessionState> + <SessionState ContinuousTestingMode="0" Name="All tests from &lt;skyscraper8.Tests&gt;" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <Project Location="/home/schiemas/RiderProjects/skyscraper8/skyscraper8.Tests" Presentation="&lt;skyscraper8.Tests&gt;" /> +</SessionState> + + + + <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> diff --git a/skyscraper8/Docsis/DocsisEnvironment.cs b/skyscraper8/Docsis/DocsisEnvironment.cs index e6cd6c7..fbb414b 100644 --- a/skyscraper8/Docsis/DocsisEnvironment.cs +++ b/skyscraper8/Docsis/DocsisEnvironment.cs @@ -339,18 +339,7 @@ namespace skyscraper5.Docsis break; case nameof(PrivacyKeyManagementResponse): PrivacyKeyManagementResponse privacyKeyManagementResponse = (PrivacyKeyManagementResponse)mmm; - switch (privacyKeyManagementResponse.Code) - { - case 5: - //Contains a scrambled authentication key, so not interesting for us - break; - case 8: - //Since the key is encrypted as well, this isn't interesting. - break; - default: - //CM-SP-SECv4.0-I01-190815.pdf page 50 - throw new NotImplementedException(String.Format("{0}.{1} {2}", nameof(PrivacyKeyManagementResponse), nameof(privacyKeyManagementResponse.Code), privacyKeyManagementResponse.Code)); - } + eventHandler.OnKeyManagementResponse(privacyKeyManagementResponse); break; case nameof(DynamicServiceChangeResponse): //Nothing of interesent in here either. @@ -362,7 +351,8 @@ namespace skyscraper5.Docsis //not interesting break; case nameof(DynamicServiceAdditionResponse): - //not interesting + DynamicServiceAdditionResponse dynamicServiceAdditionResponse = (DynamicServiceAdditionResponse)mmm; + eventHandler.OnDynamicServiceAddition(dynamicServiceAdditionResponse.TransactionId, dynamicServiceAdditionResponse.ConfirmationCode, dynamicServiceAdditionResponse.TlvEncodedInformation); break; case nameof(DynamicServiceDeletionResponse): //nothing in there diff --git a/skyscraper8/Docsis/IDocsisEventHandler.cs b/skyscraper8/Docsis/IDocsisEventHandler.cs index b586c39..b0060f9 100644 --- a/skyscraper8/Docsis/IDocsisEventHandler.cs +++ b/skyscraper8/Docsis/IDocsisEventHandler.cs @@ -5,6 +5,7 @@ using System.Net; using System.Net.NetworkInformation; using System.Text; using System.Threading.Tasks; +using skyscraper5.Docsis.AnnexC; using skyscraper5.Docsis.MacManagement; namespace skyscraper5.Docsis @@ -16,5 +17,7 @@ namespace skyscraper5.Docsis void OnUpstreamChannel(UpstreamChannelDescriptor mmm); void OnDownstreamChannel(PhysicalAddress physicalAddress, MacDomainDescriptor.DownstreamActiveChannel downstreamActiveChannel); void OnLearnedIpFromMac(PhysicalAddress arpHeaderSenderHardwareAddress, IPAddress arpHeaderSenderProtocolAddress); + void OnKeyManagementResponse(PrivacyKeyManagementResponse privacyKeyManagementResponse); + void OnDynamicServiceAddition(ushort transactionId, byte confirmationCode, CommonTlvEncodingObject tlvEncodedInformation); } } diff --git a/skyscraper8/Docsis/MacManagement/BaselinePrivacyKeyManagementMessages/5_AuthReply.cs b/skyscraper8/Docsis/MacManagement/BaselinePrivacyKeyManagementMessages/5_AuthReply.cs index 355fd3c..f292a24 100644 --- a/skyscraper8/Docsis/MacManagement/BaselinePrivacyKeyManagementMessages/5_AuthReply.cs +++ b/skyscraper8/Docsis/MacManagement/BaselinePrivacyKeyManagementMessages/5_AuthReply.cs @@ -4,7 +4,7 @@ using System.IO; namespace skyscraper5.Docsis.MacManagement.BaselinePrivacyKeyManagementMessages { - internal class AuthReply : PrivacyKeyManagementResponse.BpkmMessageObject + public class AuthReply : PrivacyKeyManagementResponse.BpkmMessageObject { public AuthReply(byte[] buffer) : base(buffer) { @@ -39,7 +39,7 @@ namespace skyscraper5.Docsis.MacManagement.BaselinePrivacyKeyManagementMessages public byte[] AuthKey { get; private set; } public SaDescriptorObject SaDescriptor { get; private set; } - internal class SaDescriptorObject + public class SaDescriptorObject { public SaDescriptorObject(byte[] buffer) { @@ -70,10 +70,10 @@ namespace skyscraper5.Docsis.MacManagement.BaselinePrivacyKeyManagementMessages } } - public ushort SAID { get; } - public SaTypeEnum SaType { get; } - public DataEncryptionAlgorithmIdentifiers DataEncryptionAlgorithm { get; } - public DataAuthenticationIdentifiers DataAuthenticationAlgorithm { get; } + public ushort SAID { get; private set; } + public SaTypeEnum SaType { get; private set; } + public DataEncryptionAlgorithmIdentifiers DataEncryptionAlgorithm { get; private set; } + public DataAuthenticationIdentifiers DataAuthenticationAlgorithm { get; private set; } public enum SaTypeEnum { diff --git a/skyscraper8/Docsis/MacManagement/BaselinePrivacyKeyManagementMessages/8_KeyReply.cs b/skyscraper8/Docsis/MacManagement/BaselinePrivacyKeyManagementMessages/8_KeyReply.cs index e0beb24..94e5523 100644 --- a/skyscraper8/Docsis/MacManagement/BaselinePrivacyKeyManagementMessages/8_KeyReply.cs +++ b/skyscraper8/Docsis/MacManagement/BaselinePrivacyKeyManagementMessages/8_KeyReply.cs @@ -8,7 +8,7 @@ using skyscraper5.Skyscraper.IO; namespace skyscraper5.Docsis.MacManagement.BaselinePrivacyKeyManagementMessages { - internal class KeyReply : PrivacyKeyManagementResponse.BpkmMessageObject + public class KeyReply : PrivacyKeyManagementResponse.BpkmMessageObject { public KeyReply(byte[] buffer) : base(buffer) { diff --git a/skyscraper8/Docsis/MacManagement/T13_V1_PrivacyKeyManagementResponse.cs b/skyscraper8/Docsis/MacManagement/T13_V1_PrivacyKeyManagementResponse.cs index b5bdc0d..4e662e3 100644 --- a/skyscraper8/Docsis/MacManagement/T13_V1_PrivacyKeyManagementResponse.cs +++ b/skyscraper8/Docsis/MacManagement/T13_V1_PrivacyKeyManagementResponse.cs @@ -13,7 +13,7 @@ namespace skyscraper5.Docsis.MacManagement { [SkyscraperPlugin] [MacManagementMessageType(1,13)] - internal class PrivacyKeyManagementResponse : MacManagementMessage + public class PrivacyKeyManagementResponse : MacManagementMessage { public PrivacyKeyManagementResponse(PhysicalAddress source, PhysicalAddress destination, byte[] buffer) : base(source, destination, buffer) { @@ -22,7 +22,11 @@ namespace skyscraper5.Docsis.MacManagement Identifier = ms.ReadUInt8(); ushort length = ms.ReadUInt16BE(); if (length > ms.GetAvailableBytes()) + { + Valid = false; return; + } + byte[] subbuffer = ms.ReadBytes(length); switch (Code) @@ -52,7 +56,7 @@ namespace skyscraper5.Docsis.MacManagement protected BpkmMessageObject(byte[] buffer) { MemoryStream ms = new MemoryStream(buffer, false); - while (ms.GetAvailableBytes() > 3) + while (ms.GetAvailableBytes() >= 3) { byte type = ms.ReadUInt8(); ushort length = ms.ReadUInt16BE(); diff --git a/skyscraper8/Docsis/MacManagement/T5_V1_RangingResponse.cs b/skyscraper8/Docsis/MacManagement/T5_V1_RangingResponse.cs index 388b7b8..1f255fc 100644 --- a/skyscraper8/Docsis/MacManagement/T5_V1_RangingResponse.cs +++ b/skyscraper8/Docsis/MacManagement/T5_V1_RangingResponse.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Net.NetworkInformation; @@ -36,7 +37,7 @@ namespace skyscraper5.Docsis.MacManagement Valid = false; return; } - if (length == 0) + if (length == 0 && type != 15 && type != 16) { Valid = false; return; @@ -99,8 +100,7 @@ namespace skyscraper5.Docsis.MacManagement SCdmaPowerHeadroom = v[0]; break; case 12: - byte[] upstreamChannelAdjustmentsBuffer = ms.ReadBytes(length); - UpstreamChannelAdjustments = new UpstreamChannelAdjustmentsObject(upstreamChannelAdjustmentsBuffer); + UpstreamChannelAdjustments = new UpstreamChannelAdjustmentsObject(v); break; case 13: T4TimeoutMultiplier = v[0]; @@ -118,13 +118,13 @@ namespace skyscraper5.Docsis.MacManagement newLen = (ushort)ms.GetAvailableBytes(); } v = ms.ReadBytes(newLen); - TransmitEqualizationEncodingsForOfdmaChannels result1516 = Parse1516(v); if (type == 15) TransmitEqualizationAdjustForOfdmaChannels = Parse1516(v); - else if (type == 16) - TransmitEqualizationSetForOfdmaChannels = Parse1516(v); else - throw new NotImplementedException(String.Format("2-byte TLV entry in Ranging Response with ID {0}", type)); + { + Debug.Assert(type == 16); + TransmitEqualizationSetForOfdmaChannels = Parse1516(v); + } break; case 17: CommandPower = new CommandPowerObject(v); @@ -145,11 +145,6 @@ namespace skyscraper5.Docsis.MacManagement } break; default: - if (type > 18) - { - Valid = false; - return; - } //see CM-SP-MULPIv4.0-I01-190815.pdf page 141 throw new NotImplementedException(String.Format("{0} Type {1}", nameof(RangingResponse), type)); } @@ -184,8 +179,8 @@ namespace skyscraper5.Docsis.MacManagement } public TransmitEqualizationEncodingsForOfdmaChannels TransmitEqualizationAdjustForOfdmaChannels { get; private set; } - private CommandPowerObject CommandPower { get; set; } - class CommandPowerObject : Validatable + public CommandPowerObject CommandPower { get; set; } + public class CommandPowerObject : Validatable { public CommandPowerObject(byte[] buffer) { @@ -255,7 +250,7 @@ namespace skyscraper5.Docsis.MacManagement public byte? UpstreamChannelIdOverride { get; private set; } public byte? SCdmaPowerHeadroom { get; } public UpstreamChannelAdjustmentsObject UpstreamChannelAdjustments { get; private set; } - private CommandPowerObject FdxCommandedPower { get; } + public CommandPowerObject FdxCommandedPower { get; } public byte? TimingAdjustFractionalPart { get; } public byte? SCdmaMaximumScheduledCodes { get; } diff --git a/skyscraper8/Docsis/NullDocsisEventHandler.cs b/skyscraper8/Docsis/NullDocsisEventHandler.cs index ca39776..c87e5a5 100644 --- a/skyscraper8/Docsis/NullDocsisEventHandler.cs +++ b/skyscraper8/Docsis/NullDocsisEventHandler.cs @@ -1,33 +1,85 @@ using System.Net; using System.Net.NetworkInformation; +using skyscraper5.Docsis.AnnexC; using skyscraper5.Docsis.MacManagement; namespace skyscraper5.Docsis; public class NullDocsisEventHandler : IDocsisEventHandler { + private HashSet participants; + private uint? timing; + private Dictionary knownIps; + public void OnParticipantDetected(PhysicalAddress pa) { - throw new NotImplementedException(); + if (participants == null) + participants = new HashSet(); + + participants.Add(pa); } public void OnCmtsTimestamp(PhysicalAddress source, uint timing) { - throw new NotImplementedException(); + OnParticipantDetected(source); + this.timing = timing; } public void OnUpstreamChannel(UpstreamChannelDescriptor mmm) { - throw new NotImplementedException(); + if (_queue == null) + _queue = new Queue(); + + _queue.Enqueue(mmm); } public void OnDownstreamChannel(PhysicalAddress physicalAddress, MacDomainDescriptor.DownstreamActiveChannel downstreamActiveChannel) { - throw new NotImplementedException(); + if (_queue == null) + _queue = new Queue(); + + _queue.Enqueue(downstreamActiveChannel); } public void OnLearnedIpFromMac(PhysicalAddress arpHeaderSenderHardwareAddress, IPAddress arpHeaderSenderProtocolAddress) { - throw new NotImplementedException(); + if (knownIps == null) + knownIps = new Dictionary(); + + knownIps.Add(arpHeaderSenderHardwareAddress, arpHeaderSenderProtocolAddress); + } + + public void OnKeyManagementResponse(PrivacyKeyManagementResponse privacyKeyManagementResponse) + { + if (_queue == null) + _queue = new Queue(); + + _queue.Enqueue(privacyKeyManagementResponse); + } + + public void OnDynamicServiceAddition(ushort transactionId, byte confirmationCode, + CommonTlvEncodingObject tlvEncodedInformation) + { + if (_queue == null) + _queue = new Queue(); + + _queue.Enqueue(tlvEncodedInformation); + } + + private Queue _queue; + + public Queue GetQueue() + { + return _queue; + } + + public HashSet GetParticipants() + { + return participants; + } + + public uint GetTiming() + { + return timing.Value; } } diff --git a/skyscraper8/Experimentals/NdsSsu/NdsSsuDetector.cs b/skyscraper8/Experimentals/NdsSsu/NdsSsuDetector.cs index c4e023e..5d2d95d 100644 --- a/skyscraper8/Experimentals/NdsSsu/NdsSsuDetector.cs +++ b/skyscraper8/Experimentals/NdsSsu/NdsSsuDetector.cs @@ -106,7 +106,7 @@ namespace skyscraper8.Experimentals.NdsSsu public void OnNdsSsuError(int pid, NdsSsuError error) { - throw new NotImplementedException(); + Score--; } private int maxNumFiles; diff --git a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs index 671d4e2..27df39f 100644 --- a/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs +++ b/skyscraper8/Skyscraper/Scraper/SkyscraperContext.cs @@ -97,6 +97,7 @@ using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; using RntParser = skyscraper5.Dvb.TvAnytime.RntParser; using skyscraper8.DvbSis; using skyscraper8.T2MI.Packets; +using skyscraper5.Docsis.AnnexC; namespace skyscraper5.Skyscraper.Scraper { @@ -3313,6 +3314,16 @@ namespace skyscraper5.Skyscraper.Scraper void T2MIEventHandler.OnFramingAndTimingInformation(int relatedPid, _0xF0_FramingTimingInformation fti) { logger.WarnFormat("Found T2MI F&TI Information on PID 0x{0:X4}. This isn't supported yet. It would be great if you could share a sample of this stream, so this can be implemented.", relatedPid); - } + } + + public void OnKeyManagementResponse(PrivacyKeyManagementResponse privacyKeyManagementResponse) + { + logger.WarnFormat("Found a DOCSIS Key Management Response. Those aren't supported yet. It would be great if you could share a sample of this stream, so those can be implemented."); + } + + public void OnDynamicServiceAddition(ushort transactionId, byte confirmationCode, CommonTlvEncodingObject tlvEncodedInformation) + { + logger.WarnFormat("Found a DOCSIS Dynamic Service Addition. Those aren't supported yet. It would be great if you could share a sample of this stream, so those can be implemented."); + } } }