GSE testing

This commit is contained in:
feyris-tan 2025-09-19 08:48:16 +02:00
parent cc8e1edd90
commit f83b920af4
17 changed files with 610 additions and 50 deletions

View File

@ -12,3 +12,10 @@ These contain blob-like data, like Screenshots, DSM-CC Carousels, etc.
|--|----------| |--|----------|
| 1|MinIO | | 1|MinIO |
| 2|Filesystem| | 2|Filesystem|
#IP Traffic handlers
These will have IP packets forwarded to.
|ID|Type |
|--|-----------|
| 1|PCAP Writer|
| 2|Discard |

View File

@ -170,6 +170,8 @@ namespace SDL2Demo.Jobs
ImGui.Text("This assumes that both tuners are connected to the same antenna set-up, using e.g. a splitter."); ImGui.Text("This assumes that both tuners are connected to the same antenna set-up, using e.g. a splitter.");
ImGui.PushID("tunerB"); ImGui.PushID("tunerB");
if (settingsWindowSetFilterTunerSelection - 1 < tuners.Count)
settingsWindowSetFilterTunerSelection = 0;
if (ImGui.BeginCombo("Tuner for BLScanEx and RFScan", tuners[settingsWindowSetFilterTunerSelection].Name)) if (ImGui.BeginCombo("Tuner for BLScanEx and RFScan", tuners[settingsWindowSetFilterTunerSelection].Name))
{ {
for (int i = 0; i < tuners.Count; i++) for (int i = 0; i < tuners.Count; i++)

View File

@ -187,7 +187,6 @@ namespace skyscraper8.DvbNip
rawSlepString = rawSlepString.Replace("</dvbi-types:", "</"); rawSlepString = rawSlepString.Replace("</dvbi-types:", "</");
rawSlepString = rawSlepString.Replace("<dvbisdt:", "<"); rawSlepString = rawSlepString.Replace("<dvbisdt:", "<");
rawSlepString = rawSlepString.Replace("</dvbisdt:", "</"); rawSlepString = rawSlepString.Replace("</dvbisdt:", "</");
File.WriteAllText("slep3.xml", rawSlepString);
ServiceListEntryPoints serviceListEntryPoints = DvbIUtils.UnpackServiceListEntryPoints(rawSlepString); ServiceListEntryPoints serviceListEntryPoints = DvbIUtils.UnpackServiceListEntryPoints(rawSlepString);
EventHandler?.OnServiceListEntryPoints(CurrentCarrierInformation, serviceListEntryPoints, currentTime.Value, this); EventHandler?.OnServiceListEntryPoints(CurrentCarrierInformation, serviceListEntryPoints, currentTime.Value, this);
return true; return true;

View File

@ -32,6 +32,7 @@ using skyscraper8;
using skyscraper8.SatIp; using skyscraper8.SatIp;
using skyscraper8.SatIp.RtspResponses; using skyscraper8.SatIp.RtspResponses;
using skyscraper8.SimpleServiceDiscoveryProtocol; using skyscraper8.SimpleServiceDiscoveryProtocol;
using skyscraper8.Skyscraper.Math;
[assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")] [assembly: log4net.Config.XmlConfigurator(ConfigFile = "log4net.config")]
namespace skyscraper5 namespace skyscraper5
@ -39,19 +40,9 @@ namespace skyscraper5
class Program class Program
{ {
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private const int PUBLIC_RELEASE = 7; private const int PUBLIC_RELEASE = 8;
private static void IntegrationTest() private static void IntegrationTest()
{ {
PluginManager pluginManager = PluginManager.GetInstance();
StorageConnectionManager storageConnectionManager = StorageConnectionManager.GetInstance();
DataStorageFactory dataStorageFactory = storageConnectionManager.GetDefaultDataStorageFactory();
ObjectStorageFactory objectStorageFactory = storageConnectionManager.GetDefaultObjectStorageFactory();
M3U8Stream m3U8Stream = new M3U8Stream("D:\\NIP-Research\\nip.m3u8");
SkyscraperContext context = new SkyscraperContext(new TsContext(), dataStorageFactory.CreateDataStorage(), objectStorageFactory.CreateObjectStorage());
context.InitalizeFilterChain();
context.IngestFromStream(m3U8Stream);
/*List<SsdpDevice> ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList(); /*List<SsdpDevice> ssdpDevices = SsdpClient.GetSsdpDevices(1000).ToList();
foreach (SsdpDevice ssdpDevice in ssdpDevices) foreach (SsdpDevice ssdpDevice in ssdpDevices)
{ {
@ -282,7 +273,40 @@ namespace skyscraper5
qadsipc.Run(); qadsipc.Run();
return; return;
} }
}
if (args[0].ToLowerInvariant().Equals("shannon"))
{
if (args.Length != 2)
{
Console.WriteLine("Specify ONE file, please.");
return;
}
FileInfo fi = new FileInfo(args[1]);
if (!fi.Exists)
{
Console.WriteLine("{0} doesn't exist.", fi.FullName);
return;
}
FileStream fileStream = fi.OpenRead();
EntropyCalculatorStream entropyCalculatorStream = new EntropyCalculatorStream();
fileStream.CopyTo(entropyCalculatorStream);
fileStream.Close();
fileStream.Dispose();
Console.WriteLine("Entropy value: {0} ({1}%)", entropyCalculatorStream.Entropy, entropyCalculatorStream.Percentage);
return;
}
if (args[0].ToLowerInvariant().Equals("pcapon"))
{
TogglePcapConfiguration(1);
return;
}
if (args[0].ToLowerInvariant().Equals("pcapoff"))
{
TogglePcapConfiguration(2);
return;
}
}
/*Passing passing = new Passing(); /*Passing passing = new Passing();
if (!passing.Boot()) if (!passing.Boot())
@ -296,12 +320,28 @@ namespace skyscraper5
Console.WriteLine(" or: .\\skyscraper8.exe \"C:\\path\\to\\file.ts\\"); Console.WriteLine(" or: .\\skyscraper8.exe \"C:\\path\\to\\file.ts\\");
Console.WriteLine(" or: .\\skyscraper8.exe \"C:\\path\\to\\my\\folder\\with\\ts\\files\\\" (for batch extraction)"); Console.WriteLine(" or: .\\skyscraper8.exe \"C:\\path\\to\\my\\folder\\with\\ts\\files\\\" (for batch extraction)");
Console.WriteLine(" or: .\\skyscraper8.exe satip IP_ADDRESS DISEQC POLARITY FREQUENCY SYSTEM SYMBOL_RATE (see README file)"); Console.WriteLine(" or: .\\skyscraper8.exe satip IP_ADDRESS DISEQC POLARITY FREQUENCY SYSTEM SYMBOL_RATE (see README file)");
Console.WriteLine(" or: .\\skyscraper8.exe pcapon - to write a configuration file that allows PCAP writing during scraping.");
Console.WriteLine(" or: .\\skyscraper8.exe pcapoff - to write a configuration file that turns off PCAP writing during scraping.");
Console.WriteLine(); Console.WriteLine();
Console.WriteLine("Bonus feature:"); Console.WriteLine("default behaviour is pcap writing on.");
Console.WriteLine();
Console.WriteLine("Bonus features:");
Console.WriteLine(".\\skyscraper8.exe hlsproxy \"C:\\path\\to\\hls\\files\\\" - to pipe a HLS stream from a local directory into VLC."); Console.WriteLine(".\\skyscraper8.exe hlsproxy \"C:\\path\\to\\hls\\files\\\" - to pipe a HLS stream from a local directory into VLC.");
Console.WriteLine(".\\skyscraper8.exe hlsproxy-destructive \"C:\\path\\to\\hls\\files\\\" - to pipe a HLS stream from a local directory into VLC and delete HLS segments afterwards. (be careful!)"); Console.WriteLine(".\\skyscraper8.exe hlsproxy-destructive \"C:\\path\\to\\hls\\files\\\" - to pipe a HLS stream from a local directory into VLC and delete HLS segments afterwards. (be careful!)");
Console.WriteLine(".\\skyscraper8.exe shannon \"C:\\some\\file.bmp\" - calculates the Shannon entropy value for any given file.");
}
private static void TogglePcapConfiguration(int value)
{
PluginManager pluginManager = PluginManager.GetInstance();
if (!pluginManager.Ini.ContainsKey("ip_handler"))
pluginManager.Ini.Add("ip_handler", new IniSection());
pluginManager.Ini["ip_handler"]["type"] = value.ToString();
pluginManager.SaveConfiguration();
Console.WriteLine("Wrote skyscraper5.ini.");
} }
private static void ProcessDirectory(DirectoryInfo di) private static void ProcessDirectory(DirectoryInfo di)
{ {
DataStorage dataStorage = new InMemoryScraperStorage(); DataStorage dataStorage = new InMemoryScraperStorage();

View File

@ -2,7 +2,7 @@
"profiles": { "profiles": {
"skyscraper8": { "skyscraper8": {
"commandName": "Project", "commandName": "Project",
"commandLineArgs": "cscan tcp://172.20.20.203:6969", "commandLineArgs": "\"C:\\devel\\skyscraper8\\skyscraper8\\bin\\Debug\\net8.0\\638938290099956387.ts\"",
"remoteDebugEnabled": false "remoteDebugEnabled": false
}, },
"Container (Dockerfile)": { "Container (Dockerfile)": {

View File

@ -20,6 +20,7 @@ namespace skyscraper8
internal class QuickAndDirtySatIpClient internal class QuickAndDirtySatIpClient
{ {
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private const bool ENABLE_TS_WRITER = true;
public QuickAndDirtySatIpClient(string[] args) public QuickAndDirtySatIpClient(string[] args)
{ {
@ -114,7 +115,7 @@ namespace skyscraper8
objectStorage = new FilesystemStorage(new DirectoryInfo(".")); objectStorage = new FilesystemStorage(new DirectoryInfo("."));
context = new SkyscraperContext(new TsContext(), dataStorage, objectStorage); context = new SkyscraperContext(new TsContext(), dataStorage, objectStorage);
context.EnableTimeout = true; context.EnableTimeout = true;
context.TimeoutSeconds = 10; context.TimeoutSeconds = 60;
context.InitalizeFilterChain(); context.InitalizeFilterChain();
RtspPlayResponse play = rtspClient.GetPlay(setup); RtspPlayResponse play = rtspClient.GetPlay(setup);
@ -150,6 +151,7 @@ namespace skyscraper8
rtspClient.Dispose(); rtspClient.Dispose();
} }
private FileStream fs;
private uint stuffingBytes; private uint stuffingBytes;
private Queue<byte[]> packetQueue; private Queue<byte[]> packetQueue;
private ObjectStorage objectStorage; private ObjectStorage objectStorage;
@ -167,6 +169,8 @@ namespace skyscraper8
{ {
packetQueue.Enqueue(buffer); packetQueue.Enqueue(buffer);
} }
DumpPacket(buffer);
i += 187; i += 187;
} }
else if (data[i] == 0xff) else if (data[i] == 0xff)
@ -176,6 +180,20 @@ namespace skyscraper8
} }
} }
private void DumpPacket(byte[] buffer)
{
if (!ENABLE_TS_WRITER)
return;
if (fs == null)
{
string fname = String.Format("{0}.ts", DateTime.Now.Ticks);
fs = File.OpenWrite(fname);
}
fs.Write(buffer, 0, buffer.Length);
}
private int rtcps; private int rtcps;
private void Setup_OnRtcpPacket(byte[] data, int length) private void Setup_OnRtcpPacket(byte[] data, int length)
{ {

View File

@ -0,0 +1,156 @@
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;
using skyscraper5.Skyscraper.IO;
namespace skyscraper8.Skyscraper
{
internal class BbframeDeencapsulator
{
private bool interruptedGseHem;
private MemoryStream interruptedGseHemBuffer;
private bool interruptedGseHemWantsCrc32;
public void PushPacket(byte[] bbframe)
{
MemoryStream ms = new MemoryStream(bbframe, false);
//BBHeader
byte matype1 = ms.ReadUInt8();
int tsGsField = (matype1 & 0xc0) >> 6;
bool sisMisField = (matype1 & 0x20) != 0;
bool ccmAcmField = (matype1 & 0x10) != 0;
bool issyi = (matype1 & 0x08) != 0;
bool npd = (matype1 & 0x04) != 0;
int ro = (matype1 & 0x03);
byte matype2 = ms.ReadUInt8();
ushort userPacketLength = ms.ReadUInt16BE();
ushort dataFieldLength = ms.ReadUInt16BE();
byte sync = ms.ReadUInt8();
ushort syncd = ms.ReadUInt16BE();
byte crc8 = ms.ReadUInt8();
switch (tsGsField)
{
case 2:
int bytes = dataFieldLength / 8;
if (ms.GetAvailableBytes() < bytes)
return;
HandleGse(ms);
break;
default: //0 = generic packetized, 1 = generic continouus, 2 = gse, 3 = ts
throw new NotImplementedException(String.Format("TS/GS field says 0x{0:X2}", tsGsField));
}
}
private bool isGseSynced;
private int gseNeeded;
private MemoryStream gseNeededBuffer;
private void HandleGse(MemoryStream ms)
{
if (!isGseSynced)
{
ms.Position = 10;
byte syncByte = ms.ReadUInt8();
ms.Position = 10;
if ((syncByte & 0xc0) == 0xc0)
{
isGseSynced = true;
}
else
{
return;
}
}
if (gseNeeded > 0)
{
int blockSize = (int)System.Math.Min(gseNeeded, ms.GetAvailableBytes());
gseNeededBuffer.Write(ms.ReadBytes(blockSize), 0, blockSize);
gseNeeded -= blockSize;
if (gseNeeded == 0)
{
int payloadSize = (int)gseNeededBuffer.Position;
gseNeededBuffer.Position = 0;
byte[] payloadBuffer = gseNeededBuffer.ReadBytes(payloadSize);
}
}
while (ms.GetAvailableBytes() > 2)
{
//GSE-Header
byte byteA = ms.ReadUInt8();
bool startIndicator = (byteA & 0x80) != 0;
bool endIndicator = (byteA & 0x40) != 0;
int labelIndicator = (byteA & 0x30) >> 4;
if (!startIndicator && !endIndicator && labelIndicator == 0)
{
//end of base band frame
return;
}
else
{
byte byteB = ms.ReadUInt8();
int gseLength = byteA & 0x0f;
gseLength <<= 8;
gseLength += byteB;
if (!startIndicator || !endIndicator)
{
byte fragId = ms.ReadUInt8();
gseLength--;
}
if (startIndicator && !endIndicator)
{
ushort totalLength = ms.ReadUInt16BE();
gseLength -= 2;
}
if (startIndicator)
{
ushort protocolType = ms.ReadUInt16BE();
gseLength -= 2;
if (labelIndicator == 0)
{
PhysicalAddress sixByteLabel = new PhysicalAddress(ms.ReadBytes(6));
gseLength -= 6;
}
else if (labelIndicator == 1)
{
byte[] threeByteLabel = ms.ReadBytes(3);
gseLength -= 3;
}
}
if (!startIndicator && endIndicator)
gseLength -= 4;
int startCrc32 = (int)ms.Position;
if (gseLength > ms.GetAvailableBytes())
{
gseNeeded = gseLength;
gseNeededBuffer = new MemoryStream();
gseNeeded -= (int)ms.GetAvailableBytes();
gseNeededBuffer.Write(ms.ReadBytes(ms.GetAvailableBytes()));
return;
}
byte[] payload = ms.ReadBytes(gseLength);
if (!startIndicator && endIndicator)
{
uint crc32 = ms.ReadUInt32BE();
int endCrc32 = (int)ms.Position;
DvbCrc32.ValidateCrc(ms, startCrc32, endCrc32);
}
}
}
}
}
}

View File

@ -6,18 +6,22 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using skyscraper8.Skyscraper;
namespace skyscraper5.src.Skyscraper namespace skyscraper5.src.Skyscraper
{ {
internal class DigitalDevicesBbFrameReader : ITsPacketProcessor internal class DigitalDevicesBbFrameReader : ITsPacketProcessor
{ {
private IGsEventHandler mpeEventHandler; private IGsEventHandler mpeEventHandler;
private BbframeDeencapsulator deencapsulator;
public DigitalDevicesBbFrameReader(IGsEventHandler mpeEventHandler) public DigitalDevicesBbFrameReader(IGsEventHandler mpeEventHandler)
{ {
this.mpeEventHandler = mpeEventHandler; this.mpeEventHandler = mpeEventHandler;
} }
private long packetsRecovered;
private long packetsLost;
private MemoryStream outbuf; private MemoryStream outbuf;
private bool annoncementDone; private bool annoncementDone;
public void PushPacket(TsPacket packet) public void PushPacket(TsPacket packet)
@ -35,7 +39,23 @@ namespace skyscraper5.src.Skyscraper
if (outbuf != null) if (outbuf != null)
{ {
byte[] chi = outbuf.ToArray(); byte[] chi = outbuf.ToArray();
byte[] ipPacket = IpPacketFinder.LookForIpPacket(outbuf.ToArray(), 32); if (deencapsulator == null)
deencapsulator = new BbframeDeencapsulator();
deencapsulator.PushPacket(chi);
/*List<byte[]> ipPackets = IpPacketFinder.LookForIpPackets(outbuf.ToArray());
if (ipPackets != null)
{
foreach (byte[] ipPacket in ipPackets)
{
mpeEventHandler.OnIpDatagram(0x118, ipPacket);
packetsRecovered++;
}
}
else
{
packetsLost++;
}*/
/*byte[] ipPacket = IpPacketFinder.LookForIpPacket(outbuf.ToArray(), 32);
if (ipPacket != null) if (ipPacket != null)
{ {
if (!annoncementDone) if (!annoncementDone)
@ -44,10 +64,15 @@ namespace skyscraper5.src.Skyscraper
annoncementDone = true; annoncementDone = true;
} }
mpeEventHandler.OnIpDatagram(0x0118, ipPacket); mpeEventHandler.OnIpDatagram(0x0118, ipPacket);
packetsRecovered++;
} }
else
{
packetsLost++;
}*/
} }
outbuf = new MemoryStream(); outbuf = new MemoryStream();
outbuf.Write(packets,8, packets[7]); outbuf.Write(packets,9, packets[7] - 1);
} }
else else
{ {

View File

@ -131,7 +131,7 @@ namespace skyscraper8.Skyscraper.IO
segmentNames = newLines; segmentNames = newLines;
return true; return true;
} }
for (int i = 0; i < Math.Min(newLines.Length, segmentNames.Length); i++) for (int i = 0; i < System.Math.Min(newLines.Length, segmentNames.Length); i++)
{ {
if (!segmentNames[i].Equals(newLines[i])) if (!segmentNames[i].Equals(newLines[i]))
{ {

View File

@ -13,7 +13,7 @@ namespace skyscraper5.Skyscraper
{ {
byte[] ipBuffer = new byte[20]; byte[] ipBuffer = new byte[20];
for (int i = 1; i < searchDepth; i++) for (int i = 0; i < searchDepth; i++)
{ {
int v4HeaderEnd = i + 20; int v4HeaderEnd = i + 20;
if (v4HeaderEnd > gsPacket.Length) if (v4HeaderEnd > gsPacket.Length)
@ -39,5 +39,40 @@ namespace skyscraper5.Skyscraper
return null; return null;
} }
public static List<byte[]> LookForIpPackets(byte[] gsPacket)
{
List<byte[]> result = null;
byte[] ipBuffer = new byte[20];
for (int offset = 0; offset < gsPacket.Length; offset++)
{
int v4HeaderEnd = offset + 20;
if (v4HeaderEnd > gsPacket.Length)
break;
if (gsPacket[offset] == 0x45)
{
Array.Copy(gsPacket, offset, ipBuffer, 0, ipBuffer.Length);
InternetHeader ipv4 = new(ipBuffer);
if (!ipv4.ChecksumValid)
continue;
int payloadStart = offset + ipBuffer.Length;
int payloadEnd = offset + ipv4.TotalLength;
if (payloadEnd > gsPacket.Length)
break;
int packetLength = payloadEnd - offset;
byte[] finalPacket = new byte[packetLength];
Array.Copy(gsPacket, offset, finalPacket, 0, packetLength);
if (result == null)
result = new List<byte[]>();
result.Add(finalPacket);
offset = payloadEnd;
}
}
return result;
}
} }
} }

View File

@ -0,0 +1,110 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Math
{
internal class EntropyCalculatorStream : Stream
{
public override void Flush()
{
//no actual writes done, so nothing to flush.
}
public override int Read(byte[] buffer, int offset, int count)
{
//this is a sink, so nothing to read here.
throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
if (offset == 0)
return 0;
//this is a sink, so we can't do actual seeks
throw new NotSupportedException();
}
public override void SetLength(long value)
{
//TODO: allow this later, although I have no idea why one would actually want this.
throw new NotSupportedException();
}
private double _entropy;
private long[] freq;
private long internalPosition;
public override void Write(byte[] buffer, int offset, int count)
{
//Count the bytes
if (freq == null)
freq = new long[byte.MaxValue + 1];
for (int i = 0; i < count; i++)
freq[buffer[i + offset]]++;
internalPosition += count;
//Actually calculate the entropy here.
double newEntropy = 0.0;
for (int i = 0; i < freq.Length; i++)
{
double p_i = (double)freq[i] / (double)internalPosition;
if (p_i > 0)
newEntropy -= p_i * System.Math.Log2(p_i);
}
//Raise events if we feel like it
if (newEntropy != Entropy)
{
double oldEntropy = Entropy;
double oldPercentage = Percentage;
double newPercentage = (newEntropy / 8.0) * 100.0;
if (newEntropy > Entropy)
EntropyRising?.Invoke(oldEntropy, newEntropy, oldPercentage, newPercentage);
else if (newEntropy < Entropy)
EntropyFalling?.Invoke(oldEntropy, newEntropy, oldPercentage, newPercentage);
}
_entropy = newEntropy;
}
public override bool CanRead => false;
public override bool CanSeek => false;
public override bool CanWrite => true;
public override long Length => internalPosition;
public override long Position
{
get
{
return internalPosition;
}
set
{
throw new NotSupportedException();
}
}
public double Entropy
{
get
{
return _entropy;
}
}
public double Percentage
{
get
{
return (Entropy / 8.0) * 100.0;
}
}
public delegate void EntropyCallback(double oldEntropy, double newEntropy, double oldPercentage, double newPercentage);
public event EntropyCallback EntropyRising;
public event EntropyCallback EntropyFalling;
}
}

View File

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Net
{
internal interface IpTrafficHandler : IDisposable
{
void HandlePacket(int pid, byte[] payload);
}
}

View File

@ -0,0 +1,27 @@
using log4net;
using skyscraper5.Skyscraper.Plugins;
using skyscraper8.Skyscraper.Scraper.Storage;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Net
{
[SkyscraperPlugin]
[StorageId(2)]
[StorageName("Packet Discarder")]
internal class NullIpTrafficHandler : IpTrafficHandler
{
public void Dispose()
{
}
public void HandlePacket(int pid, byte[] payload)
{
}
}
}

View File

@ -0,0 +1,46 @@
using log4net;
using skyscraper5.Skyscraper.Net.Pcap;
using skyscraper5.Skyscraper.Plugins;
using skyscraper8.Skyscraper.Scraper.Storage;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace skyscraper8.Skyscraper.Net.Pcap
{
[SkyscraperPlugin]
[StorageId(1)]
[StorageName("PCAP Writer")]
internal class PcapIpTrafficHandler : IpTrafficHandler
{
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
private PcapWriter[] pcapWriters;
public void HandlePacket(int pid, byte[] payload)
{
if (pcapWriters == null)
pcapWriters = new PcapWriter[0x1fff];
if (pcapWriters[pid] == null)
{
string fname = String.Format("{0:X4},{1}.pcap", pid, DateTime.Now.Ticks);
logger.InfoFormat("Opening file for writing: {0}", fname);
FileStream fs = File.OpenWrite(fname);
pcapWriters[pid] = new PcapWriter(fs, TcpdumpNetworkType.RawIp);
}
pcapWriters[pid].WritePacket(payload);
}
public void Dispose()
{
if (pcapWriters != null)
{
for (int i = 0; i < pcapWriters.Length; i++)
{
if (pcapWriters[i] != null)
pcapWriters[i].Dispose();
}
}
}
}
}

View File

@ -17,6 +17,9 @@ using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using skyscraper8.Skyscraper.Net;
using skyscraper8.Skyscraper.Net.Pcap;
using skyscraper8.Skyscraper.Plugins;
using skyscraper8.Skyscraper.Scraper.Storage; using skyscraper8.Skyscraper.Scraper.Storage;
using skyscraper8.Skyscraper.Text; using skyscraper8.Skyscraper.Text;
@ -42,8 +45,11 @@ namespace skyscraper5.Skyscraper.Plugins
_mpeg2ExtensionDescriptors = new ConstructorInfo[256]; _mpeg2ExtensionDescriptors = new ConstructorInfo[256];
ScanAssembly(this.GetType().Assembly); ScanAssembly(this.GetType().Assembly);
FileInfo iniFileInfo = new FileInfo(iniFilename); FileInfo skyscraperMainAssembly = GetSkyscraperMainAssembly();
DirectoryInfo skyscraperHome = skyscraperMainAssembly.Directory;
iniFileInfo = new FileInfo(Path.Combine(skyscraperHome.FullName, iniFilename));
if (iniFileInfo.Exists) if (iniFileInfo.Exists)
{ {
Ini = new Ini(iniFileInfo.FullName); Ini = new Ini(iniFileInfo.FullName);
@ -76,12 +82,13 @@ namespace skyscraper5.Skyscraper.Plugins
else else
{ {
Debug.WriteLine(String.Format("{0} was not found. Create it using the UI!", iniFileInfo.FullName)); Debug.WriteLine(String.Format("{0} was not found. Create it using the UI!", iniFileInfo.FullName));
Ini = new Ini();
} }
FileInfo fi = GetSkyscraperMainAssembly();
if (fi != null) if (skyscraperMainAssembly != null)
{ {
DirectoryInfo directory = fi.Directory; DirectoryInfo directory = skyscraperMainAssembly.Directory;
logger.DebugFormat("Found skyscraper main assembly at: {0}", directory.FullName); logger.DebugFormat("Found skyscraper main assembly at: {0}", directory.FullName);
FileInfo[] fileInfos = directory.GetFiles("skyscraper5.*.dll"); FileInfo[] fileInfos = directory.GetFiles("skyscraper5.*.dll");
foreach (FileInfo fileInfo in fileInfos) foreach (FileInfo fileInfo in fileInfos)
@ -173,6 +180,7 @@ namespace skyscraper5.Skyscraper.Plugins
} }
private FileInfo iniFileInfo;
private const string iniFilename = "skyscraper5.ini"; private const string iniFilename = "skyscraper5.ini";
private static PluginManager _instance; private static PluginManager _instance;
@ -199,6 +207,7 @@ namespace skyscraper5.Skyscraper.Plugins
private Type filesystemProcessorType = typeof(FilesystemProcessorPlugin); private Type filesystemProcessorType = typeof(FilesystemProcessorPlugin);
private Type textDecoderType = typeof(TextDecoder); private Type textDecoderType = typeof(TextDecoder);
private PluginPrioritySorter sorter = new PluginPrioritySorter(); private PluginPrioritySorter sorter = new PluginPrioritySorter();
private Type ipTrafficHandler = typeof(IpTrafficHandler);
private List<IDnsParser> _dnsParsers; private List<IDnsParser> _dnsParsers;
private List<ISkyscraperMpePlugin> _mpePlugins; private List<ISkyscraperMpePlugin> _mpePlugins;
@ -214,6 +223,7 @@ namespace skyscraper5.Skyscraper.Plugins
private ConstructorInfo[] _dsmCcMessages; private ConstructorInfo[] _dsmCcMessages;
private ConstructorInfo[] _mpeg2ExtensionDescriptors; private ConstructorInfo[] _mpeg2ExtensionDescriptors;
private TextDecoder[] _textDecoders; private TextDecoder[] _textDecoders;
private Dictionary<int, Type> _ipTrafficHandles;
private void ScanAssembly(Assembly assembly) private void ScanAssembly(Assembly assembly)
{ {
@ -319,13 +329,36 @@ namespace skyscraper5.Skyscraper.Plugins
HandleTextDecoder(type); HandleTextDecoder(type);
continue; continue;
} }
else if (type.IsAssignableTo(ipTrafficHandler))
{
HandleIpTrafficHandler(type);
continue;
}
throw new NotImplementedException(); throw new NotImplementedException();
} }
_mpePlugins.Sort(sorter); _mpePlugins.Sort(sorter);
} }
private void HandleIpTrafficHandler(Type type)
{
Attribute attribute = type.GetCustomAttribute(typeof(StorageIdAttribute));
if (attribute == null)
throw new PluginsException(String.Format("The type {0} does not have a {1}", type.Name, typeof(StorageIdAttribute)));
if (_ipTrafficHandles == null)
_ipTrafficHandles = new Dictionary<int, Type>();
StorageIdAttribute sia = (StorageIdAttribute)attribute;
if (_ipTrafficHandles.ContainsKey(sia.Id))
{
throw new PluginsException(String.Format("Multiple {0} claim to have ID {1}. {2} <-> {3}", nameof(IpTrafficHandler), sia.Id, _ipTrafficHandles[sia.Id].Name,type.Name));
}
_ipTrafficHandles.Add(sia.Id, type);
}
private void HandleTextDecoder(Type type) private void HandleTextDecoder(Type type)
{ {
List<EncodingTypeIdAttribute> idAttributes = type.GetCustomAttributes<EncodingTypeIdAttribute>().ToList(); List<EncodingTypeIdAttribute> idAttributes = type.GetCustomAttributes<EncodingTypeIdAttribute>().ToList();
@ -701,6 +734,11 @@ namespace skyscraper5.Skyscraper.Plugins
return _dataStorages.AsReadOnly(); return _dataStorages.AsReadOnly();
} }
public ReadOnlyDictionary<int, Type> GetIpTrafficHandlers()
{
return _ipTrafficHandles.AsReadOnly();
}
public void AutoconfigureObject(string categoryName, object targetObject) public void AutoconfigureObject(string categoryName, object targetObject)
{ {
if (Ini == null) if (Ini == null)
@ -743,5 +781,10 @@ namespace skyscraper5.Skyscraper.Plugins
TextDecoder[] saneClone = (TextDecoder[])clone; TextDecoder[] saneClone = (TextDecoder[])clone;
return saneClone; return saneClone;
} }
public void SaveConfiguration()
{
Ini.Export(iniFileInfo);
}
} }
} }

