public void WriteFrame(PcapFrame frame, bool flush)
        {
            TimeSpan delta = frame.Timestamp.Subtract(this.referenceTime);
            //The smallest unit of time is the tick, which is equal to 100 nanoseconds. A tick can be negative or positive.
            long totalMicroseconds = delta.Ticks / 10;
            uint seconds           = (uint)(totalMicroseconds / 1000000);
            uint microseconds      = (uint)(totalMicroseconds % 1000000);

            fileStream.Write(ToByteArray(seconds), 0, 4);
            fileStream.Write(ToByteArray(microseconds), 0, 4);
            //number of octets of packet saved in file
            fileStream.Write(ToByteArray((uint)frame.Data.Length), 0, 4);
            //actual length of packet
            fileStream.Write(ToByteArray((uint)frame.Data.Length), 0, 4);
            //data
            fileStream.Write(frame.Data, 0, frame.Data.Length);
            if (flush)
            {
                fileStream.Flush();
            }
            framesWritten++;
        }
 public void WriteFrame(PcapFrame frame)
 {
     WriteFrame(frame, false);
 }
예제 #3
0
        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();
            }
        }