357 lines
10 KiB
C#
357 lines
10 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;
|
|
|
|
namespace skyscraper5.src.InteractionChannel.Model
|
|
{
|
|
public class Tim : Validatable
|
|
{
|
|
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));
|
|
|
|
internal void Handle(PhysicalAddress macAddress, ushort? networkId, InteractionChannelHandler handler)
|
|
{
|
|
foreach(TsDescriptor descriptor in Descriptors)
|
|
{
|
|
if (descriptor == null)
|
|
{
|
|
continue;
|
|
}
|
|
if (descriptor is UserDefinedDescriptor)
|
|
{
|
|
continue;
|
|
}
|
|
if (!descriptor.Valid)
|
|
{
|
|
Valid = false;
|
|
return;
|
|
}
|
|
byte id = descriptor.GetDescriptorId();
|
|
switch(id)
|
|
{
|
|
case 0xa0:
|
|
handler.OnNetworkLayerInfo(macAddress, (_0xa0_NetworkLayerInfoDescriptor)descriptor);
|
|
break;
|
|
case 0xa1:
|
|
if (Broadcast)
|
|
{
|
|
if (networkId.HasValue)
|
|
{
|
|
handler.OnCorrectionMessage(networkId.Value, ToCmt((_0xa1_CorrectionMessageDescriptor)descriptor));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
handler.OnCorrectionMessage(macAddress, ((_0xa1_CorrectionMessageDescriptor)descriptor));
|
|
}
|
|
break;
|
|
case 0xa4:
|
|
handler.OnControlAssignment(macAddress,(_0xa4_SyncAssignDescriptor)descriptor);
|
|
break;
|
|
case 0xa9:
|
|
handler.OnSatelliteReturnLink(macAddress, (_0xa9_SatelliteReturnLinkDescriptor)descriptor);
|
|
break;
|
|
case 0xab:
|
|
handler.OnContentionControl(macAddress, ((_0xab_ContentionControlDescriptor)descriptor));
|
|
break;
|
|
case 0xac:
|
|
handler.OnCorrectionControl(macAddress, (_0xac_CorrectionControlDescriptor)descriptor);
|
|
break;
|
|
case 0xad:
|
|
handler.OnForwardInteractionPath(macAddress, (_0xad_ForwardInteractionPathDescriptor)descriptor);
|
|
break;
|
|
case 0xaf:
|
|
handler.OnConnectionControl(macAddress, (_0xaf_ConnectionControlDescriptor)descriptor);
|
|
break;
|
|
case 0xb1:
|
|
handler.OnCorrectionMessageExtension(macAddress, (_0xb1_CorrectionMessageExtensionDescriptor)descriptor);
|
|
break;
|
|
case 0xb2:
|
|
handler.OnReturnTransmissionMOdes(macAddress, (_0xb2_ReturnTransmissionModesDescriptor)descriptor);
|
|
break;
|
|
case 0xb7:
|
|
handler.OnFramePayloadFormatAnnouncement(networkId.Value, (_0xb7_FramePayloadFormatDescriptor)descriptor);
|
|
break;
|
|
case 0xb9:
|
|
handler.LogonResponseDescriptor(macAddress, (_0xb9_LogonResponseDescriptor)descriptor);
|
|
break;
|
|
case 0xbb:
|
|
handler.OnLowerLayerService(macAddress, (_0xbb_LowerLayerServiceDescriptor)descriptor);
|
|
break;
|
|
case 0xc4:
|
|
handler.OnHigherLayerInitalization(macAddress, (_0xc4_HigherLayersInitializeDescriptor)descriptor);
|
|
break;
|
|
default:
|
|
if (id >= 0xe0 && id <= 0xfe)
|
|
break;
|
|
throw new NotImplementedException(String.Format("TIM Descriptor 0x{0:X2} ({1}) is not fully implemented yet. Please share a sample of this stream.", id, descriptor.GetType().Name));
|
|
}
|
|
}
|
|
}
|
|
|
|
private Cmt ToCmt(_0xa1_CorrectionMessageDescriptor descriptor)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
}
|