330 lines
8.6 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|