250 lines
7.0 KiB
C#
250 lines
7.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using skyscraper5.Mpeg2;
|
|
using skyscraper5.Skyscraper.IO;
|
|
|
|
namespace skyscraper5.Docsis
|
|
{
|
|
internal class DocsisPacketProcessor : ITsPacketProcessor, IPayloadUnitDecoder, IDisposable
|
|
{
|
|
public DocsisPacketProcessor(IDocsisEventHandler eventHandler)
|
|
{
|
|
this.eventHandler = eventHandler;
|
|
this.docsisEnvironment = new DocsisEnvironment(eventHandler);
|
|
}
|
|
|
|
|
|
private IDocsisEventHandler eventHandler;
|
|
|
|
private bool currentPayloadUnitPresent;
|
|
private MemoryStream currentPayloadBuffer;
|
|
private byte? FC;
|
|
|
|
public int? FC_TYPE
|
|
{
|
|
get
|
|
{
|
|
if (!FC.HasValue)
|
|
return null;
|
|
|
|
int i = (FC.Value & 0xc0) >> 6;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
public int? FC_PARM
|
|
{
|
|
get
|
|
{
|
|
if (!FC.HasValue)
|
|
return null;
|
|
int i = (FC.Value & 0x3e) >> 1;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
public bool? EHDR_ON
|
|
{
|
|
get
|
|
{
|
|
if (!FC.HasValue)
|
|
return null;
|
|
|
|
bool i = (FC.Value & 0x01) != 0;
|
|
return i;
|
|
}
|
|
}
|
|
|
|
private byte? MAC_PARM;
|
|
|
|
private byte? LEN_L, LEN_R;
|
|
|
|
private int? LEN
|
|
{
|
|
get
|
|
{
|
|
if (!LEN_L.HasValue || !LEN_R.HasValue)
|
|
return null;
|
|
|
|
int result = LEN_L.Value;
|
|
result <<= 8;
|
|
result += LEN_R.Value;
|
|
return result;
|
|
}
|
|
}
|
|
|
|
private byte[] EHDR;
|
|
private bool EHDR_done;
|
|
private int EHDR_ptr;
|
|
private int neededBytes;
|
|
|
|
private byte? HCS_L, HCS_R;
|
|
|
|
private bool packetDone;
|
|
|
|
public void PushPacket(TsPacket packet)
|
|
{
|
|
if (packet.AdaptionFieldControl != 1)
|
|
{
|
|
PacketLoss();
|
|
return;
|
|
}
|
|
|
|
bool packetPayloadUnitStart = packet.PayloadUnitStart;
|
|
MemoryStream ms = new MemoryStream(packet.Payload, false);
|
|
|
|
if (!currentPayloadUnitPresent && !packetPayloadUnitStart)
|
|
return;
|
|
|
|
if (!currentPayloadUnitPresent && packetPayloadUnitStart)
|
|
{
|
|
ms.Position = packet.PayloadStartOffset;
|
|
currentPayloadUnitPresent = true;
|
|
currentPayloadBuffer = new MemoryStream();
|
|
}
|
|
|
|
while (ms.GetAvailableBytes() > 0)
|
|
{
|
|
if (!FC.HasValue)
|
|
{
|
|
FC = ms.ReadUInt8();
|
|
currentPayloadBuffer.WriteByte(FC.Value);
|
|
continue;
|
|
}
|
|
|
|
if (!MAC_PARM.HasValue)
|
|
{
|
|
MAC_PARM = ms.ReadUInt8();
|
|
currentPayloadBuffer.WriteByte(MAC_PARM.Value);
|
|
continue;
|
|
}
|
|
|
|
if (!LEN_L.HasValue)
|
|
{
|
|
LEN_L = ms.ReadUInt8();
|
|
currentPayloadBuffer.WriteByte(LEN_L.Value);
|
|
continue;
|
|
}
|
|
|
|
if (!LEN_R.HasValue)
|
|
{
|
|
LEN_R = ms.ReadUInt8();
|
|
currentPayloadBuffer.WriteByte(LEN_R.Value);
|
|
if (EHDR_ON.Value)
|
|
{
|
|
EHDR = new byte[MAC_PARM.Value];
|
|
neededBytes = MAC_PARM.Value;
|
|
EHDR_done = false;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (!EHDR_done && EHDR_ON.Value)
|
|
{
|
|
int ehdrAvailable = (int)Math.Min(neededBytes, ms.GetAvailableBytes());
|
|
int ehdrWasRead = ms.Read(EHDR, EHDR_ptr, ehdrAvailable);
|
|
neededBytes -= ehdrWasRead;
|
|
EHDR_ptr += ehdrWasRead;
|
|
if (neededBytes == 0)
|
|
{
|
|
currentPayloadBuffer.Write(EHDR, 0, EHDR.Length);
|
|
EHDR_done = true;
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (!HCS_L.HasValue)
|
|
{
|
|
HCS_L = ms.ReadUInt8();
|
|
currentPayloadBuffer.WriteByte(HCS_L.Value);
|
|
continue;
|
|
}
|
|
|
|
if (!HCS_R.HasValue)
|
|
{
|
|
HCS_R = ms.ReadUInt8();
|
|
currentPayloadBuffer.WriteByte(HCS_R.Value);
|
|
packetDone = false;
|
|
neededBytes = LEN.Value;
|
|
if (EHDR_ON.Value)
|
|
neededBytes -= EHDR.Length;
|
|
continue;
|
|
}
|
|
|
|
if (!packetDone)
|
|
{
|
|
int toRead = (int)Math.Min(neededBytes, ms.GetAvailableBytes());
|
|
if (toRead < 0)
|
|
{
|
|
PacketLoss();
|
|
return;
|
|
}
|
|
byte[] tmp = new byte[toRead];
|
|
int readAmount = ms.Read(tmp, 0, toRead);
|
|
currentPayloadBuffer.Write(tmp, 0, readAmount);
|
|
neededBytes -= readAmount;
|
|
if (neededBytes == 0)
|
|
packetDone = true;
|
|
continue;
|
|
}
|
|
|
|
HandlePacket();
|
|
while (ms.GetAvailableBytes() > 0)
|
|
{
|
|
byte stuffing = ms.ReadUInt8();
|
|
if (stuffing != 0xff)
|
|
{
|
|
ms.Position--;
|
|
currentPayloadUnitPresent = true;
|
|
currentPayloadBuffer = new MemoryStream();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void PacketLoss()
|
|
{
|
|
Reset();
|
|
}
|
|
|
|
private void Reset()
|
|
{
|
|
currentPayloadUnitPresent = false;
|
|
currentPayloadBuffer = null;
|
|
FC = null;
|
|
MAC_PARM = null;
|
|
LEN_L = null;
|
|
LEN_R = null;
|
|
EHDR = null;
|
|
EHDR_done = false;
|
|
EHDR_ptr = 0;
|
|
neededBytes = 0;
|
|
HCS_L = null;
|
|
HCS_R = null;
|
|
packetDone = false;
|
|
}
|
|
|
|
private ulong processedPackets = 0;
|
|
private DocsisEnvironment docsisEnvironment;
|
|
|
|
private void HandlePacket()
|
|
{
|
|
currentPayloadBuffer.Position = 0;
|
|
docsisEnvironment.PushPacket(currentPayloadBuffer);
|
|
Reset();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
docsisEnvironment?.Dispose();
|
|
}
|
|
|
|
public DocsisEnvironment DocsisEnvironment => docsisEnvironment;
|
|
}
|
|
}
|