diff --git a/src/iosource/PktSrc.cc b/src/iosource/PktSrc.cc index 2ca5d2720e..0fa9585621 100644 --- a/src/iosource/PktSrc.cc +++ b/src/iosource/PktSrc.cc @@ -139,6 +139,16 @@ void PktSrc::Done() Close(); } +bool PktSrc::HasBeenIdleFor(double interval) const + { + if ( have_packet || had_packet ) + return false; + + // Take the hit of a current_time() call now. + double now = zeek::util::current_time(true); + return idle_at_wallclock < now - interval; + }; + void PktSrc::Process() { if ( ! IsOpen() ) @@ -191,6 +201,18 @@ bool PktSrc::ExtractNextPacketInternal() } else { + // Update the idle_at timestamp the first time we've failed + // to extract a packet. This assumes ExtractNextPacket() is + // called regularly which is true for non-selectable PktSrc + // instances, but even for selectable ones with an FD the + // main-loop will call Process() on the interface regularly + // and detect it as idle. + if ( had_packet ) + { + DBG_LOG(DBG_PKTIO, "source %s is idle now", props.path.c_str()); + idle_at_wallclock = zeek::util::current_time(true); + } + had_packet = false; } diff --git a/src/iosource/PktSrc.h b/src/iosource/PktSrc.h index d93b5d60bc..a1ef1c6e64 100644 --- a/src/iosource/PktSrc.h +++ b/src/iosource/PktSrc.h @@ -88,6 +88,24 @@ public: */ bool IsError() const; + /** + * Return true if the source has been observed idle for the given + * wallclock interval. + * + * The default implementation looks at failing ExtractNextPacket() calls + * and keeps the wallclock timestamp when there was no packet available. + * The source is considered idle when there has not been a packet since + * \a interval seconds. + * + * Alternative implementations may check internally buffered packets + * or queue lengths. + * + * @param interval Interval in seconds. + * + * @return True if the source has been idle for \a interval seconds. + */ + virtual bool HasBeenIdleFor(double interval) const; + /** * If the source encountered an error, returns a corresponding error * message. Returns an empty string otherwise. @@ -365,6 +383,8 @@ private: // Did the previous call to ExtractNextPacket() yield a packet. bool had_packet; + double idle_at_wallclock = 0.0; + // For BPF filtering support. std::vector filters;