/// <summary> /// O( ) /// </summary> public static void TestAConstructor_And_Reserialization() { byte FractionsLost = (byte)Utility.Random.Next(byte.MinValue, byte.MaxValue); int RandomId = RFC3550.Random32(Utility.Random.Next()), CumulativePacketsLost = RFC3550.Random32(Utility.Random.Next(0, Binary.U24MaxValue)), ExtendedHighestSequenceNumberReceived = RFC3550.Random32(Utility.Random.Next()), InterarrivalJitterEstimate = RFC3550.Random32(Utility.Random.Next()), LastSendersReportTimestamp = RFC3550.Random32(Utility.Random.Next()), DelaySinceLastSendersReport = RFC3550.Random32(Utility.Random.Next()); //Create the ReportBlock using the random values using (Rtcp.ReportBlock rb = new Rtcp.ReportBlock(RandomId, FractionsLost, CumulativePacketsLost, ExtendedHighestSequenceNumberReceived, InterarrivalJitterEstimate, LastSendersReportTimestamp, DelaySinceLastSendersReport)) { //Check IsComplete System.Diagnostics.Debug.Assert(rb.IsComplete, "IsComplete must be true."); //Check Size System.Diagnostics.Debug.Assert(rb.Size == Rtcp.ReportBlock.ReportBlockSize, "Unexpected Size"); //Check SendersSynchronizationSourceIdentifier System.Diagnostics.Debug.Assert(rb.SendersSynchronizationSourceIdentifier == RandomId, "Unexpected SendersSynchronizationSourceIdentifier"); //Check FractionsLost 8 bit System.Diagnostics.Debug.Assert(rb.FractionsLost == FractionsLost, "Unexpected FractionsLost"); //Check CumulativePacketsLost 24 bit, //System.Diagnostics.Debug.Assert(rb.CumulativePacketsLost == CumulativePacketsLost, "Unexpected CumulativePacketsLost"); //Check ExtendedHighestSequenceNumberReceived System.Diagnostics.Debug.Assert(rb.ExtendedHighestSequenceNumberReceived == ExtendedHighestSequenceNumberReceived, "Unexpected ExtendedHighestSequenceNumberReceived"); //Check InterarrivalJitterEstimate System.Diagnostics.Debug.Assert(rb.InterarrivalJitterEstimate == InterarrivalJitterEstimate, "Unexpected InterarrivalJitterEstimate"); //Check LastSendersReportTimestamp System.Diagnostics.Debug.Assert(rb.LastSendersReportTimestamp == LastSendersReportTimestamp, "Unexpected LastSendersReportTimestamp"); //Check DelaySinceLastSendersReport System.Diagnostics.Debug.Assert(rb.DelaySinceLastSendersReport == DelaySinceLastSendersReport, "Unexpected DelaySinceLastSendersReport"); //Serialize, Deserialize and verify again using (Rtcp.ReportBlock s = new Rtcp.ReportBlock(new Common.MemorySegment(rb.Prepare().ToArray()))) { //Check IsComplete System.Diagnostics.Debug.Assert(s.IsComplete, "IsComplete must be true."); //Check IsComplete System.Diagnostics.Debug.Assert(rb.SequenceEqual(s), "Unexpected results from Prepare"); } } }
//Test AddReports And Enumerator And Reserialization public static void Test_RFC3550_Page40_Figure2() { //Create a random id int RandomId = RFC3550.Random32(Utility.Random.Next()); //Create a SendersReport instance using the specified options. using (Media.Rtcp.SendersReport p = new Rtcp.SendersReport(2, 0, 0, RandomId)) { //Let LSR = DateTime ExpectedDateTime = new DateTime(1995, 11, 10, 11, 33, 25, 125, DateTimeKind.Utc); //n = LSR // //sec = 0xb44d_b705 p.NtpMSW = -1269975291; //unchecked((int)3024992005); //frac = 0x2000_0000 p.NtpLSW = 536870912; //Ensure was written and read correctly if (p.NtpDateTime != ExpectedDateTime) { throw new Exception("NtpDateTime does not equal ExpectedDate: " + p.NtpDateTime); } //The middle 32 bits out of 64 in the NTP timestamp (as explained in Section 4) received as part of the most recent RTCP sender report (SR) packet from source SSRC_n. If no SR has been received yet, the field is set to zero. if ((ulong)((p.NtpTimestamp) >> 16) << 32 != 0xB705200000000000) { throw new Exception(); } //In Seconds, DSLR = 0x0005:4000 (5.250s) const double ExpectedDelay = 5.250; //Let A = DateTime A = new DateTime(1995, 11, 10, 11, 33, 36, 500, DateTimeKind.Utc); //.ToString("s.ffff") //The delay, expressed in units of 1/65536 seconds, between receiving the last SR packet from source SSRC_n and sending this reception report block. If no SR packet has been received yet from SSRC_n, the DLSR field is set to zero. TimeSpan delay = A.Subtract(TimeSpan.FromSeconds(ExpectedDelay)).Subtract(ExpectedDateTime); //46864.500 - 5.250 - 46853.125 = 6.125 if (delay.TotalSeconds != 6.125) { throw new Exception("Unexpected delay of: " + delay.ToString()); } } }
/// <summary> /// O( ) /// </summary> public static void TestAConstructor_And_Reserialization() { //Permute every possible value in the 5 bit BlockCount for (byte ReportBlockCounter = byte.MinValue; ReportBlockCounter <= Media.Common.Binary.FiveBitMaxValue; ++ReportBlockCounter) { //Permute every possible value in the Padding field. for (byte PaddingCounter = byte.MinValue; PaddingCounter <= Media.Common.Binary.FiveBitMaxValue; ++PaddingCounter) { //Create a random id int RandomId = RFC3550.Random32(Utility.Random.Next()); //Create a SendersReport instance using the specified options. using (Media.Rtcp.SendersReport p = new Rtcp.SendersReport(0, PaddingCounter, ReportBlockCounter, RandomId)) { //Check SendersInformation System.Diagnostics.Debug.Assert(p.SendersInformation.Count() == Rtcp.SendersReport.SendersInformationSize, "Unexpected SendersInformation Count"); System.Diagnostics.Debug.Assert(p.SendersInformation.All(s => s == 0), "Unexpected SendersInformation Data"); //Check IsComplete System.Diagnostics.Debug.Assert(p.IsComplete, "IsComplete must be true."); //Check Length System.Diagnostics.Debug.Assert(p.Length == Binary.BitsPerByte + Rtcp.ReportBlock.ReportBlockSize * ReportBlockCounter + Rtcp.SendersReport.SendersInformationSize + PaddingCounter, "Unexpected Length"); //Check SynchronizationSourceIdentifier System.Diagnostics.Debug.Assert(p.SynchronizationSourceIdentifier == RandomId, "Unexpected SynchronizationSourceIdentifier"); //Check the BlockCount count System.Diagnostics.Debug.Assert(p.BlockCount == ReportBlockCounter, "Unexpected BlockCount"); //Check the PaddingOctets count System.Diagnostics.Debug.Assert(p.PaddingOctets == PaddingCounter, "Unexpected PaddingOctets"); //Check all data in the padding but not the padding octet itself. System.Diagnostics.Debug.Assert(p.PaddingData.Take(PaddingCounter - 1).All(b => b == 0), "Unexpected PaddingData"); //Verify all IReportBlock foreach (Rtcp.IReportBlock rb in p) { System.Diagnostics.Debug.Assert(rb.BlockIdentifier == 0, "Unexpected ChunkIdentifier"); System.Diagnostics.Debug.Assert(rb.BlockData.All(b => b == 0), "Unexpected BlockData"); System.Diagnostics.Debug.Assert(rb.Size == Media.Rtcp.ReportBlock.ReportBlockSize, "Unexpected Size"); } //Serialize and Deserialize and verify again using (Rtcp.SendersReport s = new Rtcp.SendersReport(new Rtcp.RtcpPacket(p.Prepare().ToArray(), 0), true)) { //Check SynchronizationSourceIdentifier System.Diagnostics.Debug.Assert(s.SynchronizationSourceIdentifier == p.SynchronizationSourceIdentifier, "Unexpected SynchronizationSourceIdentifier"); //Check the Payload.Count System.Diagnostics.Debug.Assert(s.Payload.Count == p.Payload.Count, "Unexpected Payload Count"); //Check the Length, System.Diagnostics.Debug.Assert(s.Length == p.Length, "Unexpected Length"); //Check the BlockCount count System.Diagnostics.Debug.Assert(s.BlockCount == p.BlockCount, "Unexpected BlockCount"); //Verify all IReportBlock foreach (Rtcp.IReportBlock rb in s) { System.Diagnostics.Debug.Assert(rb.BlockIdentifier == 0, "Unexpected ChunkIdentifier"); System.Diagnostics.Debug.Assert(rb.BlockData.All(b => b == 0), "Unexpected BlockData"); System.Diagnostics.Debug.Assert(rb.Size == Media.Rtcp.ReportBlock.ReportBlockSize, "Unexpected Size"); } //Check the RtcpData System.Diagnostics.Debug.Assert(p.RtcpData.SequenceEqual(s.RtcpData), "Unexpected RtcpData"); //Check the PaddingOctets System.Diagnostics.Debug.Assert(s.PaddingOctets == p.PaddingOctets, "Unexpected PaddingOctets"); //Check all data in the padding but not the padding octet itself. System.Diagnostics.Debug.Assert(s.PaddingData.SequenceEqual(p.PaddingData), "Unexpected PaddingData"); //Check SendersInformation System.Diagnostics.Debug.Assert(s.SendersInformation.Count() == Rtcp.SendersReport.SendersInformationSize && s.SendersInformation.All(o => o == 0), "Unexpected SendersInformation"); } } } } }
/// <summary> /// O( ) /// </summary> public static void TestAConstructor_And_Reserialization() { //Permute every possible value in the 5 bit BlockCount except the last, it is possible to have 32 with there are 31 entries in the SourceList, this logic should be tested seperately. for (byte SourceCounter = byte.MinValue; SourceCounter <= Media.Common.Binary.FiveBitMaxValue - 1; ++SourceCounter) { //Permute every possible value in the Padding field. for (byte PaddingCounter = byte.MinValue; PaddingCounter <= Media.Common.Binary.FiveBitMaxValue; ++PaddingCounter) { //Enumerate every possible reason length within reason. for (byte ReasonLength = byte.MinValue; ReasonLength <= Media.Common.Binary.FiveBitMaxValue; ++ReasonLength) { //Create the RandomId and ReasonForLeaving int RandomId = RFC3550.Random32(Utility.Random.Next()); IEnumerable <byte> ReasonForLeaving = Array.ConvertAll(Enumerable.Range(1, (int)ReasonLength).ToArray(), Convert.ToByte); //Create a GoodbyeReport instance using the specified options. using (Media.Rtcp.GoodbyeReport p = new Rtcp.GoodbyeReport(0, PaddingCounter, RandomId, new RFC3550.SourceList(SourceCounter), ReasonForLeaving.ToArray())) { //Check IsComplete System.Diagnostics.Debug.Assert(p.IsComplete, "IsComplete must be true."); //Check SynchronizationSourceIdentifier System.Diagnostics.Debug.Assert(p.SynchronizationSourceIdentifier == RandomId, "Unexpected SynchronizationSourceIdentifier"); //Calculate the length of the ReasonForLeaving, should always be padded to 32 bits for octet alignment. int expectedReasonLength = ReasonLength > 0 ? Binary.BytesToMachineWords(ReasonLength + 1) * Binary.BytesPerInteger : 0; //Check HasReasonForLeaving System.Diagnostics.Debug.Assert(expectedReasonLength > 0 == p.HasReasonForLeaving, "Unexpected HasReasonForLeaving"); //The ssrc is always present in these tests. int expectedBlockCount = SourceCounter + 1; //Check BlockCount System.Diagnostics.Debug.Assert(p.BlockCount == expectedBlockCount, "Unexpected BlockCount"); //Check the SourceList int expectedSourceListSize = expectedBlockCount * RFC3550.SourceList.ItemSize; //The first entry is in the header.... if (expectedSourceListSize > 0) { //Use the SourceList using (Media.RFC3550.SourceList sourceList = p.GetSourceList()) { System.Diagnostics.Debug.Assert(sourceList.IsComplete == true, "SourceList.IsComplete"); System.Diagnostics.Debug.Assert(expectedSourceListSize == sourceList.Size, "Unexpected SourceList Size"); System.Diagnostics.Debug.Assert(expectedBlockCount == sourceList.Count, "Unexpected SourceList Count"); System.Diagnostics.Debug.Assert(RandomId == sourceList.CurrentSource, "Unexpected Source in SourceList"); System.Diagnostics.Debug.Assert((uint)RandomId == sourceList.First(), "Unexpected Source in SourceList"); System.Diagnostics.Debug.Assert(sourceList.Skip(1).All(s => s == uint.MinValue), "Unexpected Source in SourceList"); System.Diagnostics.Debug.Assert(sourceList.ToArray().SequenceEqual(Enumerable.Concat <uint>(LinqExtensions.Yield((uint)RandomId), Enumerable.Repeat(uint.MinValue, SourceCounter))), "Unexpected Source in SourceList"); } } //The amount of bytes expected in the payload does not contain the first entry of the list. int expectedInPayload = expectedSourceListSize - RFC3550.SourceList.ItemSize; //Check the Payload.Count System.Diagnostics.Debug.Assert(p.Payload.Count == expectedInPayload + PaddingCounter + expectedReasonLength, "Unexpected Payload Count"); //Check the Length, System.Diagnostics.Debug.Assert(p.Length == p.Header.Size + expectedInPayload + PaddingCounter + expectedReasonLength, "Unexpected Length"); //Check the reaosn for leaving System.Diagnostics.Debug.Assert(p.ReasonForLeavingData.SequenceEqual(ReasonForLeaving), "Unexpected ReasonForLeaving data"); //Check the PaddingOctets count System.Diagnostics.Debug.Assert(p.PaddingOctets == PaddingCounter, "Unexpected PaddingOctets"); //Check all data in the padding but not the padding octet itself. System.Diagnostics.Debug.Assert(p.PaddingData.Take(PaddingCounter - 1).All(b => b == 0), "Unexpected PaddingData"); //Add remaining amount of reports to test the Add method //Enumerate the RtcpReport version of the instance //Serialize and Deserialize and verify again using (Rtcp.GoodbyeReport s = new Rtcp.GoodbyeReport(new Rtcp.RtcpPacket(p.Prepare().ToArray(), 0), true)) { //Check the Payload.Count System.Diagnostics.Debug.Assert(s.Payload.Count == p.Payload.Count, "Unexpected Payload Count"); //Check the Length, System.Diagnostics.Debug.Assert(s.Length == p.Length, "Unexpected Length"); //Check the BlockCount count System.Diagnostics.Debug.Assert(s.BlockCount == p.BlockCount, "Unexpected BlockCount"); //Check the reaosn for leaving System.Diagnostics.Debug.Assert(s.ReasonForLeavingData.SequenceEqual(ReasonForLeaving) && s.ReasonForLeavingData.Count() == ReasonLength, "Unexpected ReasonForLeaving data"); //Check the PaddingOctets count System.Diagnostics.Debug.Assert(s.PaddingOctets == p.PaddingOctets, "Unexpected PaddingOctets"); //Check all data in the padding but not the padding octet itself. System.Diagnostics.Debug.Assert(s.PaddingData.SequenceEqual(p.PaddingData), "Unexpected PaddingData"); } } } } } }
/// <summary> /// O( ) /// </summary> public static void TestAConstructor_And_Reserialization() { //Permute every possible value in the 5 bit BlockCount for (byte SubTypeCounter = byte.MinValue; SubTypeCounter <= Binary.FiveBitMaxValue; ++SubTypeCounter) { //Permute every possible value in the Padding field. for (byte PaddingCounter = byte.MinValue; PaddingCounter <= Media.Common.Binary.FiveBitMaxValue; ++PaddingCounter) { //Enumerate every possible reason length for (byte ApplicationSpecificDataLength = byte.MinValue; ApplicationSpecificDataLength <= Media.Common.Binary.FiveBitMaxValue; ++ApplicationSpecificDataLength) { //Create a random id int RandomId = RFC3550.Random32(Utility.Random.Next()); //Create the Name and ApplicationDependentData IEnumerable <byte> NameData = Array.ConvertAll(Enumerable.Range(1, (int)Rtcp.ApplicationSpecificReport.NameSize).ToArray(), Convert.ToByte), ApplicationDependentData = Array.ConvertAll(Enumerable.Range(1, (int)ApplicationSpecificDataLength).ToArray(), Convert.ToByte); //Create a GoodbyeReport instance using the specified options. using (Media.Rtcp.ApplicationSpecificReport p = new Rtcp.ApplicationSpecificReport(0, PaddingCounter, RandomId, SubTypeCounter, NameData.ToArray(), ApplicationDependentData.ToArray())) { //Check IsComplete System.Diagnostics.Debug.Assert(p.IsComplete, "IsComplete must be true."); //Calculate the length of the ReasonForLeaving, should always be padded to 32 bits for octet alignment. int expectedApplicationSpecificDataLength = ApplicationSpecificDataLength > 0 ? Binary.BytesToMachineWords(ApplicationSpecificDataLength + 1) * Binary.BytesPerInteger : 0; //Check HasApplicationDependentData System.Diagnostics.Debug.Assert(expectedApplicationSpecificDataLength > 0 == p.HasApplicationDependentData, "Unexpected HasApplicationDependentData"); //Check the Payload.Count System.Diagnostics.Debug.Assert(p.Payload.Count == Rtcp.ApplicationSpecificReport.NameSize + PaddingCounter + expectedApplicationSpecificDataLength, "Unexpected Payload Count"); //Check the Length, System.Diagnostics.Debug.Assert(p.Length == Rtcp.RtcpHeader.Length + Binary.BytesPerInteger + Rtcp.ApplicationSpecificReport.NameSize + PaddingCounter + expectedApplicationSpecificDataLength, "Unexpected Length"); //Check the BlockCount and SubType System.Diagnostics.Debug.Assert(p.BlockCount == SubTypeCounter && p.Subtype == SubTypeCounter, "Unexpected SubType"); //Check the RtcpData, Name and ApplicationDependentData System.Diagnostics.Debug.Assert(p.RtcpData.Take(Rtcp.ApplicationSpecificReport.NameSize + ApplicationSpecificDataLength).SequenceEqual(NameData.Concat(ApplicationDependentData)) && p.Name.SequenceEqual(NameData) && p.ApplicationDependentData.Count() == expectedApplicationSpecificDataLength && p.ApplicationDependentData.Take(ApplicationSpecificDataLength).SequenceEqual(ApplicationDependentData), "Unexpected ApplicationDependentData data"); //Check the PaddingOctets count System.Diagnostics.Debug.Assert(p.PaddingOctets == PaddingCounter, "Unexpected PaddingOctets"); //Check all data in the padding but not the padding octet itself. System.Diagnostics.Debug.Assert(p.PaddingData.Take(PaddingCounter - 1).All(b => b == 0), "Unexpected PaddingData"); //Serialize and Deserialize the packet and verify again using (Media.Rtcp.ApplicationSpecificReport s = new Rtcp.ApplicationSpecificReport(new Rtcp.RtcpPacket(p.Prepare().ToArray(), 0))) { //Check the Payload.Count System.Diagnostics.Debug.Assert(s.Payload.Count == p.Payload.Count, "Unexpected Payload Count"); //Check the Length, System.Diagnostics.Debug.Assert(s.Length == p.Length, "Unexpected Length"); //Check the BlockCount and SubType System.Diagnostics.Debug.Assert(p.BlockCount == SubTypeCounter && p.Subtype == SubTypeCounter, "Unexpected BlockCount"); //Check the RtcpData, Name and ApplicationDependentData System.Diagnostics.Debug.Assert(s.RtcpData.Take(Rtcp.ApplicationSpecificReport.NameSize + ApplicationSpecificDataLength).SequenceEqual(NameData.Concat(ApplicationDependentData)) && p.Name.SequenceEqual(NameData) && s.ApplicationDependentData.Count() == expectedApplicationSpecificDataLength && s.ApplicationDependentData.Take(ApplicationSpecificDataLength).SequenceEqual(ApplicationDependentData) && s.ApplicationDependentData.SequenceEqual(p.ApplicationDependentData), "Unexpected ApplicationDependentData data"); //Check the PaddingOctets count System.Diagnostics.Debug.Assert(s.PaddingOctets == p.PaddingOctets, "Unexpected PaddingOctets"); //Check all data in the padding but not the padding octet itself. System.Diagnostics.Debug.Assert(s.PaddingData.SequenceEqual(p.PaddingData), "Unexpected PaddingData"); } } } } } }
/// <summary> /// O( ) /// </summary> public static void TestAConstructor_And_Reserialization() { //Permute every possible value in the 5 bit BlockCount for (byte ReportBlockCounter = byte.MinValue; ReportBlockCounter <= Media.Common.Binary.FiveBitMaxValue; ++ReportBlockCounter) { //Permute every possible value in the Padding field. for (byte PaddingCounter = byte.MinValue; PaddingCounter <= Media.Common.Binary.FiveBitMaxValue; ++PaddingCounter) { //Enumerate every possible reason length for (byte ReasonLength = byte.MinValue; ReasonLength <= Media.Common.Binary.FiveBitMaxValue; ++ReasonLength) { //Create the RandomId and ReasonForLeaving int RandomId = RFC3550.Random32(Utility.Random.Next()); IEnumerable <byte> ReasonForLeaving = Array.ConvertAll(Enumerable.Range(1, (int)ReasonLength).ToArray(), Convert.ToByte); //Create a GoodbyeReport instance using the specified options. using (Media.Rtcp.GoodbyeReport p = new Rtcp.GoodbyeReport(0, PaddingCounter, RandomId, new RFC3550.SourceList(ReportBlockCounter), ReasonForLeaving.ToArray())) { //Check IsComplete System.Diagnostics.Debug.Assert(p.IsComplete, "IsComplete must be true."); //Check SynchronizationSourceIdentifier System.Diagnostics.Debug.Assert(p.SynchronizationSourceIdentifier == RandomId, "Unexpected SynchronizationSourceIdentifier"); //Calculate the length of the ReasonForLeaving, should always be padded to 32 bits for octet alignment. int expectedReasonLength = ReasonLength > 0 ? Binary.BytesToMachineWords(ReasonLength + 1) * Binary.BytesPerInteger : 0; //Check HasReasonForLeaving System.Diagnostics.Debug.Assert(expectedReasonLength > 0 == p.HasReasonForLeaving, "Unexpected HasReasonForLeaving"); //Check the Payload.Count System.Diagnostics.Debug.Assert(p.Payload.Count == ReportBlockCounter * Binary.BytesPerInteger + PaddingCounter + expectedReasonLength, "Unexpected Payload Count"); //Check the Length, System.Diagnostics.Debug.Assert(p.Length == p.Header.Size + ReportBlockCounter * Binary.BytesPerInteger + PaddingCounter + expectedReasonLength, "Unexpected Length"); //Check the BlockCount count System.Diagnostics.Debug.Assert(p.BlockCount == ReportBlockCounter, "Unexpected BlockCount"); //Check the reaosn for leaving System.Diagnostics.Debug.Assert(p.ReasonForLeaving.SequenceEqual(ReasonForLeaving), "Unexpected ReasonForLeaving data"); //Check the PaddingOctets count System.Diagnostics.Debug.Assert(p.PaddingOctets == PaddingCounter, "Unexpected PaddingOctets"); //Check all data in the padding but not the padding octet itself. System.Diagnostics.Debug.Assert(p.PaddingData.Take(PaddingCounter - 1).All(b => b == 0), "Unexpected PaddingData"); //Serialize and Deserialize and verify again using (Rtcp.GoodbyeReport s = new Rtcp.GoodbyeReport(new Rtcp.RtcpPacket(p.Prepare().ToArray(), 0), true)) { //Check the Payload.Count System.Diagnostics.Debug.Assert(s.Payload.Count == p.Payload.Count, "Unexpected Payload Count"); //Check the Length, System.Diagnostics.Debug.Assert(s.Length == p.Length, "Unexpected Length"); //Check the BlockCount count System.Diagnostics.Debug.Assert(s.BlockCount == p.BlockCount, "Unexpected BlockCount"); //Check the reaosn for leaving System.Diagnostics.Debug.Assert(s.ReasonForLeaving.SequenceEqual(ReasonForLeaving) && s.ReasonForLeaving.Count() == ReasonLength, "Unexpected ReasonForLeaving data"); //Check the PaddingOctets count System.Diagnostics.Debug.Assert(s.PaddingOctets == p.PaddingOctets, "Unexpected PaddingOctets"); //Check all data in the padding but not the padding octet itself. System.Diagnostics.Debug.Assert(s.PaddingData.SequenceEqual(p.PaddingData), "Unexpected PaddingData"); } } } } } }
public static GoodbyeReport CreateGoodbye(TransportContext context, byte[] reasonForLeaving = null, int? ssrc = null, RFC3550.SourceList sourcesLeaving = null) { //Make a Goodbye, indicate version in Client, allow reason for leaving //Todo add other parties where null with SourceList return new GoodbyeReport(context.Version, ssrc ?? (int)context.SynchronizationSourceIdentifier, sourcesLeaving ?? new RFC3550.SourceList((uint)context.SynchronizationSourceIdentifier), reasonForLeaving); }