Using socket descriptor as an index works okay for UNIX, though it
wastes the first several indices which are assigned to STDIN/STDOUT,
files, etc. However, for Windows it is really bad, since descriptors are
large, nonconsecutive numbers. Using a little overhead to track each
iod's index and the next empty space is worth it.
1. pcap_get_selectable_fd() may return -1 for some devices, even if the
platform as a whole supports select() on these handles. Check for
this condition throughout.
2. The various backend system calls (kevent, poll, epoll, etc.) do not
sleep for the timeout period if no valid handles are registered,
unlike select on UNIX. This leads to busy wait, looping continuously.
Instead, we call usleep() in those cases.
For platforms without selectable pcap handles (e.g. Windows), the
arrival of data for a pcap read would previously skip checking for any
triggered non-pcap events in that loop iteration. This is not usually a
problem because the next loop will be triggered immediately, picking up
the non-pcap events before any further pcap data arrives. However,
excessive pcap data on a handle in immediate mode might prevent the
engine loop from checking for non-pcap events for long enough to result
in timeouts. Instead, do a non-blocking check for triggered events in
this case and handle those in the same loop iteration.
WSAPoll returns WSAEINVAL when there are no valid sockets in the fdarray
parameter. Individual WSAPOLLFDs can be ignored by setting them to a
negative value (just as with POSIX poll(2)), but there must be at least
one valid (not-ignored) socket to check.
Handled this by either returning error if the error was not EINVAL, or
by checking each WSAPOLLFD in the fdarray; at the first valid one,
return the error, since this was not the reason for the error. If none
are valid, continue, ignoring the error.
Make current loglevel and current log callback global
to the library. Attaching them to the nsock pool doesn't
bring any benefit and prevents from logging activity in
code sections that don't have access to a pool (such as
proxy chain specification parsing).
Updated external calls and nsock tests accordingly.
Entering nsock_loop() with the poll engine activated and no registered FD
(timers only, for instance) should not directly return, but sleep until next
timeout.
This prevents nsock from iterating over the whole list of events at
each runloop, thus improving performance.
It made it necessary to have pointers from the msevents to the event
lists they belong to. The patch therefore also changes gh_list from
autonomous containers to embedded structures.
Added unit tests accordingly and cosmetic changes to make things look
more consistent.
Reworked the logging infrastructure to make it more flexible
and consistent.
Updated nmap, nping and ncat accordingly. Nsock log level can
now be adjusted at runtime by pressing d/D in nmap.
I'm not sure why I wasn't seeing this error before:
engine_poll.c: In function ‘poll_loop’:
engine_poll.c:352:46: error: ‘EINTR’ undeclared (first use in this function)
engine_poll.c:352:46: note: each undeclared identifier is reported only once for each function it appears in
- Do not set the X flags as events to be watched.
- Do not use POLLPRI as a R flag.
Not doing so causes WSAPoll() to fail with an "invalid argument" error.