Gianluca Varenni wrote:
It works (even with AirPcap adapters), with a caveat. The handle doesn't get
signalled immediately. It gets signalled when at least mintocopy bytes have
been stored in the WinPcap kernel buffer. By default mintocopy is 16k, so if
you receive less than 16k packets, the event never gets signalled. You can
use WaitForSingleObject/WaitForMultipleObjects, *but* you need to use a
timeout to avoid a deadlock if less than mintocopy bytes are received.
Wow, it's BSD-compatible! :-)
(That's the equivalent of the bug that various BSDs have, wherein a
select() wakeup doesn't occur until the BPF store buffer fills up,
regardless of the timeout. The workaround is similar - add a timeout to
the select(), and make sure the BPF device is in non-blocking mode, so
that if the timeout expires and there are *no* packets available, you
won't block forever.
The fix is to, in the BPF code, catch attempts to select() or poll() on
the descriptor, and start a timer when that happens, and when that timer
expires, indicate that the descriptor is readable. I don't know whether
that can be done in Windows, as I don't know whether a device can have a
"call me when somebody does a 'wait for' on a handle for me" routine.
Now, if the way the timeout worked was that it caused a read to finish
if more than the specified amount of time elapsed *between packets*,
this wouldn't be an issue; the code would do a wakeup if either the
buffer fills up or it's been too long since the last packet arrived.
That would also have two other advantages:
1) it arguably does what's *really* wanted here, which is to do
batching of packets when they're arriving at a high rate without waiting
too long - or forever - if they're arriving at a slow rate; a fairly
short timeout might work, as the timer doesn't start until a packet
arrives, and it resets on each packet, and a short timeout means you
don't have a high latency when packets are arriving slowly.
2) it means that people wouldn't have gotten confused and thought that
the libpcap timeout somehow guaranteed that a pcap_dispatch() call would
return after a given period of time, even if no packets were processed.
Solaris's timer in bpfmod doesn't start until at least one packet
arrives, but it doesn't get reset on each packet.