public PcapStreamReader(System.IO.Stream pcapStream, int packetQueueSize, StreamReadCompletedCallback streamReadCompletedCallback, bool startBackgroundWorkers, long streamMaxLength, int readTimeoutMilliseconds) { this.pcapStream = pcapStream; this.streamLength = streamMaxLength; this.readBytesEstimate = 0; this.readTimeoutMilliseconds = readTimeoutMilliseconds; this.packetQueueSize = packetQueueSize; this.streamReadCompletedCallback = streamReadCompletedCallback; //TODO: Figure out if it is a libpcap or pcapNG stream... this.pcapParser = PcapParserFactory.CreatePcapParser(this);// new PcapParser(pcapStream, this.AbortReadingPcapStream); /* * byte[] buffer4=new byte[4];//32 bits is suitable * byte[] buffer2=new byte[2];//16 bits is sometimes needed * uint wiresharkMagicNumber=0xa1b2c3d4; * * //Section Header Block (mandatory) * * this.pcapStream.Read(buffer4, 0, 4); * * if(wiresharkMagicNumber==this.ToUInt32(buffer4, false)) * this.littleEndian=false; * else if(wiresharkMagicNumber==this.ToUInt32(buffer4, true)) * this.littleEndian=true; * else * throw new System.IO.InvalidDataException("The stream is not a PCAP file. Magic number is "+this.ToUInt32(buffer4, false).ToString("X2")+" or "+this.ToUInt32(buffer4, true).ToString("X2")+" but should be "+wiresharkMagicNumber.ToString("X2")+"."); * * * this.pcapStream.Read(buffer2, 0, 2); * this.majorVersionNumber=ToUInt16(buffer2, this.littleEndian); * * this.pcapStream.Read(buffer2, 0, 2); * this.minorVersionNumber=ToUInt16(buffer2, this.littleEndian); * * this.pcapStream.Read(buffer4, 0, 4); * this.timezoneOffsetSeconds=(int)ToUInt32(buffer4, this.littleEndian); * * this.pcapStream.Read(buffer4, 0, 4); * * this.pcapStream.Read(buffer4, 0, 4); * this.maximumPacketSize=ToUInt32(buffer4, this.littleEndian); * * this.pcapStream.Read(buffer4, 0, 4); //offset = 20 = 0x14 * this.dataLinkType=(DataLinkType)ToUInt32(buffer4, this.littleEndian); */ //this.pcapHeaderSize = this.pcapStream.Position; this.backgroundStreamReader = new System.ComponentModel.BackgroundWorker(); this.backgroundStreamReader.WorkerSupportsCancellation = true; this.packetQueue = new Queue <PcapFrame>(this.packetQueueSize); this.enqueuedByteCount = 0; this.dequeuedByteCount = 0; if (startBackgroundWorkers) { this.StartBackgroundWorkers(); } }
public void Dispose() { //throw new Exception("The method or operation is not implemented."); if (this.backgroundStreamReaderCanceller != null) { try { this.backgroundStreamReaderCanceller.Cancel(); this.backgroundStreamReaderCanceller.Dispose(); } catch (ObjectDisposedException) { } } if (this.pcapStream != null) { try { this.pcapStream.Close(); } catch { this.pcapStream.Dispose(); } finally { this.pcapStream = null; } /* * if(this.pcapStream.CanWrite) * this.pcapStream.Flush(); */ } this.streamReadCompletedCallback = null; }
public IEnumerable <PcapFrame> PacketEnumerator(EmptyDelegate waitFunction, StreamReadCompletedCallback captureCompleteCallback) { const int MIN_TAKE_TIMEOUT = 100; int timeoutMilliSecs = MIN_TAKE_TIMEOUT; var cancellationToken = this.backgroundStreamReaderCanceller.Token; //int maxSleepMS = (int)Math.Sqrt(2.0 * this.readTimeoutMilliseconds);//200*200/2 = 20.000 = 20 seconds //maxSleepMS += timeoutMilliSecs;//to make sure BlockingRead timeouts before int maxSleepMS = (int)Math.Sqrt(2.0 * this.readTimeoutMilliseconds + timeoutMilliSecs * timeoutMilliSecs); while (!cancellationToken.IsCancellationRequested && (/*this.backgroundStreamReader.IsBusy ||*/ !this.EndOfStream() || this.packetQueue.Count > 0)) { /* * if(this.packetQueue.Count>0) { * sleepMilliSecs = 20; * PcapFrame packet; * lock(this.packetQueue) { * packet=this.packetQueue.Dequeue(); * } * this.dequeuedByteCount+=packet.Data.Length; * if (this.packetQueue.Count < this.packetQueueMaxSize / 2) * this.packetQueueHasRoomEvent.Set(); * yield return packet; * } * else { * if (sleepMilliSecs++ > maxSleepMS) {//200*200/2 = 20.000 = 20 seconds * //abort the reading, something has gone wrong... * yield break; * } * if (waitFunction != null) * waitFunction(); * else { * //This works in .NET 4.5 and .NET Standard: * System.Threading.Tasks.Task.Delay(sleepMilliSecs).Wait(); * * //This works in .NET 4.0 * //System.Threading.Thread.Sleep(sleepMilliSecs); * * } * } */ if (this.packetQueue.TryTake(out PcapFrame packet, timeoutMilliSecs, cancellationToken)) { timeoutMilliSecs = MIN_TAKE_TIMEOUT; this.dequeuedByteCount += packet.Data.Length; yield return(packet); } else { if (timeoutMilliSecs++ > maxSleepMS) //20 seconds of total waiting time since last Take/Dequeue //abort the reading, something has gone wrong... { yield break; } waitFunction?.Invoke(); } } //yield break; }
public IEnumerable <PcapFrame> PacketEnumerator(EmptyDelegate waitFunction, StreamReadCompletedCallback captureCompleteCallback) { int sleepMilliSecs = 20; var cancellationToken = this.backgroundStreamReaderCanceller.Token; int maxSleepMS = (int)Math.Sqrt(2.0 * this.readTimeoutMilliseconds); //200*200/2 = 20.000 = 20 seconds maxSleepMS += sleepMilliSecs; //to make sure BlockingRead timeouts before while (!cancellationToken.IsCancellationRequested && (/*this.backgroundStreamReader.IsBusy ||*/ !this.EndOfStream() || this.packetQueue.Count > 0)) { if (this.packetQueue.Count > 0) { sleepMilliSecs = 20; PcapFrame packet; lock (this.packetQueue) { packet = this.packetQueue.Dequeue(); } this.dequeuedByteCount += packet.Data.Length; if (this.packetQueue.Count < this.packetQueueMaxSize / 2) { this.packetQueueHasRoomEvent.Set(); } yield return(packet); } else { if (sleepMilliSecs++ > maxSleepMS) //200*200/2 = 20.000 = 20 seconds //abort the reading, something has gone wrong... { yield break; } if (waitFunction != null) { waitFunction(); } else { //This works in .NET 4.5 and .NET Standard: System.Threading.Tasks.Task.Delay(sleepMilliSecs).Wait(); //This works in .NET 4.0 //System.Threading.Thread.Sleep(sleepMilliSecs); } } } //yield break; }
public IEnumerable <PcapFrame> PacketEnumerator(EmptyDelegate waitFunction, StreamReadCompletedCallback captureCompleteCallback) { int sleepMilliSecs = 20; int maxSleepMS = (int)Math.Sqrt(2.0 * this.readTimeoutMilliseconds); //200*200/2 = 20.000 = 20 seconds maxSleepMS += sleepMilliSecs; //to make sure BlockingRead timeouts before while (!this.backgroundStreamReader.CancellationPending && (this.backgroundStreamReader.IsBusy || !this.EndOfStream() || this.packetQueue.Count > 0)) { if (this.packetQueue.Count > 0) { sleepMilliSecs = 20; PcapFrame packet; lock (this.packetQueue) { packet = this.packetQueue.Dequeue(); } this.dequeuedByteCount += packet.Data.Length; yield return(packet); } else { if (sleepMilliSecs++ > maxSleepMS) //200*200/2 = 20.000 = 20 seconds //abort the reading, something has gone wrong... { yield break; } if (waitFunction != null) { waitFunction(); } else { System.Threading.Thread.Sleep(sleepMilliSecs); } } } //yield break; }
public PcapStreamReader(System.IO.Stream pcapStream, int packetQueueSize, StreamReadCompletedCallback streamReadCompletedCallback, bool startBackgroundWorkers, long streamMaxLength) : this(pcapStream, packetQueueSize, streamReadCompletedCallback, startBackgroundWorkers, streamMaxLength, /*20000*/ pcapStream.ReadTimeout) { }
public PcapStreamReader(System.Net.Sockets.NetworkStream pcapStream, int packetQueueSize, StreamReadCompletedCallback streamReadCompletedCallback, bool startBackgroundWorkers, long streamMaxLength) : this(pcapStream, packetQueueSize, streamReadCompletedCallback, startBackgroundWorkers, long.MaxValue, pcapStream.ReadTimeout) { }
public PcapStreamReader(System.IO.FileStream pcapStream, int packetQueueSize, StreamReadCompletedCallback streamReadCompletedCallback, bool startBackgroundWorkers, long streamMaxLength) : this(pcapStream, packetQueueSize, streamReadCompletedCallback, startBackgroundWorkers, long.MaxValue, 20000) { }
public PcapStreamReader(System.IO.Stream pcapStream, int packetQueueSize, StreamReadCompletedCallback streamReadCompletedCallback) : this(pcapStream, packetQueueSize, streamReadCompletedCallback, true) { }
public PcapStreamReader(System.IO.Stream pcapStream, int packetQueueSize, StreamReadCompletedCallback streamReadCompletedCallback, bool startBackgroundWorkers, long streamMaxLength, int readTimeoutMilliseconds) { this.pcapStream = pcapStream; this.streamLength = streamMaxLength; this.readBytesEstimate = 0; this.readTimeoutMilliseconds = readTimeoutMilliseconds; this.packetQueueMaxSize = packetQueueSize; this.streamReadCompletedCallback = streamReadCompletedCallback; //TODO: Figure out if it is a libpcap or pcapNG stream... this.pcapParser = PcapParserFactory.CreatePcapParser(this);// new PcapParser(pcapStream, this.AbortReadingPcapStream); /* * byte[] buffer4=new byte[4];//32 bits is suitable * byte[] buffer2=new byte[2];//16 bits is sometimes needed * uint wiresharkMagicNumber=0xa1b2c3d4; * * //Section Header Block (mandatory) * * this.pcapStream.Read(buffer4, 0, 4); * * if(wiresharkMagicNumber==this.ToUInt32(buffer4, false)) * this.littleEndian=false; * else if(wiresharkMagicNumber==this.ToUInt32(buffer4, true)) * this.littleEndian=true; * else * throw new System.IO.InvalidDataException("The stream is not a PCAP file. Magic number is "+this.ToUInt32(buffer4, false).ToString("X2")+" or "+this.ToUInt32(buffer4, true).ToString("X2")+" but should be "+wiresharkMagicNumber.ToString("X2")+"."); * * * this.pcapStream.Read(buffer2, 0, 2); * this.majorVersionNumber=ToUInt16(buffer2, this.littleEndian); * * this.pcapStream.Read(buffer2, 0, 2); * this.minorVersionNumber=ToUInt16(buffer2, this.littleEndian); * * this.pcapStream.Read(buffer4, 0, 4); * this.timezoneOffsetSeconds=(int)ToUInt32(buffer4, this.littleEndian); * * this.pcapStream.Read(buffer4, 0, 4); * * this.pcapStream.Read(buffer4, 0, 4); * this.maximumPacketSize=ToUInt32(buffer4, this.littleEndian); * * this.pcapStream.Read(buffer4, 0, 4); //offset = 20 = 0x14 * this.dataLinkType=(DataLinkType)ToUInt32(buffer4, this.littleEndian); */ //this.pcapHeaderSize = this.pcapStream.Position; //this.backgroundStreamReader = new System.Threading.Tasks.Task() //this.backgroundStreamReader=new System.ComponentModel.BackgroundWorker(); //this.backgroundStreamReader.WorkerSupportsCancellation = true; this.packetQueue = new Queue <PcapFrame>(this.packetQueueMaxSize); this.packetQueueHasRoomEvent = new System.Threading.AutoResetEvent(true); this.enqueuedByteCount = 0; this.dequeuedByteCount = 0; this.backgroundStreamReaderCanceller = new System.Threading.CancellationTokenSource(); System.Threading.CancellationToken cancellationToken = backgroundStreamReaderCanceller.Token; this.readAction = new Action(() => { DateTime firstFrameTimestamp = DateTime.MinValue; DateTime lastFrameTimestamp = DateTime.MinValue; int framesCount = 0; try { //int sleepMilliSecs = 20; while (!cancellationToken.IsCancellationRequested && !this.EndOfStream()) { if (this.packetQueue.Count < this.packetQueueMaxSize) { PcapFrame packet = this.pcapParser.ReadPcapPacketBlocking(); if (firstFrameTimestamp == DateTime.MinValue) { firstFrameTimestamp = packet.Timestamp; } lastFrameTimestamp = packet.Timestamp; framesCount++; lock (this.packetQueue) { this.packetQueue.Enqueue(packet); } this.enqueuedByteCount += packet.Data.Length; //sleepMilliSecs = 20; } else { //this.packetQueueHasRoomEvent.WaitOne(); bool signalReceived = this.packetQueueHasRoomEvent.WaitOne(1000); #if DEBUG if (!signalReceived) { System.Diagnostics.Debugger.Break(); } #endif /*System.Threading.Thread.Sleep(sleepMilliSecs); * if (sleepMilliSecs < 1000) * sleepMilliSecs+=10;*/ } } } catch (System.IO.EndOfStreamException) { //Do nothing, just stop reading this.pcapStream = null; } catch (System.IO.IOException) { //probably a socket timout if (!(this.pcapStream is System.IO.FileStream) && this.pcapStream != null) { if (this.pcapStream.CanWrite) { this.pcapStream.Flush(); } this.pcapStream.Dispose(); } //this.pcapStream = null; } catch (OperationCanceledException) { if (!(this.pcapStream is System.IO.FileStream) && this.pcapStream != null) { if (this.pcapStream.CanWrite) { this.pcapStream.Flush(); } this.pcapStream.Dispose(); } } #if !DEBUG catch (Exception ex) { this.pcapStream = null; //this.backgroundStreamReaderCanceller.Cancel(); //e.Cancel = true; //e.Result = ex.Message; this.AbortFileRead(); } #endif //do a callback with this.filename as well as first and last timestamp if (this.streamReadCompletedCallback != null && firstFrameTimestamp != DateTime.MinValue && lastFrameTimestamp != DateTime.MinValue) { this.streamReadCompletedCallback(framesCount, firstFrameTimestamp, lastFrameTimestamp); } }); if (startBackgroundWorkers) { this.StartBackgroundWorkers(); } }
public PcapStreamReader(System.IO.Stream pcapStream, int packetQueueSize, StreamReadCompletedCallback streamReadCompletedCallback, bool startBackgroundWorkers, long streamMaxLength, int readTimeoutMilliseconds) { this.pcapStream = pcapStream; this.streamLength = streamMaxLength; this.readBytesEstimate = 0; this.readTimeoutMilliseconds = readTimeoutMilliseconds; this.packetQueueMaxSize = packetQueueSize; this.streamReadCompletedCallback = streamReadCompletedCallback; //TODO: Figure out if it is a libpcap or pcapNG stream... this.pcapParser = PcapParserFactory.CreatePcapParser(this);// new PcapParser(pcapStream, this.AbortReadingPcapStream); this.packetQueueBC = new System.Collections.Concurrent.BlockingCollection <PcapFrame>(this.packetQueueMaxSize); //this.packetQueue = new System.Collections.Concurrent.ConcurrentQueue<PcapFrame>(); //this.packetQueueHasRoomEvent = new System.Threading.AutoResetEvent(true); this.enqueuedByteCount = 0; this.dequeuedByteCount = 0; this.backgroundStreamReaderCanceller = new System.Threading.CancellationTokenSource(); System.Threading.CancellationToken cancellationToken = backgroundStreamReaderCanceller.Token; this.readAction = new Action(() => { DateTime firstFrameTimestamp = DateTime.MinValue; DateTime lastFrameTimestamp = DateTime.MinValue; int framesCount = 0; try { //int sleepMilliSecs = 20; while (!cancellationToken.IsCancellationRequested && !this.EndOfStream()) { PcapFrame packet = this.pcapParser.ReadPcapPacketBlocking(); //PcapFrame packet = await this.pcapParser.ReadPcapPacketAsync(cancellationToken); if (firstFrameTimestamp == DateTime.MinValue) { firstFrameTimestamp = packet.Timestamp; } lastFrameTimestamp = packet.Timestamp; framesCount++; this.enqueuedByteCount += packet.Data.Length; while (!this.packetQueueBC.TryAdd(packet, 1000, cancellationToken)) { if (cancellationToken.IsCancellationRequested || this.EndOfStream()) { break; } } //this.packetQueue.Enqueue(packet); } } catch (System.IO.EndOfStreamException) { //Do nothing, just stop reading this.pcapStream = null; } catch (System.IO.IOException) { //probably a socket timout if (!(this.pcapStream is System.IO.FileStream) && this.pcapStream != null) { if (this.pcapStream.CanWrite) { this.pcapStream.Flush(); } this.pcapStream.Dispose(); } //this.pcapStream = null; } catch (OperationCanceledException) { if (!(this.pcapStream is System.IO.FileStream) && this.pcapStream != null) { if (this.pcapStream.CanWrite) { this.pcapStream.Flush(); } this.pcapStream.Dispose(); } } #if !DEBUG catch (Exception ex) { this.pcapStream = null; //this.backgroundStreamReaderCanceller.Cancel(); //e.Cancel = true; //e.Result = ex.Message; this.AbortFileRead(); } #endif //do a callback with this.filename as well as first and last timestamp if (this.streamReadCompletedCallback != null && firstFrameTimestamp != DateTime.MinValue && lastFrameTimestamp != DateTime.MinValue) { this.streamReadCompletedCallback(framesCount, firstFrameTimestamp, lastFrameTimestamp); } }); if (startBackgroundWorkers) { this.StartBackgroundWorkers(); } }