View File

@ -78,6 +78,7 @@ using System.Security.Policy;
using System.Text; using System.Text;
using skyscraper8.Experimentals.NdsSsu; using skyscraper8.Experimentals.NdsSsu;
using skyscraper8.Experimentals.OtvSsu; using skyscraper8.Experimentals.OtvSsu;
using skyscraper8.Skyscraper.Net;
using skyscraper8.Skyscraper.Scraper; using skyscraper8.Skyscraper.Scraper;
using Tsubasa.IO; using Tsubasa.IO;
using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform; using Platform = skyscraper5.Dvb.SystemSoftwareUpdate.Model.Platform;
@ -95,7 +96,7 @@ namespace skyscraper5.Skyscraper.Scraper
{ {
public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true; public const bool ALLOW_STREAM_TYPE_AUTODETECTION = true;
public const bool ALLOW_FFMPEG_FRAMEGRABBER = true; public const bool ALLOW_FFMPEG_FRAMEGRABBER = true;
public const bool ENABLE_MPE_TO_PCAP = true;
private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name); private static readonly ILog logger = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Name);
public TsContext DvbContext { get; } public TsContext DvbContext { get; }
@ -1658,20 +1659,17 @@ namespace skyscraper5.Skyscraper.Scraper
return; return;
} }
private PcapWriter[] pcapWriters;
private IpTrafficHandler ipTrafficHandler;
public void OnIpDatagram(int pid, byte[] payload) public void OnIpDatagram(int pid, byte[] payload)
{ {
if (ENABLE_MPE_TO_PCAP) if (ipTrafficHandler == null)
{ {
if (pcapWriters == null) StorageConnectionManager storageConnectionManager = StorageConnectionManager.GetInstance();
pcapWriters = new PcapWriter[0x1fff]; ipTrafficHandler = storageConnectionManager.GetDefaultIpTrafficHandler();
if (pcapWriters[pid] == null) }
{
FileStream fs = File.OpenWrite(String.Format("{0:X4},{1}.pcap", pid,DateTime.Now.Ticks)); ipTrafficHandler?.HandlePacket(pid, payload);
pcapWriters[pid] = new PcapWriter(fs, TcpdumpNetworkType.RawIp);
}
pcapWriters[pid].WritePacket(payload);
}
int ipVersion = (payload[0] & 0xf0) >> 4; int ipVersion = (payload[0] & 0xf0) >> 4;
if (ipVersion == 4) if (ipVersion == 4)
@ -2039,19 +2037,12 @@ namespace skyscraper5.Skyscraper.Scraper
if (TcpProxyEnabled) if (TcpProxyEnabled)
TcpProxyEnabled = false; TcpProxyEnabled = false;
if (ENABLE_MPE_TO_PCAP) if (ipTrafficHandler != null)
{ {
if (pcapWriters != null) ipTrafficHandler.Dispose();
{
for (int i = 0; i < pcapWriters.Length; i++)
{
if (pcapWriters[i] != null)
pcapWriters[i].Dispose();
}
}
} }
if (DvbContext.TcpProxyEnabled) if (DvbContext.TcpProxyEnabled)
{ {

View File

@ -8,7 +8,10 @@ using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using skyscraper5.Skyscraper.Net;
using skyscraper5.Skyscraper.Scraper.Storage; using skyscraper5.Skyscraper.Scraper.Storage;
using skyscraper8.Skyscraper.Net;
using skyscraper8.Skyscraper.Net.Pcap;
namespace skyscraper8.Skyscraper.Scraper.Storage namespace skyscraper8.Skyscraper.Scraper.Storage
{ {
@ -139,5 +142,50 @@ namespace skyscraper8.Skyscraper.Scraper.Storage
{ {
return plugins.GetDataStorages(); return plugins.GetDataStorages();
} }
private bool IsIpTafficHandlerConfigured()
{
if (ini == null)
return false;
if (!ini.ContainsKey("ip_handler"))
return false;
if (!ini["ip_handler"].ContainsKey("type"))
return false;
return true;
}
internal IpTrafficHandler GetDefaultIpTrafficHandler()
{
Type targetType;
if (IsIpTafficHandlerConfigured())
{
ReadOnlyDictionary<int, Type> handlers = plugins.GetIpTrafficHandlers();
int type = Int32.Parse(ini["ip_handler"]["type"]);
if (!handlers.ContainsKey(type))
{
logger.WarnFormat("The IP traffic handler with ID {0} was not found. I'm gonna assume you want the pcap files.", type);
targetType = typeof(PcapIpTrafficHandler);
}
else
{
targetType = handlers[type];
}
}
else
{
logger.WarnFormat("You didn't call \"pcapon\" or \"pcapoff\" before. I'm gonna assume you want the pcap files.");
targetType = typeof(PcapIpTrafficHandler);
}
ConstructorInfo constructorInfo = targetType.GetConstructor(new Type[] { });
if (constructorInfo == null)
{
throw new ScraperStorageException(String.Format("The type {0} doesn't contain a parameterless constructor.", targetType.Name));
}
object invoke = constructorInfo.Invoke(new object[] { });
return (IpTrafficHandler) invoke;
}
} }
} }