Added a rudimentary ULE deframer.
This commit is contained in:
parent
0453a7115a
commit
8c76f9a421
24
skyscraper8/Ietf/IetfException.cs
Normal file
24
skyscraper8/Ietf/IetfException.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5;
|
||||
|
||||
namespace skyscraper8.Ietf
|
||||
{
|
||||
public class IetfException : SkyscraperException
|
||||
{
|
||||
public IetfException()
|
||||
{
|
||||
}
|
||||
|
||||
public IetfException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public IetfException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
46
skyscraper8/Ietf/Rfc4236_ULE/UleContestant.cs
Normal file
46
skyscraper8/Ietf/Rfc4236_ULE/UleContestant.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Skyscraper.Plugins;
|
||||
using skyscraper5.Skyscraper.Scraper;
|
||||
using skyscraper5.Skyscraper.Scraper.StreamAutodetection;
|
||||
|
||||
namespace skyscraper8.Ietf.Rfc4236_ULE
|
||||
{
|
||||
[SkyscraperPlugin]
|
||||
internal class UleContestant : Contestant, UleEventHandler
|
||||
{
|
||||
public UleContestant(int pid) : base("ULE", pid)
|
||||
{
|
||||
PacketProcessor = new UlePacketProcessor(pid, this);
|
||||
}
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void DeclareWinner(SkyscraperContext skyscraperContext, int pid, ProgramContext programContext)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override void Introduce(ProgramContext programContext)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void OnEthernetFrame(int pid, PhysicalAddress destination, PhysicalAddress source, ushort etherType, byte[] contents)
|
||||
{
|
||||
Score++;
|
||||
}
|
||||
|
||||
public void OnUleError(int pid, int errorNo)
|
||||
{
|
||||
Score--;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
skyscraper8/Ietf/Rfc4236_ULE/UleEventHandler.cs
Normal file
24
skyscraper8/Ietf/Rfc4236_ULE/UleEventHandler.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Ietf.Rfc4236_ULE
|
||||
{
|
||||
internal interface UleEventHandler
|
||||
{
|
||||
void OnEthernetFrame(int pid, PhysicalAddress destination, PhysicalAddress source, ushort etherType, byte[] contents);
|
||||
|
||||
/// <summary>
|
||||
/// The UlePacketProcessor is supposed to call this whenever an Error occurs during deframing.
|
||||
/// </summary>
|
||||
/// <param name="pid">The source PID of the ULE ES</param>
|
||||
/// <param name="errorNo">
|
||||
/// Set this to:
|
||||
/// 1* for a CRC error.
|
||||
/// </param>
|
||||
void OnUleError(int pid, int errorNo);
|
||||
}
|
||||
}
|
||||
23
skyscraper8/Ietf/Rfc4236_ULE/UleException.cs
Normal file
23
skyscraper8/Ietf/Rfc4236_ULE/UleException.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace skyscraper8.Ietf.Rfc4236_ULE
|
||||
{
|
||||
public class UleException : IetfException
|
||||
{
|
||||
public UleException()
|
||||
{
|
||||
}
|
||||
|
||||
public UleException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public UleException(string message, Exception inner) : base(message, inner)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
176
skyscraper8/Ietf/Rfc4236_ULE/UlePacketProcessor.cs
Normal file
176
skyscraper8/Ietf/Rfc4236_ULE/UlePacketProcessor.cs
Normal file
@ -0,0 +1,176 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.NetworkInformation;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using skyscraper5.Mpeg2;
|
||||
using skyscraper5.Skyscraper.IO;
|
||||
|
||||
namespace skyscraper8.Ietf.Rfc4236_ULE
|
||||
{
|
||||
internal class UlePacketProcessor : ITsPacketProcessor, IPayloadUnitDecoder
|
||||
{
|
||||
private readonly int _pid;
|
||||
private readonly UleEventHandler _eventHandler;
|
||||
|
||||
private bool reassemblyMode;
|
||||
private int reassemblyRemainingBytes;
|
||||
private MemoryStream reassemblyStream;
|
||||
private long offset;
|
||||
|
||||
public UlePacketProcessor(int pid, UleEventHandler eventHandler)
|
||||
{
|
||||
_pid = pid;
|
||||
_eventHandler = eventHandler;
|
||||
}
|
||||
|
||||
public void PushPacket(TsPacket packet)
|
||||
{
|
||||
|
||||
if (packet.PayloadUnitStart)
|
||||
{
|
||||
PushPusiPacket(packet);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (reassemblyMode)
|
||||
{
|
||||
int availableBytes = Math.Min(184, reassemblyRemainingBytes);
|
||||
reassemblyStream.Write(packet.RawPacket, 4, availableBytes);
|
||||
reassemblyRemainingBytes -= availableBytes;
|
||||
if (reassemblyRemainingBytes == 0)
|
||||
{
|
||||
reassemblyMode = false;
|
||||
reassemblyStream.Position = 0;
|
||||
OnReassembledPacket(reassemblyStream);
|
||||
reassemblyStream = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Es gibt keine neue Payload Unit, und wir bauen uns auch keine zusammen, also diese wegwerfen.
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
offset += 188;
|
||||
}
|
||||
|
||||
private void PushPusiPacket(TsPacket packet)
|
||||
{
|
||||
bool multipleSndusInPacket = false;
|
||||
|
||||
MemoryStream payload = new MemoryStream(packet.RawPacket, false);
|
||||
payload.Position += 4;
|
||||
byte nextPacketOffset = payload.ReadUInt8();
|
||||
if (!reassemblyMode)
|
||||
payload.Position += nextPacketOffset;
|
||||
|
||||
while (payload.GetAvailableBytes() > 0)
|
||||
{
|
||||
if (reassemblyMode)
|
||||
{
|
||||
int availableBytes = Math.Min((int)payload.GetAvailableBytes(), reassemblyRemainingBytes);
|
||||
byte[] stepBuffer = new byte[availableBytes];
|
||||
int sucessfullyCopiedBytes = payload.Read(stepBuffer, 0, availableBytes);
|
||||
if (sucessfullyCopiedBytes != availableBytes)
|
||||
throw new UleException("Byte copy operation failed during reassembly.");
|
||||
reassemblyStream.Write(stepBuffer, 0, sucessfullyCopiedBytes);
|
||||
reassemblyRemainingBytes -= sucessfullyCopiedBytes;
|
||||
if (reassemblyRemainingBytes == 0)
|
||||
{
|
||||
reassemblyMode = false;
|
||||
reassemblyStream.Position = 0;
|
||||
OnReassembledPacket(reassemblyStream);
|
||||
reassemblyStream = null;
|
||||
multipleSndusInPacket = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (payload.GetAvailableBytes() == 1)
|
||||
{
|
||||
/*"If only one byte remains unprocessed in the TS Packet payload
|
||||
after completion of the Current SNDU, the Receiver MUST discard this
|
||||
final byte of TS Packet payload."*/
|
||||
break;
|
||||
}
|
||||
|
||||
byte lengthByteA = payload.ReadUInt8();
|
||||
bool destinationAddressAbsent = (lengthByteA & 0x80) != 0;
|
||||
|
||||
byte lengthByteB = payload.ReadUInt8();
|
||||
|
||||
int length = lengthByteA & 0x7f;
|
||||
length <<= 8;
|
||||
length += lengthByteB;
|
||||
length += 2;
|
||||
|
||||
if (length == 0x8001)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
reassemblyMode = true;
|
||||
reassemblyRemainingBytes = length;
|
||||
reassemblyStream = new MemoryStream();
|
||||
reassemblyStream.WriteUInt8(lengthByteA);
|
||||
reassemblyStream.WriteUInt8(lengthByteB);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnReassembledPacket(MemoryStream ms)
|
||||
{
|
||||
bool crc = DvbCrc32.ValidateCrc(ms, 0, (int)ms.Length);
|
||||
if (!crc)
|
||||
{
|
||||
_eventHandler.OnUleError(_pid, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
byte lengthByteA = ms.ReadUInt8();
|
||||
bool destinationAddressAbsent = (lengthByteA & 0x80) != 0;
|
||||
byte lengthBytesB = ms.ReadUInt8();
|
||||
|
||||
ushort typeField = ms.ReadUInt16BE();
|
||||
|
||||
PhysicalAddress destAddress = null;
|
||||
if (!destinationAddressAbsent)
|
||||
destAddress = new PhysicalAddress(ms.ReadBytes(6));
|
||||
|
||||
long packetSize = ms.GetAvailableBytes() - 4;
|
||||
byte[] pdu = ms.ReadBytes(packetSize);
|
||||
uint crc32 = ms.ReadUInt32BE();
|
||||
|
||||
switch (typeField)
|
||||
{
|
||||
case 1:
|
||||
OnBridgedFrame(pdu);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException(String.Format("ULE Type 0x{0:X4}", typeField));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnBridgedFrame(byte[] pdu)
|
||||
{
|
||||
MemoryStream ms = new MemoryStream(pdu, false);
|
||||
PhysicalAddress destination = new PhysicalAddress(ms.ReadBytes(6));
|
||||
PhysicalAddress source = new PhysicalAddress(ms.ReadBytes(6));
|
||||
ushort etherType = ms.ReadUInt16BE();
|
||||
byte[] contents = ms.ReadBytes(ms.GetAvailableBytes());
|
||||
//_eventHandler.OnEthernetFrame(_pid, destination, source, etherType, contents);
|
||||
}
|
||||
|
||||
public void PacketLoss()
|
||||
{
|
||||
reassemblyMode = false;
|
||||
reassemblyRemainingBytes = 0;
|
||||
reassemblyStream = null;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user