feyris-tan 7e7a3f86dd
Some checks failed
🚀 Pack skyscraper8 / make-zip (push) Failing after 1m48s
Reworked the database handling for TIMs.
2026-03-21 22:38:16 +01:00

330 lines
8.6 KiB
C#

using skyscraper5.Mpeg2;
using skyscraper5.Mpeg2.Descriptors;
using skyscraper5.Skyscraper;
using skyscraper5.Skyscraper.IO;
using skyscraper5.src.InteractionChannel.Model.Descriptors;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
using skyscraper8.GSE.GSE;
using skyscraper8.InteractionChannel.Model2.Descriptors;
using Ionic.Crc;
using Ionic.Zlib;
namespace skyscraper5.src.InteractionChannel.Model
{
public class Tim : Validatable
{
public Tim(bool broadcast, byte status, TsDescriptor[] descs)
{
this.Broadcast = broadcast;
this.Status = status;
this.Descriptors = descs;
}
public Tim(MemoryStream ms, bool broadcast)
{
Broadcast = broadcast;
Status = ms.ReadUInt8();
byte descriptorLoopCount = ms.ReadUInt8(); descriptorLoopCount++;
int minimumRequiredLength = descriptorLoopCount * 2;
if (ms.GetAvailableBytes() < minimumRequiredLength)
{
Valid = false;
return;
}
Descriptors = new TsDescriptor[descriptorLoopCount];
for (int i = 0; i < descriptorLoopCount; i++)
{
//we don't have a way to read single descriptors so far
byte descriptorTag = ms.ReadUInt8();
byte descriptorLength = ms.ReadUInt8();
if (ms.GetAvailableBytes() < descriptorLength)
{
Valid = false;
return;
}
byte[] descriptorBuffer = ms.ReadBytes(descriptorLength);
switch(descriptorTag)
{
case 0x4a:
//Linkage_descriptor
//must appear in RMT, not TIM
Valid = false;
return;
case 0xa0:
Descriptors[i] = new _0xa0_NetworkLayerInfoDescriptor(descriptorBuffer);
break;
case 0xa1:
Descriptors[i] = new _0xa1_CorrectionMessageDescriptor(descriptorBuffer);
break;
case 0xa2:
Descriptors[i] = new _0xa2_LoginInitializeDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xa3:
Descriptors[i] = new _0xa3_AcqAssignDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xa4:
Descriptors[i] = new _0xa4_SyncAssignDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xa5:
Descriptors[i] = new _0xa5_EncryptedLoginIdDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xa7:
//RCS_content_descriptor
//can't appear in a TIM.
Valid = false;
return;
case 0xa8:
Descriptors[i] = new _0xa8_SatelliteForwardLinkDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xa9:
Descriptors[i] = new _0xa9_SatelliteReturnLinkDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xaa:
Descriptors[i] = new _0xaa_TableUpdateDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xab:
Descriptors[i] = new _0xab_ContentionControlDescriptor(descriptorBuffer);
break;
case 0xac:
Descriptors[i] = new _0xac_CorrectionControlDescriptor(descriptorBuffer);
break;
case 0xad:
Descriptors[i] = new _0xad_ForwardInteractionPathDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xae:
Descriptors[i] = new _0xae_ReturnInteractionPathDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xb1:
Descriptors[i] = new _0xb1_CorrectionMessageExtensionDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xb5:
Descriptors[i] = new _0xb5_ImplementationTypeDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xaf:
Descriptors[i] = new _0xaf_ConnectionControlDescriptor(descriptorBuffer);
break;
case 0xb2:
Descriptors[i] = new _0xb2_ReturnTransmissionModesDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xb3:
Descriptors[i] = new _0xb3_MeshLogonInitializeDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xb6:
Descriptors[i] = new _0xb6_LlFecIdentifierDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xb7:
Descriptors[i] = new _0xb7_FramePayloadFormatDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xb9:
Descriptors[i] = new _0xb9_LogonResponseDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xbb:
Descriptors[i] = new _0xbb_LowerLayerServiceDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
case 0xc4:
Descriptors[i] = new _0xc4_HigherLayersInitializeDescriptor(descriptorBuffer);
if (!Descriptors[i].Valid)
{
Valid = false;
return;
}
break;
default:
if (descriptorTag >= 0x00 && descriptorTag <= 0x49)
{
//Reserved
continue;
}
if (descriptorTag >= 0x4b && descriptorTag <= 0x9f)
{
//Reserved
continue;
}
if (descriptorTag >= 0xcc && descriptorTag <= 0xdf)
{
//Reserved
continue;
}
if (descriptorTag >= 0xe0 && descriptorTag <= 0xfe)
{
Descriptors[i] = new UserDefinedDescriptor(descriptorTag, descriptorBuffer);
break;
}
if (descriptorTag == 0xff)
{
//Forbidden
Valid = false;
return;
}
throw new NotImplementedException(String.Format("TIM Parse 0x{0:X2}", descriptorTag));
}
}
byte[] padBytes = ms.ReadBytes(ms.GetAvailableBytes() - 4);
uint crc32 = ms.ReadUInt32BE();
Valid = true;
}
public bool Broadcast { get; }
public byte Status { get; }
public TsDescriptor[] Descriptors { get; }
public bool IDEncrypt => (Status & 0x80) != 0;
public bool LogonFail => (!Broadcast & ((Status & 0x40) != 0));
public bool LogonDenied => (!Broadcast & ((Status & 0x20) != 0));
public bool Logoff => (!Broadcast & ((Status & 0x10) != 0));
public bool TransmitDisable => (!Broadcast & ((Status & 0x08) != 0));
public bool RainFadeRelease => (!Broadcast & ((Status & 0x04) != 0));
public bool RainFadeDetect => (!Broadcast & ((Status & 0x02) != 0));
public bool WakeUp => (!Broadcast & ((Status & 0x01) != 0));
public bool CscLinkFailureRec => (Broadcast & ((Status & 0x10) != 0));
public bool LinkFailureRecovery => (Broadcast & ((Status & 0x08) != 0));
public bool ReturnLinkFailure => (Broadcast & ((Status & 0x04) != 0));
public bool NccReceiveFailure => (Broadcast & ((Status & 0x02) != 0));
public bool SchedulerFailure => (Broadcast & ((Status & 0x01) != 0));
public override int GetHashCode()
{
int hash = 17;
hash ^= HashCode.Combine(Broadcast, Status, Descriptors.Length);
foreach (TsDescriptor tsDescriptor in Descriptors)
{
hash ^= tsDescriptor.GetDescriptorHashCode();
}
return hash;
}
public override bool Equals(object? obj)
{
if (obj == null)
return false;
Tim that = obj as Tim;
if (that == null)
return false;
if (this.Status != that.Status)
return false;
bool thisHasDescriptors = this.Descriptors != null;
bool thatHasDescriptors = that.Descriptors != null;
if (thisHasDescriptors != thatHasDescriptors)
return false;
if (this.Descriptors.Length != that.Descriptors.Length)
return false;
for (int i = 0; i < this.Descriptors.Length; i++)
{
TsDescriptor thisDescriptor = this.Descriptors[i];
TsDescriptor thatDescriptor = that.Descriptors[i];
byte thisDescriptorId = thisDescriptor.GetDescriptorId();
byte thatDescriptorId = thatDescriptor.GetDescriptorId();
if (thisDescriptorId != thatDescriptorId)
return false;
if (!thisDescriptor.DescriptorEquals(thatDescriptor))
{
return false;
}
}
return true;
}
}
}