Пример #1
0
        /// <summary>
        /// unix specific code, we want to poll for packets
        /// otherwise if we call pcap_dispatch() the read() will block
        /// and won't resume until a packet arrives OR until a signal
        /// occurs
        /// </summary>
        /// <param name="timeout">
        /// Timeout chosen to allow the capture thread to loop frequently enough
        /// to enable it to properly exit when the user requests it to but
        /// infrequently enough to cause any noticable performance overhead
        /// </param>
        /// <returns>true if poll was successfull and we have data to read, false otherwise</returns>
        protected internal bool PollFileDescriptor(int timeout = 500)
        {
            if (FileDescriptor < 0)
            {
                // Either this is a File Capture, or Windows
                // Assume we have data to read
                return(true);
            }
            var pollFds = new Posix.Pollfd[1];

            pollFds[0].fd     = FileDescriptor;
            pollFds[0].events = Posix.PollEvents.POLLPRI | Posix.PollEvents.POLLIN;

            var result = Posix.Poll(pollFds, (uint)pollFds.Length, timeout);

            // if we have no poll results, we don't have anything to read
            // -1 means error
            // 0 means timeout
            // non-negative means we got something
            return(result != 0);
        }
Пример #2
0
        /// <summary>
        /// The capture thread
        /// </summary>
        protected virtual void CaptureThread(CancellationToken cancellationToken)
        {
            if (!Opened)
            {
                throw new DeviceNotReadyException("Capture called before PcapDevice.Open()");
            }

            var Callback = new LibPcapSafeNativeMethods.pcap_handler(PacketHandler);

            Posix.Pollfd[] pollFds = null;
            // unix specific code
            if (UsePosixPoll)
            {
                // retrieve the file descriptor of the adapter for use with poll()
                var captureFileDescriptor = LibPcapSafeNativeMethods.pcap_fileno(PcapHandle);
                if (captureFileDescriptor == -1)
                {
                    SendCaptureStoppedEvent(CaptureStoppedEventStatus.ErrorWhileCapturing);
                    return;
                }
                pollFds           = new Posix.Pollfd[1];
                pollFds[0].fd     = captureFileDescriptor;
                pollFds[0].events = Posix.PollEvents.POLLPRI | Posix.PollEvents.POLLIN;
            }

            while (!cancellationToken.IsCancellationRequested)
            {
                // unix specific code, we want to poll for packets
                // otherwise if we call pcap_dispatch() the read() will block
                // and won't resume until a packet arrives OR until a signal
                // occurs
                if (pollFds != null)
                {
                    // Timeout chosen to allow the capture thread to loop frequently enough
                    // to enable it to properly exit when the user requests it to but
                    // infrequently enough to cause any noticable performance overhead
                    const int millisecondTimeout = 500;
                    // block here
                    var result = Posix.Poll(pollFds, (uint)pollFds.Length, millisecondTimeout);

                    // if we have no poll results, just loop
                    if (result <= 0)
                    {
                        continue;
                    }

                    // fall through here to the pcap_dispatch() call
                }

                int res = LibPcapSafeNativeMethods.pcap_dispatch(PcapHandle, m_pcapPacketCount, Callback, IntPtr.Zero);

                // pcap_dispatch() returns the number of packets read or, a status value if the value
                // is negative
                if (res <= 0)
                {
                    switch (res)                    // Check pcap loop status results and notify upstream.
                    {
                    case Pcap.LOOP_USER_TERMINATED: // User requsted loop termination with StopCapture()
                        SendCaptureStoppedEvent(CaptureStoppedEventStatus.CompletedWithoutError);
                        return;

                    case Pcap.LOOP_COUNT_EXHAUSTED:         // m_pcapPacketCount exceeded (successful exit)
                    {
                        // NOTE: pcap_dispatch() returns 0 when a timeout occurrs so to prevent timeouts
                        //       from causing premature exiting from the capture loop we only consider
                        //       exhausted events to cause an escape from the loop when they are from
                        //       offline devices, ie. files read from disk
                        if (this is CaptureFileReaderDevice)
                        {
                            SendCaptureStoppedEvent(CaptureStoppedEventStatus.CompletedWithoutError);
                            return;
                        }
                        break;
                    }

                    case Pcap.LOOP_EXIT_WITH_ERROR:         // An error occurred whilst capturing.
                        SendCaptureStoppedEvent(CaptureStoppedEventStatus.ErrorWhileCapturing);
                        return;

                    default:        // This can only be triggered by a bug in libpcap.
                        throw new PcapException("Unknown pcap_loop exit status.");
                    }
                }
                else // res > 0
                {
                    // if we aren't capturing infinitely we need to account for
                    // the packets that we read
                    if (m_pcapPacketCount != Pcap.InfinitePacketCount)
                    {
                        // take away for the packets read
                        if (m_pcapPacketCount >= res)
                        {
                            m_pcapPacketCount -= res;
                        }
                        else
                        {
                            m_pcapPacketCount = 0;
                        }

                        // no more packets to capture, we are finished capturing
                        if (m_pcapPacketCount == 0)
                        {
                            SendCaptureStoppedEvent(CaptureStoppedEventStatus.CompletedWithoutError);
                            return;
                        }
                    }
                }
            }

            SendCaptureStoppedEvent(CaptureStoppedEventStatus.CompletedWithoutError);
        }