using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Sockets; using System.Runtime.InteropServices; using System.Text; using System.Threading; using System.Threading.Tasks; using skyscraper5.IO.StreamReader; using skyscraper5.Skyscraper.IO.RemoteStreamReader; using skyscraper5.Skyscraper.Net.Sockets; using skyscraper5.src.Skyscraper.IO.PortableExecutables; namespace skyscraper5.Skyscraper.IO.CrazycatStreamReader { internal class RemoteStreamReaderServer { private bool _logRequests; private int _listenPort; private IPAddress _listenAddress; private bool clientConnected; private IStreamReader localStreamReader; private Thread clientThread; private Dictionary dllVersionInfo; public bool IsRunning { get; private set; } public int ListenPort { get => _listenPort; set { if (IsRunning) throw new InvalidOperationException(); _listenPort = value; } } public IPAddress ListenAddress { get => _listenAddress; set { if (IsRunning) throw new InvalidOperationException(); _listenAddress = value; } } public bool LogRequests { get => _logRequests; set => _logRequests = value; } public void Run() { if (localStreamReader == null) { localStreamReader = LocalStreamReader.GetInstance(); if (!localStreamReader.CheckForDVB()) { Console.WriteLine("No tuners present, quitting."); return; } } if (ListenAddress == null) ListenAddress = IPAddress.Any; IPEndPoint listenEndPoint = new IPEndPoint(ListenAddress, ListenPort); TcpListener tcpListener = new TcpListener(listenEndPoint); tcpListener.Start(); Console.WriteLine("Listening on {0}", tcpListener.LocalEndpoint); while (true) { TcpClient acceptTcpClient = tcpListener.AcceptTcpClient(); if (clientConnected) { Console.WriteLine("Rejected connection from {0}. I'm busy.", acceptTcpClient.Client.RemoteEndPoint); NetworkStream blockoffStream = acceptTcpClient.GetStream(); blockoffStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.SERVER_BUSY_WITH_ANOTHER_CLIENT); blockoffStream.Flush(); acceptTcpClient.Close(); } else { Console.WriteLine("Accepted connection from {0}", acceptTcpClient.Client.RemoteEndPoint); clientConnected = true; clientThread = new Thread(ClientThreadMethod); clientThread.Name = String.Format("RemoteStreamReader Client @ {0}", acceptTcpClient.Client.RemoteEndPoint); clientThread.Start(acceptTcpClient); } } } private void ClientThreadMethod(object o) { TcpClient tcpClient = (TcpClient)o; NetworkStream tcpStream = tcpClient.GetStream(); tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.SERVER_READY); tcpStream.Flush(); bool breakout = false; while (!breakout) { uint opcode; try { opcode = tcpStream.ReadUInt32BE(); if (LogRequests) Console.WriteLine("Request from {0}: {1}", tcpClient.Client.RemoteEndPoint, (RemoteStreamReaderConstants)opcode); } catch (Exception e) { Console.WriteLine("Lost connection to {0}: {1}", tcpClient.Client.RemoteEndPoint, e); clientConnected = false; return; } switch (opcode) { case (uint)RemoteStreamReaderConstants.REQUEST_NOOP: tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_HOSTNAME: tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); tcpStream.WriteUTF8(Environment.MachineName); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_USERNAME: tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); tcpStream.WriteUTF8(Environment.UserName); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_DATE_TIME: tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); tcpStream.WriteInt64BE(DateTime.Now.Ticks); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_DISPOSE: tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); tcpStream.Flush(); breakout = true; break; case (uint)RemoteStreamReaderConstants.REQUEST_CHECK_FOR_DVB_EX_EX: bool checkForDvbExEx = localStreamReader.CheckForDVBExEx((index, name, type) => { tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.ENUMERATE_CHECK_FOR_DVB_EX_EX); tcpStream.WriteInt32BE(index); tcpStream.WriteUTF8(name); tcpStream.WriteInt32BE((int)type); }); if (checkForDvbExEx) tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); else tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_START_DVB_EX: int readIndex = tcpStream.ReadInt32BE(); bool startDvbExResult = localStreamReader.StartDvbEx(readIndex); tcpStream.WriteUInt32BE(startDvbExResult ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_STOP_DVB: bool stopDvbResult = localStreamReader.StopDVB(); tcpStream.WriteUInt32BE(stopDvbResult ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_GET_TUNER_TYPE: STD_TYPE m = (STD_TYPE)(-1); bool getTunerTypeResult = localStreamReader.GetTunerType(ref m); tcpStream.WriteUInt32BE(getTunerTypeResult ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (getTunerTypeResult) { tcpStream.WriteInt32BE((int)m); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_GET_CAPS: Caps caps = localStreamReader.GetCaps(); tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); tcpStream.WriteInt32BE((int)caps); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_SEND_DISEQC: uint diseqcType = tcpStream.ReadUInt32BE(); byte recvMe = tcpStream.ReadUInt8(); DiSEqC_Opcode diSEqCOpcode = (DiSEqC_Opcode)recvMe; bool sendDiSEqC = localStreamReader.SendDiSEqC(diseqcType, diSEqCOpcode); tcpStream.WriteUInt32BE(sendDiSEqC ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_RF_SCAN: int rfScanFreq = tcpStream.ReadInt32BE(); int rfScanPol = tcpStream.ReadInt32BE(); int rfScanLof1 = tcpStream.ReadInt32BE(); int rfScanLof2 = tcpStream.ReadInt32BE(); int rfScanLofSw = tcpStream.ReadInt32BE(); double rfScanRfLevel = Double.NaN; bool rfScan = localStreamReader.RFScan(rfScanFreq, rfScanPol, rfScanLof1, rfScanLof2, rfScanLofSw, out rfScanRfLevel); tcpStream.WriteUInt32BE(rfScan ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.WriteDouble(rfScanRfLevel); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_SET_CHANNEL: int setChannelFreq = tcpStream.ReadInt32BE(); int setChannelSymbRate = tcpStream.ReadInt32BE(); int setChannelPol = tcpStream.ReadInt32BE(); VITERBIRATE_TYPE setChannelFec = (VITERBIRATE_TYPE)tcpStream.ReadInt32BE(); int setChannelLof1 = tcpStream.ReadInt32BE(); int setChannelLof2 = tcpStream.ReadInt32BE(); int setChannelLofSw = tcpStream.ReadInt32BE(); bool channel = localStreamReader.SetChannel(setChannelFreq, setChannelSymbRate, setChannelPol, setChannelFec, setChannelLof1, setChannelLof2, setChannelLofSw); tcpStream.WriteUInt32BE(channel ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_SIGNAL_INFO: SearchResult signalInfoSearchResult = default; bool signalInfo = localStreamReader.SignalInfo(ref signalInfoSearchResult); tcpStream.WriteUInt32BE(signalInfo ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (signalInfo) { int sizeOf = Marshal.SizeOf(typeof(SearchResult)); IntPtr allocHGlobal = Marshal.AllocHGlobal(sizeOf); Marshal.StructureToPtr(signalInfoSearchResult, allocHGlobal, true); byte[] bytes = new byte[sizeOf]; Marshal.Copy(allocHGlobal, bytes, 0, sizeOf); Marshal.FreeHGlobal(allocHGlobal); tcpStream.Write(bytes, 0, sizeOf); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_SET_FILTER: int setFilterPid = tcpStream.ReadInt32BE(); int setFilterSize = tcpStream.ReadInt32BE(); FilterServer filterServer = new FilterServer(); IntPtr setFilterNumber = default; bool filter = localStreamReader.SetFilter(setFilterPid, filterServer.DvbCallback, 0x02, setFilterSize, ref setFilterNumber); tcpStream.WriteUInt32BE(filter ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (filter) { if (filterServers == null) filterServers = new Dictionary(); filterServers.Add(setFilterNumber, filterServer); filterServer.ListenIp = ListenAddress; filterServer.TcpListener = new TcpListener(filterServer.ListenIp, 0); filterServer.TcpListener.Start(); filterServer.Thread = new Thread(filterServer.Run); string filterName = String.Format("Filter for PID {0} @{1}", setFilterPid, filterServer.TcpListener.Server.LocalEndPoint); filterServer.Thread.Name = filterName; filterServer.Thread.Start(); tcpStream.WriteIntPtr(setFilterNumber); tcpStream.WriteIPEndPoint((IPEndPoint)filterServer.TcpListener.LocalEndpoint); Console.WriteLine(filterName); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_DEL_FILTER: IntPtr delFilterNumber = tcpStream.ReadIntPtr(); bool delFilter = localStreamReader.DelFilter(delFilterNumber); tcpStream.WriteUInt32BE(delFilter ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if(delFilter) { FilterServer server = filterServers[delFilterNumber]; lock (server.clients) { server.clients.ForEach(x => x.Close()); } server.Dispose(); server.Thread.Interrupt(); filterServers.Remove(delFilterNumber); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_BL_SCAN2: int blscan2FreqStart = tcpStream.ReadInt32BE(); int blscan2FreqStop = tcpStream.ReadInt32BE(); int blscan2Pol = tcpStream.ReadInt32BE(); int blscan2Lof1 = tcpStream.ReadInt32BE(); int blscan2Lof2 = tcpStream.ReadInt32BE(); int blscan2LofSw = tcpStream.ReadInt32BE(); IntPtr blscan2SearchResults = Marshal.AllocHGlobal(65536); int blscan2TpNum = -1; BlScanCallback blScanCallback = (ref SearchResult result) => { int sizeOf = Marshal.SizeOf(typeof(SearchResult)); IntPtr allocHGlobal = Marshal.AllocHGlobal(sizeOf); Marshal.StructureToPtr(result, allocHGlobal, true); byte[] buffer = new byte[sizeOf]; Marshal.Copy(allocHGlobal, buffer, 0, sizeOf); tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.ENUMERATE_BL_SCAN_2); tcpStream.Write(buffer, 0, sizeOf); Marshal.FreeHGlobal(allocHGlobal); }; tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_WILL_TAKE_SOME_TIME); bool blScan2 = localStreamReader.BLScan2(blscan2FreqStart, blscan2FreqStop, blscan2Pol, blscan2Lof1, blscan2Lof2, blscan2LofSw, blscan2SearchResults, ref blscan2TpNum, blScanCallback); tcpStream.WriteUInt32BE(blScan2 ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (blScan2) { tcpStream.WriteInt32BE(blscan2TpNum); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_CHECK_FOR_DVB: bool checkForDvb = localStreamReader.CheckForDVB(); if (checkForDvb) tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); else tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_GET_MAC: byte[] buffer = new byte[6]; bool mac = localStreamReader.GetMAC(buffer); if (mac) { tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); tcpStream.Write(buffer, 0, 6); } else { tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_FAILED); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_AIR_SCAN: int freqStart = tcpStream.ReadInt32BE(); int freqEnd = tcpStream.ReadInt32BE(); uint step = tcpStream.ReadUInt32BE(); uint bandwidth = tcpStream.ReadUInt32BE(); int std = tcpStream.ReadInt32BE(); IntPtr airScanSearchResults = Marshal.AllocHGlobal(65536); int airScanTpNum = -1; AirScanCallback airScanCallback = (ref SearchResult2 result) => { int sizeOf = Marshal.SizeOf(typeof(SearchResult2)); IntPtr allocHGlobal = Marshal.AllocHGlobal(sizeOf); Marshal.StructureToPtr(result, allocHGlobal, true); byte[] buffer = new byte[sizeOf]; Marshal.Copy(allocHGlobal, buffer, 0, sizeOf); tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.ENUMERATE_AIR_SCAN); tcpStream.Write(buffer, 0, sizeOf); Marshal.FreeHGlobal(allocHGlobal); }; tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_WILL_TAKE_SOME_TIME); bool airscan = localStreamReader.AirScan(freqStart, freqEnd, step, bandwidth, std, airScanSearchResults, ref airScanTpNum, airScanCallback); tcpStream.WriteUInt32BE(airscan ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (airscan) { tcpStream.WriteInt32BE(airScanTpNum); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_SET_CHANNEL_2: uint freq = tcpStream.ReadUInt32BE(); uint bandwidth2 = tcpStream.ReadUInt32BE(); bool channel2 = localStreamReader.SetChannel2(freq, bandwidth2); tcpStream.WriteUInt32BE(channel2 ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_SIGNAL_INFO_2: SearchResult2 signalInfoSearchResult2 = default; bool signalInfo2 = localStreamReader.SignalInfo2(ref signalInfoSearchResult2); tcpStream.WriteUInt32BE(signalInfo2 ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (signalInfo2) { int sizeOf = Marshal.SizeOf(typeof(SearchResult2)); IntPtr allocHGlobal = Marshal.AllocHGlobal(sizeOf); Marshal.StructureToPtr(signalInfoSearchResult2, allocHGlobal, true); byte[] bytes = new byte[sizeOf]; Marshal.Copy(allocHGlobal, bytes, 0, sizeOf); Marshal.FreeHGlobal(allocHGlobal); tcpStream.Write(bytes, 0, sizeOf); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_MIS_SEL: bool bEnable = tcpStream.ReadBoolean(); byte misFilter = tcpStream.ReadUInt8(); byte misFilterMask = tcpStream.ReadUInt8(); bool misSel = localStreamReader.MISSel(bEnable, misFilter, misFilterMask); tcpStream.WriteUInt32BE(misSel ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_PLS_SEL: byte plsMode = tcpStream.ReadUInt8(); uint code = tcpStream.ReadUInt32BE(); bool plsSel = localStreamReader.PLSSel(plsMode, code); tcpStream.WriteUInt32BE(plsSel ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_BL_SCAN_EX: freq = tcpStream.ReadUInt32BE(); int freq_range = tcpStream.ReadInt32BE(); int pol = tcpStream.ReadInt32BE(); int lof1 = tcpStream.ReadInt32BE(); int lof2 = tcpStream.ReadInt32BE(); int lofsw = tcpStream.ReadInt32BE(); int minsr = tcpStream.ReadInt32BE(); std = tcpStream.ReadInt32BE(); SearchResult result = new SearchResult(); bool blScanEx = localStreamReader.BLScanEx((int)freq, freq_range, pol, lof1, lof2, lofsw, minsr, (STD_TYPE)std, ref result); tcpStream.WriteUInt32BE(blScanEx ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (blScanEx) { int sizeOfEx = Marshal.SizeOf(typeof(SearchResult)); IntPtr allocHGlobalEx = Marshal.AllocHGlobal(sizeOfEx); Marshal.StructureToPtr(result, allocHGlobalEx, true); byte[] bufferEx = new byte[sizeOfEx]; Marshal.Copy(allocHGlobalEx, bufferEx, 0, sizeOfEx); tcpStream.Write(bufferEx, 0, sizeOfEx); Marshal.FreeHGlobal(allocHGlobalEx); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_MOD_SEL: S2Mode s2mode = new S2Mode(); s2mode.frameLen = tcpStream.ReadInt32BE(); s2mode.modcode = (S2MODCODE)tcpStream.ReadInt32BE(); s2mode.pilot = tcpStream.ReadBoolean(); uint num = tcpStream.ReadUInt32BE(); bool modSel = localStreamReader.ModSel(ref s2mode, num); tcpStream.WriteUInt32BE(modSel ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (modSel) { tcpStream.WriteInt32BE(s2mode.frameLen); tcpStream.WriteInt32BE((int)s2mode.modcode); tcpStream.WriteBoolean(s2mode.pilot); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_IQ_SCAN: uint input = tcpStream.ReadUInt32BE(); sbyte[] pIQ; num = tcpStream.ReadUInt32BE(); pIQ = new sbyte[num * 2]; bool iqScan = localStreamReader.IQScan(input, pIQ, num); tcpStream.WriteUInt32BE(iqScan ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (iqScan) { byte[] pIQunsigned = new byte[num * 2]; for (long i = 0; i < num * 2; i++) { pIQunsigned[i] = (byte)pIQ[i]; } tcpStream.WriteByteArray(pIQunsigned); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_GET_SIGNAL_EX_EX: bool pPresent = false; bool pLock = false; int pRFLevel = int.MinValue; float pSNR = float.NaN; float pBER = float.NaN; bool getSignalExEx = localStreamReader.GetSignalExEx(ref pPresent, ref pLock, ref pRFLevel, ref pSNR, ref pBER); tcpStream.WriteUInt32BE(getSignalExEx ? (uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL : (uint)RemoteStreamReaderConstants.COMMAND_FAILED); if (getSignalExEx) { tcpStream.WriteBoolean(pPresent); tcpStream.WriteBoolean(pPresent); tcpStream.WriteInt32BE(pRFLevel); tcpStream.WriteFloat(pSNR); tcpStream.WriteFloat(pBER); } tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_SKYSCRAPER_ENGINE_NAME: tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); tcpStream.WriteUTF8(localStreamReader.GetEngineName()); tcpStream.Flush(); break; case (uint)RemoteStreamReaderConstants.REQUEST_SKYSCRAPER_ENGINE_VERSION: tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_SUCCESSFUL); tcpStream.WriteVersion(localStreamReader.GetEngineVersion()); tcpStream.Flush(); break; default: Console.WriteLine("Recieved unknown command {0:X8}", opcode); tcpStream.WriteUInt32BE((uint)RemoteStreamReaderConstants.COMMAND_NOT_UNDERSTOOD); tcpStream.Flush(); break; } } tcpStream.Close(); tcpClient.Close(); clientConnected = false; } private Dictionary filterServers; class FilterServer : IDisposable { public FilterServer() { clients = new List(); } private byte[] buffer; public void DvbCallback(IntPtr pointer, int length) { if (buffer == null) buffer = new byte[188]; Marshal.Copy(pointer, buffer, 0, 188); lock (clients) { foreach (TcpClientWrapped tcpClient in clients) { try { tcpClient.DropPacket(buffer, 0, 188); } catch (Exception e) { if (tcpClient.wrapped.Client != null) { Console.WriteLine("Lost filter client: {0}", tcpClient.wrapped.Client.RemoteEndPoint); } clients.Remove(tcpClient); break; } } } } public IPAddress ListenIp { get; set; } public Thread Thread { get; set; } public TcpListener TcpListener { get; set; } public List clients; public class TcpClientWrapped : IDisposable { public TcpClientWrapped(TcpClient client) { this.wrapped = client; this.bufferedStream = new BufferedStream(wrapped.GetStream(), 96256); } internal TcpClient wrapped; internal BufferedStream bufferedStream; public void Dispose() { wrapped?.Dispose(); bufferedStream?.Dispose(); } public void Close() { try { bufferedStream?.Close(); wrapped?.Close(); } catch (IOException ioe) { Console.WriteLine("Failed to properly close TCPClient"); } } internal void DropPacket(byte[] buffer, int offset, int length) { bufferedStream?.Write(buffer, offset, length); } } public void Run() { while (!disposed) { try { TcpClient acceptTcpClient = TcpListener.AcceptTcpClient(); Console.WriteLine("Accepted Filter client {0}", acceptTcpClient.Client.RemoteEndPoint); lock (clients) { clients.Add(new TcpClientWrapped(acceptTcpClient)); } } catch (Exception e) { break; } } if (!disposed) Dispose(); } private bool disposed; public void Dispose() { TcpListener.Stop(); disposed = true; } } } }