From fda30451cac5936729c683d38a700f4928812c6f Mon Sep 17 00:00:00 2001 From: "Kevin L. Mitchell" Date: Thu, 7 Jun 2001 00:29:48 +0000 Subject: [PATCH] Author: Kev Log message: This is the long awaited merge of the events branch with the main-line. The events branch is now defunct. Enjoy... git-svn-id: file:///home/klmitch/undernet-ircu/undernet-ircu-svn/ircu2/trunk@487 c9e4aea6-c8fd-4c43-8297-357d70d61c8c --- ChangeLog | 617 ++++++++++++++++++++++++ INSTALL_FR | 1 - RELEASE.NOTES | 2 +- acconfig.h | 4 + config.h.in | 14 +- configure | 495 +++++++++++++------ configure.in | 89 +++- include/IPcheck.h | 2 +- include/client.h | 30 ++ include/ircd.h | 1 + include/ircd_events.h | 247 ++++++++++ include/ircd_osdep.h | 2 +- include/ircd_policy.h | 1 + include/list.h | 2 + include/listener.h | 5 +- include/numeric.h | 1 + include/s_auth.h | 15 +- include/s_bsd.h | 2 + include/s_debug.h | 21 +- include/uping.h | 12 +- ircd/IPcheck.c | 37 +- ircd/Makefile.in | 1066 ++++++++++++++++++++++------------------- ircd/channel.c | 2 + ircd/engine_devpoll.c | 406 ++++++++++++++++ ircd/engine_kqueue.c | 414 ++++++++++++++++ ircd/engine_poll.c | 404 ++++++++++++++++ ircd/engine_select.c | 375 +++++++++++++++ ircd/ircd.c | 105 ++-- ircd/ircd_events.c | 736 ++++++++++++++++++++++++++++ ircd/ircd_signal.c | 49 +- ircd/list.c | 67 ++- ircd/listener.c | 150 +++--- ircd/m_list.c | 2 + ircd/m_stats.c | 18 + ircd/os_bsd.c | 10 +- ircd/os_generic.c | 20 +- ircd/os_linux.c | 10 +- ircd/os_openbsd.c | 10 +- ircd/os_solaris.c | 19 +- ircd/res.c | 43 ++ ircd/s_auth.c | 207 +++++--- ircd/s_bsd.c | 764 ++++++++--------------------- ircd/s_conf.c | 2 +- ircd/s_err.c | 2 +- ircd/s_serv.c | 2 +- ircd/s_stats.c | 1 + ircd/s_user.c | 2 +- ircd/send.c | 6 +- ircd/uping.c | 125 ++++- 49 files changed, 5095 insertions(+), 1522 deletions(-) create mode 100644 include/ircd_events.h create mode 100644 ircd/engine_devpoll.c create mode 100644 ircd/engine_kqueue.c create mode 100644 ircd/engine_poll.c create mode 100644 ircd/engine_select.c create mode 100644 ircd/ircd_events.c diff --git a/ChangeLog b/ChangeLog index 294e412..4936069 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,273 @@ +2001-06-06 Kevin L. Mitchell + + * ircd/res.c (init_resolver): don't start DNS expires with a 0 + relative timeout--if the server starts slow, timeouts could be + messy...there's probably a better solution, but this'll do for now + + * ircd/os_solaris.c: _XOPEN_SOURCE doesn't get along with Solaris + headers very well; include stropts.h; define an os_set_tos() + + * ircd/os_generic.c (os_set_tos): added an os_set_tos() for + os_generic.c + + * ircd/ircd.c: if there are no C-lines, we don't want to have a + timer that expires at the absolute time of 0--it kinda blocks all + the other timers! + + * ircd/engine_devpoll.c: some includes for open(); declare errcode + and codesize in engine_loop() + + * ircd/list.c (free_client): remove bogus check on timer active + flag + + * ircd/s_auth.c: pull out destruction code in + auth_timeout_request() into an externally-visible + destroy_auth_request(); manage cli_auth pointer in client + structure; use it for an extra assertion check + + * ircd/list.c: include s_auth.h for destroy_auth_request(); add + debugging notices to show flow when deallocating + connections/clients; call destroy_auth_request() when free'ing a + client that has an auth outstanding; don't free the connection if + the process timer is unmarked but still active + + * ircd/ircd_events.c: set GEN_ACTIVE when initializing a generator + and reset it before calling the event handler for an ET_DESTROY + event + + * include/s_auth.h (destroy_auth_request): declare + destroy_auth_request(), which can be used to destroy an + outstanding auth request if a client socket goes away before the + auth exchange is completed + + * include/ircd_events.h: add an active flag to keep track of + whether or not particular generators are active, for the + convenience of functions using the API + + * include/client.h: add a pointer for auth requests to struct + Connection so we can kill outstanding auth requests if a client + socket closes unexpectedly + + * ircd/s_bsd.c: cli_connect() could become 0 during the course of + the sock or timer callback; take that into account in the assert + + * ircd/list.c: add magic number checking and setting--magic + numbers are zero'd on frees to detect double-frees; add back + setting of cli_from() to 0 to break the back-link from the struct + Connection (duh) + + * ircd/ircd.c: set me's magic number correctly + + * include/client.h: define magic numbers and accessor/verifier + macros + + * ircd/list.c: assert that dealloc_client() is called with + cli_connect(cptr) == 0; set cli_connect(cptr) to 0 before calling + dealloc_client(); don't mess with cli_from(cptr) + + * ircd/s_bsd.c: only attempt to dealloc a connection if the + associated client has already been destroyed, or at least delinked + +2001-06-05 Kevin L. Mitchell + + * ircd/list.c (free_client): only try to delete the socket when + the fd hasn't already been closed, avoiding a double-free + + * ircd/list.c (free_connection): make sure the client is really + gone before doing away with the connection + + * ircd/s_bsd.c: record that socket has been added in con_freeflag + field; queue a socket_del() as soon as the socket is close()'d; + use con_freeflag & FREEFLAG_TIMER instead of con_timer; clear + FREEFLAG_SOCKET on ET_DESTROY event in client_sock_callback(), + then dealloc the connection if safe; mark socket as dead when + there's a read error or EOF; clear FREEFLAG_TIMER flag upon entry + to client_timer_callback(); dealloc connection if safe upon + ET_DESTROY event in client_timer_callback() + + * ircd/list.c: use con_freeflag instead of con_timer; only dealloc + the connection if both socket and timer have been destroyed; + destroy both socket and timer explicitly and carefully + + * include/client.h: replace the con_timer field with a + con_freeflag field, to indicate what still needs freeing; define + the freeflags + + * ircd/engine_select.c (engine_loop): duh...sockList[i] could + become 0 + + * ircd/engine_devpoll.c (engine_loop): duh...sockList[i] could + become 0 + + * ircd/s_bsd.c: add some extra assertions to try to track down a + corruption problem + + * ircd/engine_select.c (engine_loop): add an extra assert to try + to track down a corruption problem + + * ircd/engine_poll.c (engine_loop): add an extra assert to try to + track down a corruption problem + + * ircd/engine_kqueue.c (engine_loop): add an extra assert to try + to track down a corruption problem + + * ircd/engine_devpoll.c (engine_loop): skip slots that have become + empty during processing; add an extra assert to try to track down + a corruption problem + + * ircd/engine_kqueue.c (engine_delete): make sure to zero deleted + entries + +2001-06-04 Kevin L. Mitchell + + * ircd/s_bsd.c (client_sock_callback): client is no longer + blocked, so we must mark it as unblocked + + * ircd/engine_select.c: add Debug() calls galore; add handling for + SS_NOTSOCK; use a dummy sock variable to keep things from + disappearing on us; correct timeout calculation; update nfds for + efficiency + + * ircd/engine_poll.c: use new debugging level (DEBUG_ENGINE); + remove a spurious "if (sock)" which will always be true; update + nfds for efficiency + + * ircd/engine_kqueue.c: add Debug() calls galore; add handling for + SS_NOTSOCK (just in case); correct timeout calculation + + * ircd/engine_devpoll.c: add Debug() calls galore; add handling + for SS_NOTSOCK; correct timeout calculation; add EAGAIN handling + + * include/s_debug.h (DEBUG_ENGINE): add new debugging level; + pretty-indent numbers + + * ircd/engine_poll.c (engine_loop): break out SS_NOTSOCK + case--it's not a socket; the check for writability is most likely + not needed, but present for completeness + +2001-05-24 Kevin L. Mitchell + + * ircd/s_bsd.c: add Debug messages; call read_packet() even if the + no newline flag is set; call read_packet() when the timer expires, + regardless of what's in the buffer--read_packet() should be able + to deal properly + + * ircd/IPcheck.c (ip_registry_connect_succeeded): correct a NOTICE + sent to clients to include the client nickname (duh) + + * ircd/ircd_events.c: don't destroy a timer if it's already marked + for destruction; replace a missing ! in socket_del() + + * ircd/engine_poll.c (engine_loop): reference a temporary variable + so we don't have to worry about sockList[i] going away + + * ircd/s_bsd.c (client_sock_callback): add Debug messages + + * ircd/s_auth.c: add Debug messages all over the place + + * ircd/ircd_events.c: add and edit some Debug messages; add a list + of routines to convert some of the enums and flags from numbers + into human-readable strings for the Debug messages + + * ircd/engine_poll.c: hack some Debug messages to use the new name + conversion routines in ircd_events.c; add an extra assert for a + condition that shouldn't ever happen; apparently recv() can return + EAGAIN when poll() returns readable--I wonder why... + + * include/ircd_events.h: declare some helper routines under + DEBUGMODE + +2001-05-23 Kevin L. Mitchell + + * ircd/s_bsd.c (client_sock_callback): add an extra assertion + check + + * ircd/s_auth.c: add more Debug messages + + * ircd/list.c (make_client): add an extra assertion check + + * ircd/ircd_events.c (socket_events): don't call the engine events + changer if we haven't actually made any changes to the event mask + + * ircd/uping.c: add some Debug messages + + * ircd/s_stats.c: document new /STATS e + + * ircd/s_err.c: add RPL_STATSENGINE to report the engine name + + * ircd/s_bsd.c: remove static client_timer variable; in + read_packet(), if there's still data in the client's recvQ after + parsing, add a 2 second timer (con_proc); fix the ET_DESTROY case + of client_sock_callback to handle destroying the timer properly; + rewrote client_timer_callback from scratch to be called on an + individual client + + * ircd/m_stats.c: add /STATS e to report the engine name + + * ircd/list.c: deal with con_timer field in struct Connection + properly; correct a core-level bug in remove_client_from_list--if + the client is the only one in the list, we try to update + GlobalClientList's cli_prev pointer--not good + + * ircd/ircd.c: remove call to init_client_timer() + + * ircd/engine_poll.c: made Debug messages more uniform by + prepending "poll:" to them all; corrected an off-by-one error that + caused poll_count to be 1 less than the actual count and removed + my work-around; added Debug messages to indicate which socket is + being checked and what the results are + + * ircd/Makefile.in: ran a make depend + + * include/s_bsd.h: remove init_client_timer(), since we're doing + it differently now + + * include/numeric.h (RPL_STATSENGINE): a stats reply to report the + engine name + + * include/ircd_policy.h (HEAD_IN_SAND_STATS_E): turn off /stats e + reports for non-opers + + * include/client.h: add con_timer and con_proc fields to struct + Connection and define accessor macros--con_timer marks that + con_proc contains a valid timer, and con_proc is used to pace user + data + + * ircd/s_bsd.c (close_connection): let free_client() destroy the + socket + + * ircd/s_auth.c (start_auth): add a Debug call to indicate when + auth has begun on a client + + * ircd/ircd_events.c: ensure that event_execute() is called with a + non-NULL event; modify event_add() macro to properly zero list + bits; modify gen_dequeue() to not try to clip it out of a list + it's already been clipped out of; change signal socket + initialization to use state SS_NOTSOCK; permit timeout values of + 0 in add_timer(); add many Debug calls; change socket_del() and + timer_del() to always set the GEN_DESTROY flag; use GEN_MARKED in + timer_run() instead of GEN_DESTROY so that event_generate() will + pass on the events; remove the switch and replace with a simpler + if-then-else tree in timer_run(); don't allow destroyed sockets to + be destroyed again, nor their states or event masks to be changed + + * ircd/ircd.c: initialize "running" to 1 + + * ircd/engine_poll.c: deal with SS_NOTSOCK "sockets"; add Debug + messages all over the place; fix a counting problem in + engine_add(); turn wait into a signed integer and set it to -1 + only if timer_next() returns 0; adjust wait time to be relative; + don't call gen_ref_dec() if socket disappeared while we were + processing it + + * include/ircd_events.h: the pipe for signals is not a socket, so + we must mark it as such--added SS_NOTSOCK for that special socket; + events won't be generated if GEN_DESTROY is on, so add GEN_MARKED + for the benefit of timer_run() + + * configure.in: add --enable-pedantic and --enable-warnings to + turn on (and off) -Wall -pedantic in CFLAGS + 2001-05-21 Kevin L. Mitchell * ircd/s_conf.c: change "s_addr" element accesses to "address" @@ -6,6 +276,185 @@ * include/s_conf.h: on some systems, "s_addr" is a macro; use "address" instead +2001-05-18 Kevin L. Mitchell + + * ircd/engine_kqueue.c: include ircd_alloc.h; set_or_clear returns + void in this file; add a missing semi-colon; declare errcode, + codesize + + * ircd/uping.c (uping_sender_callback): it's pptr, not uping + + * ircd/s_user.c (register_user): comment out spurious reference to + nextping + + * ircd/s_serv.c (server_estab): comment out spurious reference to + nextping + + * ircd/s_conf.c (read_configuration_file): comment out spurious + reference to nextping and nextconnect + + * ircd/s_bsd.c: comment out some spurious references to formerly + global (now non-existant) variables; correct a couple of typos + + * ircd/s_auth.c: pre-declare some functions referenced in the + callback; correct a typo + + * ircd/res.c (start_resolver): pass errno value of ENFILE + + * ircd/listener.c (accept_connection): you know your API is messed + up when...variables that shouldn't have been global crop up in + other files + + * ircd/list.c (free_client): substitution of == for = + + * ircd/ircd_signal.c: include assert.h for assertion checking; + check ev_data() to find out what signal generated event + + * ircd/ircd_events.c: some references to the variable "timer" + should have been references to the variable "ptr" + + * ircd/engine_select.c: it's struct fd_set, not struct fdset; + ev_timer(ev) is already a timer pointer; declare codesize as a + size_t to correct signedness issue; use timer_next(), not + time_next() + + * ircd/engine_poll.c: ev_timer(ev) is already a timer pointer; + select fd out of struct pollfd in assertion checking; declare + errcode and codesize; use timer_next(), not time_next() + + * ircd/engine_kqueue.c: ev_timer(ev) is already a timer pointer; + use function timer_next(), not time_next() + + * ircd/engine_devpoll.c: ev_timer(ev) is already a timer pointer; + use function timer_next(), not time_next() + + * ircd/Makefile.in (IRCD_SRC): add ircd_events.c to the list of + compiled sources; do make depend + + * include/list.h: pre-declare struct Connection + + * include/ircd_events.h (gen_ref_inc): cast to the right structure + name + + * include/s_auth.h: duh; missing */ + +2001-05-10 Kevin L. Mitchell + + * ircd/send.c: update write events status after sending data or + accumulating data to be sent + + * ircd/m_list.c (m_list): update write events status after + canceling a running /list + + * ircd/channel.c (list_next_channels): update write events status + after listing a few channels + + * ircd/s_bsd.c: extensive changes to update to new events model; + remove on_write_unblocked() and the two implementations of + read_message(), which have been deprecated by this change + + * ircd/s_auth.c: set the socket events we're interested in for + clients; simplify some logic that does the connect_nonb followed + by the socket_add + + * ircd/list.c: define free_connection() to free a connection + that's become freeable once the struct Socket has been + deallocated; fix up free_client() to take this new behavior into + account + + * ircd/ircd.c: call init_client_timer() + + * include/s_bsd.h: declare new REGISTER_ERROR_MESSAGE when unable + to register connect-in-progress with events system; declare + init_client_timer() (HACK!) to preserve rate-limiting behavior + + * include/list.h: declare new free_connection() + + * include/client.h: add a struct Socket to struct Connection + +2001-05-09 Kevin L. Mitchell + + * ircd/ircd_signal.c: massage the handlers for SIGHUP, SIGINT, and + SIGTERM into event callbacks; perform the actions in the + callbacks, since they're not called in the context of the signal; + set up the signal callbacks in the event engine + + * ircd/ircd_events.c (signal_callback): we're supposed to look for + a specific signal; don't generate an event if there is no signal + structure for it + + * ircd/ircd.c: nuke nextconnect and nextping and replace them with + connect_timer and ping_timer; massage try_connections() and + check_pings() into timer callbacks that re-add themselves at the + right time; remove ircd.c's "event_loop()"; initialize the event + system and the connect_timer and ping_timer + + * ircd/uping.c: correct a couple more typos + + * ircd/s_auth.c: rework to use new events system + + * ircd/os_solaris.c (os_connect_nonb): update to new interface + + * ircd/os_openbsd.c (os_connect_nonb): update to new interface + + * ircd/os_linux.c (os_connect_nonb): update to new interface + + * ircd/os_generic.c (os_connect_nonb): update to new interface + + * ircd/os_bsd.c (os_connect_nonb): update to new interface + + * include/s_auth.h: remove deprecated members of struct + AuthRequest, replacing them with struct Socket and struct Timer + structures; add flags to indicate when these structures have been + released by the event system; remove the deprecated + timeout_auth_queries() + + * include/ircd_osdep.h (os_connect_nonb): connect could complete + immediately, so change the interface to handle that possibility + + * ircd/uping.c (uping_server): noticed and corrected a typo + + * ircd/listener.c: set up to use ircd_event's struct Socket by + adding an socket_add() call to inetport(), replacing + free_listener() with socket_del() in close_listener(), and + reworking accept_connection to be called as the callback + + * ircd/ircd.c: add a call to IPcheck_init() + + * ircd/IPcheck.c: remove IPcheck_expire(); rework + ip_registry_expire() to be called from a timer; write + IPcheck_init() to set up the expiration timer (hard-coded for a + 60-second expiration time) + + * include/listener.h: add a struct Socket to the struct Listener; + remove accept_connection() + + * include/IPcheck.h: add IPcheck_init(), remove IPcheck_expire() + +2001-05-08 Kevin L. Mitchell + + * ircd/ircd_events.c: include config.h; use USE_KQUEUE and + USE_DEVPOLL instead of HAVE_KQUEUE and HAVE_DEVPOLL_H + + * ircd/engine_select.c: include config.h; set FD_SETSIZE to + MAXCONNECTIONS, not IRCD_FD_SETSIZE... + + * ircd/engine_poll.c: include config.h + + * ircd/engine_kqueue.c: include config.h + + * ircd/engine_devpoll.c: include config.h + + * ircd/Makefile.in: include engine sources in compilation and make + depend steps + + * configure.in: add checks for enabling the /dev/poll- and + kqueue-based engines + + * acconfig.h: add lines for USE_DEVPOLL and USE_KQUEUE + + * ircd/Makefile.in: work in the engine sources + 2001-05-07 Kevin L. Mitchell * ircd/m_settime.c: include ircd_snprintf.h @@ -197,6 +646,24 @@ * ircd/send.c (sendcmdto_flag_butone): if FLAGS_OPER is or'd with flag, send only to appropriate opers +2001-04-13 Kevin L. Mitchell + + * ircd/uping.c: refit to use the new events interface + + * ircd/res.c: refit to use the new events interface + + * ircd/ircd_events.c: create timer_chg(), which permits a + (non-periodic) timer's expire time to be modified; change the + logic in timer_run() so that timers that were re-added while the + event was being processed will not be destroyed prematurely + + * include/uping.h: include the events header, declare some extra + fields in struct UPing, remove timeout value, and define some + flags for marking which cleanup items have yet to be done + + * include/ircd_events.h: add a prototype for timer_chg() to change + the expire time of a running timer + 2001-03-13 Joseph Bongaarts * ircd/os_openbsd.c: Tweaked the openbsd hack a bit. @@ -301,6 +768,28 @@ * ircd/ircd_features.c: default LOCOP_KILL to TRUE--oops... +2001-01-16 Kevin L. Mitchell + + * ircd/ircd_events.c (timer_run): it's possible that the timer got + deleted during the callback processing, so don't go to the bother + of requeuing it if the destroy flag is set + + * ircd/engine_select.c: define FD_SETSIZE to be IRCD_FD_SETSIZE + out of config.h if this is a *BSD; include errno.h (oops); + decrement error count after an hour using a timer; use FD_SETSIZE + constant instead of IRCD_FD_SETSIZE constant; fill in event + processing code + + * ircd/engine_poll.c: include errno.h (oops); decrement error + count after an hour using a timer; fill in event processing code + + * ircd/engine_kqueue.c: include errno.h (oops); decrement error + count after an hour using a timer; assert events filter is either + EVFILT_READ or EVFILT_WRITE; fill in event processing code + + * ircd/engine_devpoll.c: include errno.h (oops); decrement error + count after an hour using a timer; fill in event processing code + 2001-01-15 Kevin L. Mitchell * ircd/client.c: fixed feattab; basically, when I changed features @@ -309,6 +798,134 @@ privileges together; also fixed a bug in the antiprivs masking loop in client_set_privs()--last index wouldn't get parsed +2001-01-11 Kevin L. Mitchell + + * ircd/ircd_events.c: call event_generate() with new data + argument; make it set that field in struct Event; make + socket_add() return the value of the eng_add callback + + * ircd/engine_select.c: make engine_add() return a + successful/unsuccessful status; add bounds-checking outside of an + assert; use accessor macros; use log_write(), not the deprecated + ircd_log(); add an assert to engine_loop() to double-check for + data structure corruption + + * ircd/engine_poll.c: make engine_add() return a + successful/unsuccessful status; add bounds-checking outside of an + assert; use accessor macros; use log_write(), not the deprecated + ircd_log(); add an assert to engine_loop() to double-check for + data structure corruption + + * ircd/engine_kqueue.c: implementation of an engine for kqueue() + + * ircd/engine_devpoll.c: implementation of an engine for /dev/poll + + * include/ircd_events.h: define some accessor macros; add ev_data + to struct Event for certain important data--errno values, for + instance; make EngineAdd callback tell us if it was successful or + not; add extra argument to event_generate(); make socket_add() + return the status from EngineAdd + +2001-01-10 Kevin L. Mitchell + + * ircd/ircd_events.c: pass initializer information about how many + total _filedescriptors_ may be opened at once + + * ircd/ircd.c: use exported "running" instead of unexported + thisServer.running + + * ircd/engine_select.c: implementation of an event engine based on + select() + + * ircd/engine_poll.c: implementation of an event engine based on + poll() + + * include/ircd_events.h: pass the engine initializer an integer + specifing how many _filedescriptors_ may be opened at once + + * include/ircd.h: running has to be exported for the engine_* + event loops + +2001-01-09 Kevin L. Mitchell + + * ircd/ircd_events.c: include some needed headers; add some + comments; make evEngines[] const; bundle sig_sock and sig_fd into + a struct named sigInfo; rework struct evInfo to have a queue of + _generators_, and only when threaded; added a gen_init() function + to centralize generator initialization; fix various compile-time + errors; rework event_add() for new queueing scheme and checked for + compile-time errors; add casts where needed; spell evEngines[] + correctly; make engine_name() return const char* + + * include/ircd_events.h: type EventCallBack depends on struct + Event, so pre-declare it; put _event_ queue into generators, and + only when threaded; give engine data a union to store both ints + and pointers; make engine name a const; fix gen_ref_dec() macro; + make engine_name() return a const char* + + * ircd/ircd_events.c: gen_dequeue() is now exported, so move it + down with the non-static functions; modify event_execute() to use + the new gen_ref_dec() to simplify code; make sure event_generate() + does not generate new events for generators marked for destruction + + * include/ircd_events.h: the engines, at least, may need to modify + reference counts to keep generators from going away while + something still points at them, so add reference counter + manipulators and export gen_dequeue() for them + + * ircd/ircd_events.c: set up the list of engines to try; set up + the signal struct Socket; rename netInfo to evInfo; move static + functions near the beginning of the file; do away with + signal_signal() (since we no longer keep a signal count ourselves) + and call event_generate() directly from signal_callback--also + renamed some functions; allow signal_callback() to read up to + SIGS_PER_SOCK at once from the signal pipe; add event_init() to + initialize the entire event system; add event_loop() to call the + engine's event loop; initialize new struct GenHeader member, + gh_engdata; remove timer_next(); add socket_add() function to add + a socket; add socket_del() to mark a socket for deletion; add + socket_state() to transition a socket between states; add + socket_events() to set what events we're interested in on the + socket; add engine_name() to retrieve event engine's name + + * include/ircd_events.h: add engine data field to struct + GenHeader; rename SOCK_ACTION_REMOVE to SOCK_ACTION_DEL; add a + note about states vs s_events; remove signal count; fold union + Generator back into struct Event; remove count members from struct + Generators; redefine engine callbacks to not take a struct + Engine*; add explanatory comments to callback definitions; add + some engine callbacks to handle operations; remove struct Engine + flag member--can detect single flag from eng_signal member; add + event_init(), event_loop(), engine_name(), and the socket_*() + functions; make timer_next() a macro to avoid a function call + +2001-01-08 Kevin L. Mitchell + + * include/ircd_events.h: rename to ircd_events.h, since it handles + events, not just networking stuff; add signal support; more + structural rearrangement + + * ircd/ircd_events.c: rename to ircd_events.c, since it handles + events, not just networking stuff; add signal support; more + structural rearrangement + +2001-01-07 Kevin L. Mitchell + + * ircd/ircd_network.c: implement timer API; add reference counts + appropriately + + * include/ircd_network.h: firm up some pieces of the interface; + split out members everything has into a separate structure; add + reference counts; add timer API + +2001-01-06 Kevin L. Mitchell + + * ircd/ircd_network.c: static data and event manipulation + functions for new event processing system + + * include/ircd_network.h: data structures for new event processing + system + 2001-01-03 Kevin L. Mitchell * ircd/whowas.c: Completely re-did the old allocation scheme by diff --git a/INSTALL_FR b/INSTALL_FR index 6242806..de339b4 100644 --- a/INSTALL_FR +++ b/INSTALL_FR @@ -155,4 +155,3 @@ vous avez des probl définissent DEBUGMODE. Recompiler l'ircd, et metez-le à la main comme: ircd - t - x9. Ceci écrira un point la sortie à votre écran, montrant probablement pourquoi il ne commence pas. - diff --git a/RELEASE.NOTES b/RELEASE.NOTES index 4e17c49..1c5df59 100644 --- a/RELEASE.NOTES +++ b/RELEASE.NOTES @@ -140,4 +140,4 @@ more than 4096 IP's in 60s it warns 'dst cache overflow'. This limit can be changed by modifying /proc/sys/net/ipv4/route/max_size. A patch to select is also recommended if you have regular poll/select -errors. \ No newline at end of file +errors. diff --git a/acconfig.h b/acconfig.h index 2d0fcf4..5b6d248 100644 --- a/acconfig.h +++ b/acconfig.h @@ -48,6 +48,10 @@ /* Define to force the poll() function to be used */ #undef USE_POLL +/* Define to enable the /dev/poll engine */ +#undef USE_DEVPOLL +/* Define to enable the kqueue engine */ +#undef USE_KQUEUE /* Define to enable various debugging code in the server; DO NOT USE * THIS ON PRODUCTION SERVERS ON PAIN OF DELINKING! diff --git a/config.h.in b/config.h.in index 3b2499c..3880424 100644 --- a/config.h.in +++ b/config.h.in @@ -19,7 +19,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * - * $Id: config.h.in,v 1.1 2001-05-07 21:21:17 kev Exp $ + * $Id: config.h.in,v 1.2 2001-06-07 00:29:46 kev Exp $ */ /* Define to `int' if doesn't define. */ @@ -84,6 +84,12 @@ /* Define if you have the header file. */ #undef HAVE_POLL_H +/* Define if you have the header file. */ +#undef HAVE_SYS_DEVPOLL_H + +/* Define if you have the header file. */ +#undef HAVE_SYS_EVENT_H + /* Define if you have the nsl library (-lnsl). */ #undef HAVE_LIBNSL @@ -102,6 +108,12 @@ /* Force inlining for a few critical functions */ #undef FORCEINLINE +/* Define to enable the /dev/poll engine */ +#undef USE_DEVPOLL + +/* Define to enable the kqueue engine */ +#undef USE_KQUEUE + /* Domain name to be used for some statistics gathering */ #undef DOMAINNAME diff --git a/configure b/configure index 0ad2cdf..8b84aa8 100755 --- a/configure +++ b/configure @@ -23,8 +23,16 @@ ac_help="$ac_help --disable-symbols Disable debugging symbols (remove -g from CFLAGS)" ac_help="$ac_help --enable-profile Enable profiling support (add -pg to CFLAGS)" +ac_help="$ac_help + --enable-pedantic Enable pedantic warnings (add -pedantic to CFLAGS)" +ac_help="$ac_help + --enable-warnings Enable warnings (add -Wall to CFLAGS)" ac_help="$ac_help --disable-inlines Disable inlining for a few critical functions" +ac_help="$ac_help + --enable-devpoll Enable the experimental /dev/poll-based engine" +ac_help="$ac_help + --enable-kqueue Enable the experimental kqueue-based engine" ac_help="$ac_help --with-symlink=name Name to give the symlink; if name is "no," no symlink will be created." @@ -601,7 +609,7 @@ else { echo "configure: error: can not run $ac_config_sub" 1>&2; exit 1; } fi echo $ac_n "checking host system type""... $ac_c" 1>&6 -echo "configure:605: checking host system type" >&5 +echo "configure:613: checking host system type" >&5 host_alias=$host case "$host_alias" in @@ -625,7 +633,7 @@ echo "$ac_t""$host" 1>&6 # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:629: checking for $ac_word" >&5 +echo "configure:637: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -655,7 +663,7 @@ if test -z "$CC"; then # Extract the first word of "cc", so it can be a program name with args. set dummy cc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:659: checking for $ac_word" >&5 +echo "configure:667: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -706,7 +714,7 @@ fi # Extract the first word of "cl", so it can be a program name with args. set dummy cl; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:710: checking for $ac_word" >&5 +echo "configure:718: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -738,7 +746,7 @@ fi fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works""... $ac_c" 1>&6 -echo "configure:742: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 +echo "configure:750: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) works" >&5 ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. @@ -749,12 +757,12 @@ cross_compiling=$ac_cv_prog_cc_cross cat > conftest.$ac_ext << EOF -#line 753 "configure" +#line 761 "configure" #include "confdefs.h" main(){return(0);} EOF -if { (eval echo configure:758: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:766: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then ac_cv_prog_cc_works=yes # If we can't run a trivial program, we are probably using a cross compiler. if (./conftest; exit) 2>/dev/null; then @@ -780,12 +788,12 @@ if test $ac_cv_prog_cc_works = no; then { echo "configure: error: installation or configuration problem: C compiler cannot create executables." 1>&2; exit 1; } fi echo $ac_n "checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler""... $ac_c" 1>&6 -echo "configure:784: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 +echo "configure:792: checking whether the C compiler ($CC $CFLAGS $LDFLAGS) is a cross-compiler" >&5 echo "$ac_t""$ac_cv_prog_cc_cross" 1>&6 cross_compiling=$ac_cv_prog_cc_cross echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 -echo "configure:789: checking whether we are using GNU C" >&5 +echo "configure:797: checking whether we are using GNU C" >&5 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -794,7 +802,7 @@ else yes; #endif EOF -if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:798: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:806: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no @@ -813,7 +821,7 @@ ac_test_CFLAGS="${CFLAGS+set}" ac_save_CFLAGS="$CFLAGS" CFLAGS= echo $ac_n "checking whether ${CC-cc} accepts -g""... $ac_c" 1>&6 -echo "configure:817: checking whether ${CC-cc} accepts -g" >&5 +echo "configure:825: checking whether ${CC-cc} accepts -g" >&5 if eval "test \"`echo '$''{'ac_cv_prog_cc_g'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -849,7 +857,7 @@ fi echo $ac_n "checking for ${CC-cc} option to accept ANSI C""... $ac_c" 1>&6 -echo "configure:853: checking for ${CC-cc} option to accept ANSI C" >&5 +echo "configure:861: checking for ${CC-cc} option to accept ANSI C" >&5 if eval "test \"`echo '$''{'am_cv_prog_cc_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -865,7 +873,7 @@ for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__ do CC="$ac_save_CC $ac_arg" cat > conftest.$ac_ext < #include @@ -902,7 +910,7 @@ return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; ; return 0; } EOF -if { (eval echo configure:906: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:914: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* am_cv_prog_cc_stdc="$ac_arg"; break else @@ -947,18 +955,34 @@ if test x"$CFLAGS" != x"$unet_old_cflags"; then # If -pg was already there, force profiling to be enabled unet_cv_enable_profile=yes fi +if test x"$CFLAGS" != x; then + unet_old_cflags=$CFLAGS + CFLAGS=`echo "$CFLAGS" | sed -e 's/-Wall//g'` +fi +if test x"$CFLAGS" != x"$unet_old_cflags"; then + # If -Wall was already there, force warnings to be enabled + unet_cv_enable_warnings=yes +fi +if test x"$CFLAGS" != x; then + unet_old_cflags=$CFLAGS + CFLAGS=`echo "$CFLAGS" | sed -e 's/-pedantic//g'` +fi +if test x"$CFLAGS" != x"$unet_old_cflags"; then + # If -pedantic was already there, force pedatic to be enabled + unet_cv_enable_pedantic=yes +fi echo $ac_n "checking for library containing crypt""... $ac_c" 1>&6 -echo "configure:955: checking for library containing crypt" >&5 +echo "configure:979: checking for library containing crypt" >&5 if eval "test \"`echo '$''{'ac_cv_search_crypt'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_crypt="no" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:997: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_crypt="none required" else @@ -980,7 +1004,7 @@ rm -f conftest* test "$ac_cv_search_crypt" = "no" && for i in descrypt crypt; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1019: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_crypt="-l$i" break @@ -1016,12 +1040,12 @@ fi # Most operating systems have gethostbyname() in the default searched # libraries (i.e. libc): echo $ac_n "checking for gethostbyname""... $ac_c" 1>&6 -echo "configure:1020: checking for gethostbyname" >&5 +echo "configure:1044: checking for gethostbyname" >&5 if eval "test \"`echo '$''{'ac_cv_func_gethostbyname'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1072: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_gethostbyname=yes" else @@ -1063,7 +1087,7 @@ else echo "$ac_t""no" 1>&6 # Some OSes (eg. Solaris) place it in libnsl: echo $ac_n "checking for gethostbyname in -lnsl""... $ac_c" 1>&6 -echo "configure:1067: checking for gethostbyname in -lnsl" >&5 +echo "configure:1091: checking for gethostbyname in -lnsl" >&5 ac_lib_var=`echo nsl'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1071,7 +1095,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1110: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1109,7 +1133,7 @@ else echo "$ac_t""no" 1>&6 # Some strange OSes (SINIX) have it in libsocket: echo $ac_n "checking for gethostbyname in -lsocket""... $ac_c" 1>&6 -echo "configure:1113: checking for gethostbyname in -lsocket" >&5 +echo "configure:1137: checking for gethostbyname in -lsocket" >&5 ac_lib_var=`echo socket'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1117,7 +1141,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1156: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1157,7 +1181,7 @@ else # AC_CHECK_LIB's API is essentially broken so the following # ugliness is necessary: echo $ac_n "checking for gethostbyname in -lsocket""... $ac_c" 1>&6 -echo "configure:1161: checking for gethostbyname in -lsocket" >&5 +echo "configure:1185: checking for gethostbyname in -lsocket" >&5 ac_lib_var=`echo socket'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1165,7 +1189,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket -lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1204: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1195,7 +1219,7 @@ if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for gethostbyname in -lresolv""... $ac_c" 1>&6 -echo "configure:1199: checking for gethostbyname in -lresolv" >&5 +echo "configure:1223: checking for gethostbyname in -lresolv" >&5 ac_lib_var=`echo resolv'_'gethostbyname | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1203,7 +1227,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lresolv $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1242: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1253,12 +1277,12 @@ fi fi echo $ac_n "checking for socket""... $ac_c" 1>&6 -echo "configure:1257: checking for socket" >&5 +echo "configure:1281: checking for socket" >&5 if eval "test \"`echo '$''{'ac_cv_func_socket'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1309: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_func_socket=yes" else @@ -1299,7 +1323,7 @@ if eval "test \"`echo '$ac_cv_func_'socket`\" = yes"; then else echo "$ac_t""no" 1>&6 echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 -echo "configure:1303: checking for socket in -lsocket" >&5 +echo "configure:1327: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1307,7 +1331,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1346: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1344,7 +1368,7 @@ EOF else echo "$ac_t""no" 1>&6 echo $ac_n "checking for socket in -lsocket""... $ac_c" 1>&6 -echo "configure:1348: checking for socket in -lsocket" >&5 +echo "configure:1372: checking for socket in -lsocket" >&5 ac_lib_var=`echo socket'_'socket | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -1352,7 +1376,7 @@ else ac_save_LIBS="$LIBS" LIBS="-lsocket -lnsl $LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1391: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* eval "ac_cv_lib_$ac_lib_var=yes" else @@ -1391,14 +1415,14 @@ fi echo $ac_n "checking for library containing res_mkquery""... $ac_c" 1>&6 -echo "configure:1395: checking for library containing res_mkquery" >&5 +echo "configure:1419: checking for library containing res_mkquery" >&5 if eval "test \"`echo '$''{'ac_cv_search_res_mkquery'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_func_search_save_LIBS="$LIBS" ac_cv_search_res_mkquery="no" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1437: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_res_mkquery="none required" else @@ -1420,7 +1444,7 @@ rm -f conftest* test "$ac_cv_search_res_mkquery" = "no" && for i in resolv; do LIBS="-l$i $ac_func_search_save_LIBS" cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then +if { (eval echo configure:1459: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then rm -rf conftest* ac_cv_search_res_mkquery="-l$i" break @@ -1453,7 +1477,7 @@ else : fi echo $ac_n "checking how to run the C preprocessor""... $ac_c" 1>&6 -echo "configure:1457: checking how to run the C preprocessor" >&5 +echo "configure:1481: checking how to run the C preprocessor" >&5 # On Suns, sometimes $CPP names a directory. if test -n "$CPP" && test -d "$CPP"; then CPP= @@ -1468,13 +1492,13 @@ else # On the NeXT, cc -E runs the code through the compiler's parser, # not just through cpp. cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1478: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1502: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1485,13 +1509,13 @@ else rm -rf conftest* CPP="${CC-cc} -E -traditional-cpp" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1495: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1519: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1502,13 +1526,13 @@ else rm -rf conftest* CPP="${CC-cc} -nologo -E" cat > conftest.$ac_ext < Syntax Error EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1512: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1536: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then : @@ -1533,12 +1557,12 @@ fi echo "$ac_t""$CPP" 1>&6 echo $ac_n "checking for ANSI C header files""... $ac_c" 1>&6 -echo "configure:1537: checking for ANSI C header files" >&5 +echo "configure:1561: checking for ANSI C header files" >&5 if eval "test \"`echo '$''{'ac_cv_header_stdc'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1546,7 +1570,7 @@ else #include EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1550: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1574: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1563,7 +1587,7 @@ rm -f conftest* if test $ac_cv_header_stdc = yes; then # SunOS 4.x string.h does not declare mem*, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1581,7 +1605,7 @@ fi if test $ac_cv_header_stdc = yes; then # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. cat > conftest.$ac_ext < EOF @@ -1602,7 +1626,7 @@ if test "$cross_compiling" = yes; then : else cat > conftest.$ac_ext < #define ISLOWER(c) ('a' <= (c) && (c) <= 'z') @@ -1613,7 +1637,7 @@ if (XOR (islower (i), ISLOWER (i)) || toupper (i) != TOUPPER (i)) exit(2); exit (0); } EOF -if { (eval echo configure:1617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1641: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then : else @@ -1636,21 +1660,21 @@ EOF fi -for ac_hdr in poll.h +for ac_hdr in poll.h sys/devpoll.h sys/event.h do ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 -echo "configure:1644: checking for $ac_hdr" >&5 +echo "configure:1668: checking for $ac_hdr" >&5 if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out" -{ (eval echo configure:1654: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +{ (eval echo configure:1678: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` if test -z "$ac_err"; then rm -rf conftest* @@ -1678,14 +1702,14 @@ done echo $ac_n "checking whether byte ordering is bigendian""... $ac_c" 1>&6 -echo "configure:1682: checking whether byte ordering is bigendian" >&5 +echo "configure:1706: checking whether byte ordering is bigendian" >&5 if eval "test \"`echo '$''{'ac_cv_c_bigendian'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else ac_cv_c_bigendian=unknown # See if sys/param.h defines the BYTE_ORDER macro. cat > conftest.$ac_ext < #include @@ -1696,11 +1720,11 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:1700: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1724: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* # It does; now see whether it defined to BIG_ENDIAN or not. cat > conftest.$ac_ext < #include @@ -1711,7 +1735,7 @@ int main() { #endif ; return 0; } EOF -if { (eval echo configure:1715: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1739: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_c_bigendian=yes else @@ -1731,7 +1755,7 @@ if test "$cross_compiling" = yes; then { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1772: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_c_bigendian=no else @@ -1768,12 +1792,12 @@ EOF fi echo $ac_n "checking for size_t""... $ac_c" 1>&6 -echo "configure:1772: checking for size_t" >&5 +echo "configure:1796: checking for size_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_size_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -1801,12 +1825,12 @@ EOF fi echo $ac_n "checking whether time.h and sys/time.h may both be included""... $ac_c" 1>&6 -echo "configure:1805: checking whether time.h and sys/time.h may both be included" >&5 +echo "configure:1829: checking whether time.h and sys/time.h may both be included" >&5 if eval "test \"`echo '$''{'ac_cv_header_time'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1815,7 +1839,7 @@ int main() { struct tm *tp; ; return 0; } EOF -if { (eval echo configure:1819: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1843: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_header_time=yes else @@ -1836,12 +1860,12 @@ EOF fi echo $ac_n "checking whether struct tm is in sys/time.h or time.h""... $ac_c" 1>&6 -echo "configure:1840: checking whether struct tm is in sys/time.h or time.h" >&5 +echo "configure:1864: checking whether struct tm is in sys/time.h or time.h" >&5 if eval "test \"`echo '$''{'ac_cv_struct_tm'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #include @@ -1849,7 +1873,7 @@ int main() { struct tm *tp; tp->tm_sec; ; return 0; } EOF -if { (eval echo configure:1853: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:1877: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* ac_cv_struct_tm=time.h else @@ -1870,12 +1894,12 @@ EOF fi echo $ac_n "checking for uid_t in sys/types.h""... $ac_c" 1>&6 -echo "configure:1874: checking for uid_t in sys/types.h" >&5 +echo "configure:1898: checking for uid_t in sys/types.h" >&5 if eval "test \"`echo '$''{'ac_cv_type_uid_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < EOF @@ -1904,7 +1928,7 @@ EOF fi echo $ac_n "checking size of short""... $ac_c" 1>&6 -echo "configure:1908: checking size of short" >&5 +echo "configure:1932: checking size of short" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_short'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1912,7 +1936,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1923,7 +1947,7 @@ main() exit(0); } EOF -if { (eval echo configure:1927: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1951: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_short=`cat conftestval` else @@ -1943,7 +1967,7 @@ EOF echo $ac_n "checking size of int""... $ac_c" 1>&6 -echo "configure:1947: checking size of int" >&5 +echo "configure:1971: checking size of int" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_int'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1951,7 +1975,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -1962,7 +1986,7 @@ main() exit(0); } EOF -if { (eval echo configure:1966: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:1990: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_int=`cat conftestval` else @@ -1982,7 +2006,7 @@ EOF echo $ac_n "checking size of long""... $ac_c" 1>&6 -echo "configure:1986: checking size of long" >&5 +echo "configure:2010: checking size of long" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_long'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -1990,7 +2014,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -2001,7 +2025,7 @@ main() exit(0); } EOF -if { (eval echo configure:2005: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2029: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_long=`cat conftestval` else @@ -2021,7 +2045,7 @@ EOF echo $ac_n "checking size of void *""... $ac_c" 1>&6 -echo "configure:2025: checking size of void *" >&5 +echo "configure:2049: checking size of void *" >&5 if eval "test \"`echo '$''{'ac_cv_sizeof_void_p'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2029,7 +2053,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < main() @@ -2040,7 +2064,7 @@ main() exit(0); } EOF -if { (eval echo configure:2044: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2068: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sizeof_void_p=`cat conftestval` else @@ -2061,12 +2085,12 @@ EOF if test "$ac_cv_sizeof_int" = 2 ; then echo $ac_n "checking for int16_t""... $ac_c" 1>&6 -echo "configure:2065: checking for int16_t" >&5 +echo "configure:2089: checking for int16_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_int16_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2094,12 +2118,12 @@ EOF fi echo $ac_n "checking for u_int16_t""... $ac_c" 1>&6 -echo "configure:2098: checking for u_int16_t" >&5 +echo "configure:2122: checking for u_int16_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_u_int16_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2128,12 +2152,12 @@ fi elif test "$ac_cv_sizeof_short" = 2 ; then echo $ac_n "checking for int16_t""... $ac_c" 1>&6 -echo "configure:2132: checking for int16_t" >&5 +echo "configure:2156: checking for int16_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_int16_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2161,12 +2185,12 @@ EOF fi echo $ac_n "checking for u_int16_t""... $ac_c" 1>&6 -echo "configure:2165: checking for u_int16_t" >&5 +echo "configure:2189: checking for u_int16_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_u_int16_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2198,12 +2222,12 @@ else fi if test "$ac_cv_sizeof_int" = 4 ; then echo $ac_n "checking for int32_t""... $ac_c" 1>&6 -echo "configure:2202: checking for int32_t" >&5 +echo "configure:2226: checking for int32_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_int32_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2231,12 +2255,12 @@ EOF fi echo $ac_n "checking for u_int32_t""... $ac_c" 1>&6 -echo "configure:2235: checking for u_int32_t" >&5 +echo "configure:2259: checking for u_int32_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_u_int32_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2265,12 +2289,12 @@ fi elif test "$ac_cv_sizeof_short" = 4 ; then echo $ac_n "checking for int32_t""... $ac_c" 1>&6 -echo "configure:2269: checking for int32_t" >&5 +echo "configure:2293: checking for int32_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_int32_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2298,12 +2322,12 @@ EOF fi echo $ac_n "checking for u_int32_t""... $ac_c" 1>&6 -echo "configure:2302: checking for u_int32_t" >&5 +echo "configure:2326: checking for u_int32_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_u_int32_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2332,12 +2356,12 @@ fi elif test "$ac_cv_sizeof_long" = 4 ; then echo $ac_n "checking for int32_t""... $ac_c" 1>&6 -echo "configure:2336: checking for int32_t" >&5 +echo "configure:2360: checking for int32_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_int32_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2365,12 +2389,12 @@ EOF fi echo $ac_n "checking for u_int32_t""... $ac_c" 1>&6 -echo "configure:2369: checking for u_int32_t" >&5 +echo "configure:2393: checking for u_int32_t" >&5 if eval "test \"`echo '$''{'ac_cv_type_u_int32_t'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < #if STDC_HEADERS @@ -2401,9 +2425,57 @@ else { echo "configure: error: Cannot find a type with size of 32 bits" 1>&2; exit 1; } fi +echo $ac_n "checking for kqueue""... $ac_c" 1>&6 +echo "configure:2430: checking for kqueue" >&5 +if eval "test \"`echo '$''{'ac_cv_func_kqueue'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext < +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char kqueue(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_kqueue) || defined (__stub___kqueue) +choke me +#else +kqueue(); +#endif + +; return 0; } +EOF +if { (eval echo configure:2458: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_kqueue=yes" +else + echo "configure: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_kqueue=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'kqueue`\" = yes"; then + echo "$ac_t""yes" 1>&6 + : +else + echo "$ac_t""no" 1>&6 +fi + echo $ac_n "checking for restartable system calls""... $ac_c" 1>&6 -echo "configure:2407: checking for restartable system calls" >&5 +echo "configure:2479: checking for restartable system calls" >&5 if eval "test \"`echo '$''{'ac_cv_sys_restartable_syscalls'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2411,7 +2483,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext <&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2505: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then ac_cv_sys_restartable_syscalls=yes else @@ -2453,7 +2525,7 @@ fi echo $ac_n "checking for donuts""... $ac_c" 1>&6 -echo "configure:2457: checking for donuts" >&5 +echo "configure:2529: checking for donuts" >&5 echo "$ac_t""yes" 1>&6 for ac_prog in gawk mawk nawk awk @@ -2461,7 +2533,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2465: checking for $ac_word" >&5 +echo "configure:2537: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_prog_AWK'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2491,7 +2563,7 @@ test -n "$AWK" && break done echo $ac_n "checking whether ${MAKE-make} sets \${MAKE}""... $ac_c" 1>&6 -echo "configure:2495: checking whether ${MAKE-make} sets \${MAKE}" >&5 +echo "configure:2567: checking whether ${MAKE-make} sets \${MAKE}" >&5 set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y%./+-%__p_%'` if eval "test \"`echo '$''{'ac_cv_prog_make_${ac_make}_set'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2529,7 +2601,7 @@ fi # SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" # ./install, which can be erroneously created by make from ./install.sh. echo $ac_n "checking for a BSD compatible install""... $ac_c" 1>&6 -echo "configure:2533: checking for a BSD compatible install" >&5 +echo "configure:2605: checking for a BSD compatible install" >&5 if test -z "$INSTALL"; then if eval "test \"`echo '$''{'ac_cv_path_install'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 @@ -2582,7 +2654,7 @@ test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL_PROGRAM}' test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' echo $ac_n "checking whether ln -s works""... $ac_c" 1>&6 -echo "configure:2586: checking whether ln -s works" >&5 +echo "configure:2658: checking whether ln -s works" >&5 if eval "test \"`echo '$''{'ac_cv_prog_LN_S'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2607,7 +2679,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2611: checking for $ac_word" >&5 +echo "configure:2683: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_RMPROG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2648,7 +2720,7 @@ do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 -echo "configure:2652: checking for $ac_word" >&5 +echo "configure:2724: checking for $ac_word" >&5 if eval "test \"`echo '$''{'ac_cv_path_SHPROG'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2686,7 +2758,7 @@ test -n "$SHPROG" || SHPROG="/bin/sh" echo $ac_n "checking for posix non-blocking""... $ac_c" 1>&6 -echo "configure:2690: checking for posix non-blocking" >&5 +echo "configure:2762: checking for posix non-blocking" >&5 if eval "test \"`echo '$''{'unet_cv_sys_nonblocking_posix'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2694,7 +2766,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < #include @@ -2720,7 +2792,7 @@ int main(void) exit(1); } EOF -if { (eval echo configure:2724: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2796: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then unet_cv_sys_nonblocking_posix=yes else @@ -2742,7 +2814,7 @@ EOF else echo $ac_n "checking for bsd non-blocking""... $ac_c" 1>&6 -echo "configure:2746: checking for bsd non-blocking" >&5 +echo "configure:2818: checking for bsd non-blocking" >&5 if eval "test \"`echo '$''{'unet_cv_sys_nonblocking_bsd'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2750,7 +2822,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < #include @@ -2776,7 +2848,7 @@ int main(void) exit(1); } EOF -if { (eval echo configure:2780: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2852: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then unet_cv_sys_nonblocking_bsd=yes else @@ -2804,19 +2876,19 @@ EOF fi fi echo $ac_n "checking for posix signals""... $ac_c" 1>&6 -echo "configure:2808: checking for posix signals" >&5 +echo "configure:2880: checking for posix signals" >&5 if eval "test \"`echo '$''{'unet_cv_sys_signal_posix'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else cat > conftest.$ac_ext < int main() { sigaction(SIGTERM, (struct sigaction *)0L, (struct sigaction *)0L) ; return 0; } EOF -if { (eval echo configure:2820: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2892: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* unet_cv_sys_signal_posix=yes else @@ -2836,7 +2908,7 @@ EOF else echo $ac_n "checking for bsd reliable signals""... $ac_c" 1>&6 -echo "configure:2840: checking for bsd reliable signals" >&5 +echo "configure:2912: checking for bsd reliable signals" >&5 if eval "test \"`echo '$''{'unet_cv_sys_signal_bsd'+set}'`\" = set"; then echo $ac_n "(cached) $ac_c" 1>&6 else @@ -2844,7 +2916,7 @@ else { echo "configure: error: can not run test program while cross compiling" 1>&2; exit 1; } else cat > conftest.$ac_ext < int calls = 0; @@ -2862,7 +2934,7 @@ int main(void) exit (0); } EOF -if { (eval echo configure:2866: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null +if { (eval echo configure:2938: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext} && (./conftest; exit) 2>/dev/null then unet_cv_sys_signal_bsd=yes else @@ -2891,20 +2963,20 @@ fi fi echo $ac_n "checking if the compiler understands -pipe""... $ac_c" 1>&6 -echo "configure:2895: checking if the compiler understands -pipe" >&5 +echo "configure:2967: checking if the compiler understands -pipe" >&5 unet_cv_pipe_flags="$ac_cv_prog_gcc" if test "$ac_cv_prog_gcc" = no; then OLDCFLAGS="$CFLAGS" CFLAGS="$CFLAGS -pipe" cat > conftest.$ac_ext <&5; (eval $ac_compile) 2>&5; }; then +if { (eval echo configure:2980: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; }; then rm -rf conftest* unet_cv_pipe_flags=yes else @@ -2924,7 +2996,7 @@ fi echo $ac_n "checking for OS-dependent information""... $ac_c" 1>&6 -echo "configure:2928: checking for OS-dependent information" >&5 +echo "configure:3000: checking for OS-dependent information" >&5 case "$host" in *-linux*) echo "$ac_t""Linux ($host) found." 1>&6 @@ -2978,7 +3050,7 @@ esac echo $ac_n "checking whether to enable use of poll()""... $ac_c" 1>&6 -echo "configure:2982: checking whether to enable use of poll()" >&5 +echo "configure:3054: checking whether to enable use of poll()" >&5 # Check whether --enable-poll or --disable-poll was given. if test "${enable_poll+set}" = set; then enableval="$enable_poll" @@ -3005,10 +3077,14 @@ if test x"$unet_cv_enable_poll" = xyes; then #define USE_POLL EOF + ENGINE_C=engine_poll.c +else + ENGINE_C=engine_select.c fi + echo $ac_n "checking whether to enable debug mode""... $ac_c" 1>&6 -echo "configure:3012: checking whether to enable debug mode" >&5 +echo "configure:3088: checking whether to enable debug mode" >&5 # Check whether --enable-debug or --disable-debug was given. if test "${enable_debug+set}" = set; then enableval="$enable_debug" @@ -3032,7 +3108,7 @@ EOF fi echo $ac_n "checking whether to enable asserts""... $ac_c" 1>&6 -echo "configure:3036: checking whether to enable asserts" >&5 +echo "configure:3112: checking whether to enable asserts" >&5 # Check whether --enable-asserts or --disable-asserts was given. if test "${enable_asserts+set}" = set; then enableval="$enable_asserts" @@ -3056,7 +3132,7 @@ EOF fi echo $ac_n "checking whether to enable debugging symbols""... $ac_c" 1>&6 -echo "configure:3060: checking whether to enable debugging symbols" >&5 +echo "configure:3136: checking whether to enable debugging symbols" >&5 # Check whether --enable-symbols or --disable-symbols was given. if test "${enable_symbols+set}" = set; then enableval="$enable_symbols" @@ -3077,7 +3153,7 @@ if test x"$unet_cv_enable_symbols" = xyes; then fi echo $ac_n "checking whether to enable profiling support (gprof)""... $ac_c" 1>&6 -echo "configure:3081: checking whether to enable profiling support (gprof)" >&5 +echo "configure:3157: checking whether to enable profiling support (gprof)" >&5 # Check whether --enable-profile or --disable-profile was given. if test "${enable_profile+set}" = set; then enableval="$enable_profile" @@ -3097,8 +3173,50 @@ if test x"$unet_cv_enable_profile" = xyes; then CFLAGS="-pg $CFLAGS" fi +echo $ac_n "checking whether to enable pedantic compiler warnings""... $ac_c" 1>&6 +echo "configure:3178: checking whether to enable pedantic compiler warnings" >&5 +# Check whether --enable-pedantic or --disable-pedantic was given. +if test "${enable_pedantic+set}" = set; then + enableval="$enable_pedantic" + unet_cv_enable_pedantic=$enable_pedantic +else + if eval "test \"`echo '$''{'unet_cv_enable_pedantic'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + unet_cv_enable_pedantic=no +fi + +fi + +echo "$ac_t""$unet_cv_enable_pedantic" 1>&6 + +if test x"$unet_cv_enable_pedantic" = xyes; then + CFLAGS="-pedantic $CFLAGS" +fi + +echo $ac_n "checking whether to enable compiler warnings""... $ac_c" 1>&6 +echo "configure:3199: checking whether to enable compiler warnings" >&5 +# Check whether --enable-warnings or --disable-warnings was given. +if test "${enable_warnings+set}" = set; then + enableval="$enable_warnings" + unet_cv_enable_warnings=$enable_warnings +else + if eval "test \"`echo '$''{'unet_cv_enable_warnings'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + unet_cv_enable_warnings=no +fi + +fi + +echo "$ac_t""$unet_cv_enable_warnings" 1>&6 + +if test x"$unet_cv_enable_warnings" = xyes; then + CFLAGS="-Wall $CFLAGS" +fi + echo $ac_n "checking whether to enable inlining for a few critical functions""... $ac_c" 1>&6 -echo "configure:3102: checking whether to enable inlining for a few critical functions" >&5 +echo "configure:3220: checking whether to enable inlining for a few critical functions" >&5 # Check whether --enable-inlines or --disable-inlines was given. if test "${enable_inlines+set}" = set; then enableval="$enable_inlines" @@ -3121,8 +3239,68 @@ EOF fi +echo $ac_n "checking whether to enable the /dev/poll event engine""... $ac_c" 1>&6 +echo "configure:3244: checking whether to enable the /dev/poll event engine" >&5 +# Check whether --enable-devpoll or --disable-devpoll was given. +if test "${enable_devpoll+set}" = set; then + enableval="$enable_devpoll" + unet_cv_enable_devpoll=$enable_devpoll +else + if eval "test \"`echo '$''{'unet_cv_enable_devpoll'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + unet_cv_enable_devpoll=no +fi + +fi + + +if test x"$ac_cv_header_sys_devpoll_h" = xno; then + unet_cv_enable_devpoll=no +fi + +echo "$ac_t""$unet_cv_enable_devpoll" 1>&6 + +if test x"$unet_cv_enable_devpoll" != xno; then + cat >> confdefs.h <<\EOF +#define USE_DEVPOLL +EOF + + ENGINE_C="engine_devpoll.c $ENGINE_C" +fi + +echo $ac_n "checking whether to enable the kqueue event engine""... $ac_c" 1>&6 +echo "configure:3274: checking whether to enable the kqueue event engine" >&5 +# Check whether --enable-kqueue or --disable-kqueue was given. +if test "${enable_kqueue+set}" = set; then + enableval="$enable_kqueue" + unet_cv_enable_kqueue=$enable_kqueue +else + if eval "test \"`echo '$''{'unet_cv_enable_kqueue'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + unet_cv_enable_kqueue=no +fi + +fi + + +if test x"$ac_cv_header_sys_event_h" = xno -o x"$ac_cv_func_kqueue" = xno; then + unet_cv_enable_kqueue=no +fi + +echo "$ac_t""$unet_cv_enable_kqueue" 1>&6 + +if test x"$unet_cv_enable_kqueue" != xno; then + cat >> confdefs.h <<\EOF +#define USE_KQUEUE +EOF + + ENGINE_C="engine_kqueue.c $ENGINE_C" +fi + echo $ac_n "checking what name to give the symlink""... $ac_c" 1>&6 -echo "configure:3126: checking what name to give the symlink" >&5 +echo "configure:3304: checking what name to give the symlink" >&5 # Check whether --with-symlink or --without-symlink was given. if test "${with_symlink+set}" = set; then withval="$with_symlink" @@ -3154,7 +3332,7 @@ fi echo $ac_n "checking what permissions to set on the installed binary""... $ac_c" 1>&6 -echo "configure:3158: checking what permissions to set on the installed binary" >&5 +echo "configure:3336: checking what permissions to set on the installed binary" >&5 # Check whether --with-mode or --without-mode was given. if test "${with_mode+set}" = set; then withval="$with_mode" @@ -3180,7 +3358,7 @@ IRCDMODE=$unet_cv_with_mode unet_uid=`id | sed -e 's/.*uid=[0-9]*(//' -e 's/).*//' 2> /dev/null` echo $ac_n "checking which user should own the installed binary""... $ac_c" 1>&6 -echo "configure:3184: checking which user should own the installed binary" >&5 +echo "configure:3362: checking which user should own the installed binary" >&5 # Check whether --with-owner or --without-owner was given. if test "${with_owner+set}" = set; then withval="$with_owner" @@ -3206,7 +3384,7 @@ IRCDOWN=$unet_cv_with_owner unet_gid=`id | sed -e 's/.*gid=[0-9]*(//' -e 's/).*//' 2> /dev/null` echo $ac_n "checking which group should own the installed binary""... $ac_c" 1>&6 -echo "configure:3210: checking which group should own the installed binary" >&5 +echo "configure:3388: checking which group should own the installed binary" >&5 # Check whether --with-group or --without-group was given. if test "${with_group+set}" = set; then withval="$with_group" @@ -3238,7 +3416,7 @@ if test -f /etc/resolv.conf; then fi fi echo $ac_n "checking for site domain name""... $ac_c" 1>&6 -echo "configure:3242: checking for site domain name" >&5 +echo "configure:3420: checking for site domain name" >&5 # Check whether --with-domain or --without-domain was given. if test "${with_domain+set}" = set; then withval="$with_domain" @@ -3268,7 +3446,7 @@ EOF echo $ac_n "checking if chroot operation is desired""... $ac_c" 1>&6 -echo "configure:3272: checking if chroot operation is desired" >&5 +echo "configure:3450: checking if chroot operation is desired" >&5 # Check whether --with-chroot or --without-chroot was given. if test "${with_chroot+set}" = set; then withval="$with_chroot" @@ -3316,7 +3494,7 @@ prefix=$unet_save_prefix exec_prefix=$unet_save_exec_prefix echo $ac_n "checking where the binary will be for /restart""... $ac_c" 1>&6 -echo "configure:3320: checking where the binary will be for /restart" >&5 +echo "configure:3498: checking where the binary will be for /restart" >&5 if test x"$unet_cv_with_symlink" = xno; then unet_spath="$unet_bindir/ircd" else @@ -3338,7 +3516,7 @@ EOF echo $ac_n "checking what the data directory should be""... $ac_c" 1>&6 -echo "configure:3342: checking what the data directory should be" >&5 +echo "configure:3520: checking what the data directory should be" >&5 # Check whether --with-dpath or --without-dpath was given. if test "${with_dpath+set}" = set; then withval="$with_dpath" @@ -3381,7 +3559,7 @@ DPATH=$unet_cv_with_dpath echo $ac_n "checking where the default configuration file resides""... $ac_c" 1>&6 -echo "configure:3385: checking where the default configuration file resides" >&5 +echo "configure:3563: checking where the default configuration file resides" >&5 # Check whether --with-cpath or --without-cpath was given. if test "${with_cpath+set}" = set; then withval="$with_cpath" @@ -3423,7 +3601,7 @@ EOF echo $ac_n "checking where to put the debugging log if debugging enabled""... $ac_c" 1>&6 -echo "configure:3427: checking where to put the debugging log if debugging enabled" >&5 +echo "configure:3605: checking where to put the debugging log if debugging enabled" >&5 # Check whether --with-lpath or --without-lpath was given. if test "${with_lpath+set}" = set; then withval="$with_lpath" @@ -3469,7 +3647,7 @@ EOF unet_maxcon=`ulimit -Hn` unet_maxcon=`expr $unet_maxcon - 4` echo $ac_n "checking max connections""... $ac_c" 1>&6 -echo "configure:3473: checking max connections" >&5 +echo "configure:3651: checking max connections" >&5 # Check whether --with-maxcon or --without-maxcon was given. if test "${with_maxcon+set}" = set; then withval="$with_maxcon" @@ -3644,6 +3822,7 @@ s%@LN_S@%$LN_S%g s%@RMPROG@%$RMPROG%g s%@SHPROG@%$SHPROG%g s%@OSDEP_C@%$OSDEP_C%g +s%@ENGINE_C@%$ENGINE_C%g s%@INSTALL_RULE@%$INSTALL_RULE%g s%@SYMLINK@%$SYMLINK%g s%@IRCDMODE@%$IRCDMODE%g diff --git a/configure.in b/configure.in index 14b86d0..07db11f 100644 --- a/configure.in +++ b/configure.in @@ -76,6 +76,24 @@ if test x"$CFLAGS" != x"$unet_old_cflags"; then # If -pg was already there, force profiling to be enabled unet_cv_enable_profile=yes fi +dnl Notice the -Wall flag and deal accordingly +if test x"$CFLAGS" != x; then + unet_old_cflags=$CFLAGS + CFLAGS=`echo "$CFLAGS" | sed -e 's/-Wall//g'` +fi +if test x"$CFLAGS" != x"$unet_old_cflags"; then + # If -Wall was already there, force warnings to be enabled + unet_cv_enable_warnings=yes +fi +dnl Notice the -pedantic flag and deal accordingly +if test x"$CFLAGS" != x; then + unet_old_cflags=$CFLAGS + CFLAGS=`echo "$CFLAGS" | sed -e 's/-pedantic//g'` +fi +if test x"$CFLAGS" != x"$unet_old_cflags"; then + # If -pedantic was already there, force pedatic to be enabled + unet_cv_enable_pedantic=yes +fi dnl Checks for libraries. @@ -93,7 +111,7 @@ AC_SEARCH_LIBS(res_mkquery, resolv, , dnl Checks for header files. AC_HEADER_STDC -AC_CHECK_HEADERS(poll.h) +AC_CHECK_HEADERS(poll.h sys/devpoll.h sys/event.h) dnl Checks for typedefs, structures, and compiler characteristics dnl AC_C_CONST @@ -105,6 +123,7 @@ AC_TYPE_UID_T unet_CHECK_TYPE_SIZES dnl Checks for library functions. +AC_CHECK_FUNC(kqueue) dnl Do we have restarting syscalls ? AC_SYS_RESTARTABLE_SYSCALLS @@ -200,7 +219,11 @@ AC_MSG_RESULT([$unet_cv_enable_poll]) if test x"$unet_cv_enable_poll" = xyes; then AC_DEFINE([USE_POLL], , [Specify whether or not to use poll()]) + ENGINE_C=engine_poll.c +else + ENGINE_C=engine_select.c fi +AC_SUBST(ENGINE_C) dnl Now look for --enable-debug AC_MSG_CHECKING([whether to enable debug mode]) @@ -254,6 +277,32 @@ if test x"$unet_cv_enable_profile" = xyes; then CFLAGS="-pg $CFLAGS" fi +dnl Now check for --enable-pedantic +AC_MSG_CHECKING([whether to enable pedantic compiler warnings]) +AC_ARG_ENABLE([pedantic], +[ --enable-pedantic Enable pedantic warnings (add -pedantic to CFLAGS)], +[unet_cv_enable_pedantic=$enable_pedantic], +[AC_CACHE_VAL(unet_cv_enable_pedantic, +[unet_cv_enable_pedantic=no])]) +AC_MSG_RESULT([$unet_cv_enable_pedantic]) + +if test x"$unet_cv_enable_pedantic" = xyes; then + CFLAGS="-pedantic $CFLAGS" +fi + +dnl Now check for --enable-warnings +AC_MSG_CHECKING([whether to enable compiler warnings]) +AC_ARG_ENABLE([warnings], +[ --enable-warnings Enable warnings (add -Wall to CFLAGS)], +[unet_cv_enable_warnings=$enable_warnings], +[AC_CACHE_VAL(unet_cv_enable_warnings, +[unet_cv_enable_warnings=no])]) +AC_MSG_RESULT([$unet_cv_enable_warnings]) + +if test x"$unet_cv_enable_warnings" = xyes; then + CFLAGS="-Wall $CFLAGS" +fi + dnl --disable-inlines check... AC_MSG_CHECKING([whether to enable inlining for a few critical functions]) AC_ARG_ENABLE([inlines], @@ -267,6 +316,44 @@ if test x"$unet_cv_enable_inlines" = xyes; then AC_DEFINE([FORCEINLINE], , [Force inlining for a few critical functions]) fi +dnl --enable-devpoll check... +AC_MSG_CHECKING([whether to enable the /dev/poll event engine]) +AC_ARG_ENABLE([devpoll], +[ --enable-devpoll Enable the experimental /dev/poll-based engine], +[unet_cv_enable_devpoll=$enable_devpoll], +[AC_CACHE_VAL(unet_cv_enable_devpoll, +[unet_cv_enable_devpoll=no])]) + +if test x"$ac_cv_header_sys_devpoll_h" = xno; then + unet_cv_enable_devpoll=no +fi + +AC_MSG_RESULT([$unet_cv_enable_devpoll]) + +if test x"$unet_cv_enable_devpoll" != xno; then + AC_DEFINE([USE_DEVPOLL], , [Define to enable the /dev/poll engine]) + ENGINE_C="engine_devpoll.c $ENGINE_C" +fi + +dnl --enable-kqueue check... +AC_MSG_CHECKING([whether to enable the kqueue event engine]) +AC_ARG_ENABLE([kqueue], +[ --enable-kqueue Enable the experimental kqueue-based engine], +[unet_cv_enable_kqueue=$enable_kqueue], +[AC_CACHE_VAL(unet_cv_enable_kqueue, +[unet_cv_enable_kqueue=no])]) + +if test x"$ac_cv_header_sys_event_h" = xno -o x"$ac_cv_func_kqueue" = xno; then + unet_cv_enable_kqueue=no +fi + +AC_MSG_RESULT([$unet_cv_enable_kqueue]) + +if test x"$unet_cv_enable_kqueue" != xno; then + AC_DEFINE([USE_KQUEUE], , [Define to enable the kqueue engine]) + ENGINE_C="engine_kqueue.c $ENGINE_C" +fi + dnl --with-symlink lets us set the name of the symlink; defaults to "ircd" AC_MSG_CHECKING([what name to give the symlink]) AC_ARG_WITH([symlink], diff --git a/include/IPcheck.h b/include/IPcheck.h index a81747c..4062a90 100644 --- a/include/IPcheck.h +++ b/include/IPcheck.h @@ -20,12 +20,12 @@ struct Client; /* * Prototypes */ +extern void IPcheck_init(void); extern int IPcheck_local_connect(struct in_addr ip, time_t* next_target_out); extern void IPcheck_connect_fail(struct in_addr ip); extern void IPcheck_connect_succeeded(struct Client *cptr); extern int IPcheck_remote_connect(struct Client *cptr, int is_burst); extern void IPcheck_disconnect(struct Client *cptr); extern unsigned short IPcheck_nr(struct Client* cptr); -extern void IPcheck_expire(); #endif /* INCLUDED_ipcheck_h */ diff --git a/include/client.h b/include/client.h index 61a57d2..21b8b35 100644 --- a/include/client.h +++ b/include/client.h @@ -31,6 +31,9 @@ #ifndef INCLUDED_msgq_h #include "msgq.h" #endif +#ifndef INCLUDED_ircd_events_h +#include "ircd_events.h" +#endif #ifndef INCLUDED_ircd_handler_h #include "ircd_handler.h" #endif @@ -53,6 +56,7 @@ struct Whowas; struct DNSReply; struct hostent; struct Privs; +struct AuthRequest; /* * Structures @@ -110,11 +114,13 @@ struct Connection { * to which the allocation is tied to! *Never* refer to * these fields, if (from != self). */ + unsigned long con_magic; /* magic number */ struct Connection* con_next; /* Next connection with queued data */ struct Connection** con_prev_p; /* What points to us */ struct Client* con_client; /* Client associated with connection */ unsigned int con_count; /* Amount of data in buffer */ int con_fd; /* >= 0, for local clients */ + int con_freeflag; /* indicates if connection can be freed */ int con_error; /* last socket level error for client */ unsigned int con_snomask; /* mask for server messages */ time_t con_nextnick; /* Next time a nick change is allowed */ @@ -149,9 +155,15 @@ struct Connection { char con_passwd[PASSWDLEN + 1]; char con_buffer[BUFSIZE]; /* Incoming message buffer; or the error that caused this clients socket to be `dead' */ + struct Socket con_socket; /* socket descriptor for client */ + struct Timer con_proc; /* process latent messages from client */ + struct AuthRequest* con_auth; /* auth request for client */ }; +#define CONNECTION_MAGIC 0x12f955f3 + struct Client { + unsigned long cli_magic; /* magic number */ struct Client* cli_next; /* link in GlobalClientList */ struct Client* cli_prev; /* link in GlobalClientList */ struct Client* cli_hnext; /* link in hash table bucket or this */ @@ -182,6 +194,10 @@ struct Client { char cli_info[REALLEN + 1]; /* Free form additional client information */ }; +#define CLIENT_MAGIC 0x4ca08286 + +#define cli_verify(cli) ((cli)->cli_magic == CLIENT_MAGIC) +#define cli_magic(cli) ((cli)->cli_magic) #define cli_next(cli) ((cli)->cli_next) #define cli_prev(cli) ((cli)->cli_prev) #define cli_hnext(cli) ((cli)->cli_hnext) @@ -208,6 +224,7 @@ struct Client { #define cli_count(cli) ((cli)->cli_connect->con_count) #define cli_fd(cli) ((cli)->cli_connect->con_fd) +#define cli_freeflag(cli) ((cli)->cli_connect->con_freeflag) #define cli_error(cli) ((cli)->cli_connect->con_error) #define cli_snomask(cli) ((cli)->cli_connect->con_snomask) #define cli_nextnick(cli) ((cli)->cli_connect->con_nextnick) @@ -235,12 +252,18 @@ struct Client { #define cli_sockhost(cli) ((cli)->cli_connect->con_sockhost) #define cli_passwd(cli) ((cli)->cli_connect->con_passwd) #define cli_buffer(cli) ((cli)->cli_connect->con_buffer) +#define cli_socket(cli) ((cli)->cli_connect->con_socket) +#define cli_proc(cli) ((cli)->cli_connect->con_proc) +#define cli_auth(cli) ((cli)->cli_connect->con_auth) +#define con_verify(con) ((con)->con_magic == CONNECTION_MAGIC) +#define con_magic(con) ((con)->con_magic) #define con_next(con) ((con)->con_next) #define con_prev_p(con) ((con)->con_prev_p) #define con_client(con) ((con)->con_client) #define con_count(con) ((con)->con_count) #define con_fd(con) ((con)->con_fd) +#define con_freeflag(con) ((con)->con_freeflag) #define con_error(con) ((con)->con_error) #define con_snomask(con) ((con)->con_snomask) #define con_nextnick(con) ((con)->con_nextnick) @@ -268,6 +291,9 @@ struct Client { #define con_sockhost(con) ((con)->con_sockhost) #define con_passwd(con) ((con)->con_passwd) #define con_buffer(con) ((con)->con_buffer) +#define con_socket(con) ((con)->con_socket) +#define con_proc(con) ((con)->con_proc) +#define con_auth(con) ((con)->con_auth) #define STAT_CONNECTING 0x001 /* connecting to another server */ #define STAT_HANDSHAKE 0x002 /* pass - server sent */ @@ -407,6 +433,10 @@ struct Client { #define ClearWallops(x) (cli_flags(x) &= ~FLAGS_WALLOP) #define ClearServNotice(x) (cli_flags(x) &= ~FLAGS_SERVNOTICE) +/* free flags */ +#define FREEFLAG_SOCKET 0x0001 /* socket needs to be freed */ +#define FREEFLAG_TIMER 0x0002 /* timer needs to be freed */ + /* server notice stuff */ #define SNO_ADD 1 diff --git a/include/ircd.h b/include/ircd.h index df1a398..73c2890 100644 --- a/include/ircd.h +++ b/include/ircd.h @@ -59,6 +59,7 @@ extern time_t nextping; extern char* configfile; extern int debuglevel; extern char* debugmode; +extern int running; #endif /* INCLUDED_ircd_h */ diff --git a/include/ircd_events.h b/include/ircd_events.h new file mode 100644 index 0000000..54d034f --- /dev/null +++ b/include/ircd_events.h @@ -0,0 +1,247 @@ +#ifndef INCLUDED_ircd_events_h +#define INCLUDED_ircd_events_h +/* + * IRC - Internet Relay Chat, include/ircd_events.h + * Copyright (C) 2001 Kevin L. Mitchell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ + +#ifndef INCLUDED_config_h +#include "config.h" +#endif +#ifndef INCLUDED_sys_types_h +#include /* time_t */ +#define INCLUDED_sys_types_h +#endif + +struct Event; + +typedef void (*EventCallBack)(struct Event*); + +enum SocketState { + SS_CONNECTING, /* Connection in progress on socket */ + SS_LISTENING, /* Socket is a listening socket */ + SS_CONNECTED, /* Socket is a connected socket */ + SS_DATAGRAM, /* Socket is a datagram socket */ + SS_CONNECTDG, /* Socket is a connected datagram socket */ + SS_NOTSOCK /* Socket isn't a socket at all */ +}; + +enum TimerType { + TT_ABSOLUTE, /* timer that runs at a specific time */ + TT_RELATIVE, /* timer that runs so many seconds in the future */ + TT_PERIODIC /* timer that runs periodically */ +}; + +enum EventType { + ET_READ, /* Readable event detected */ + ET_WRITE, /* Writable event detected */ + ET_ACCEPT, /* Connection can be accepted */ + ET_CONNECT, /* Connection completed */ + ET_EOF, /* End-of-file on connection */ + ET_ERROR, /* Error condition detected */ + ET_SIGNAL, /* A signal was received */ + ET_EXPIRE, /* A timer expired */ + ET_DESTROY /* The generator is being destroyed */ +}; + +struct GenHeader { + struct GenHeader* gh_next; /* linked list of generators */ + struct GenHeader** gh_prev_p; +#ifdef IRCD_THREADED + struct GenHeader* gh_qnext; /* linked list of generators in queue */ + struct GenHeader** gh_qprev_p; + struct Event* gh_head; /* head of event queue */ + struct Event* gh_tail; /* tail of event queue */ +#endif + unsigned int gh_flags; /* generator flags */ + unsigned int gh_ref; /* reference count */ + EventCallBack gh_call; /* generator callback function */ + void* gh_data; /* extra data */ + union { + void* ed_ptr; /* engine data == pointer */ + int ed_int; /* engine data == integer */ + } gh_engdata;/* engine data */ +}; + +#define GEN_DESTROY 0x0001 /* generator is to be destroyed */ +#define GEN_MARKED 0x0002 /* generator is marked for destruction */ +#define GEN_ACTIVE 0x0004 /* generator is active */ + +struct Socket { + struct GenHeader s_header; /* generator information */ + enum SocketState s_state; /* state socket's in */ + unsigned int s_events; /* events socket is interested in */ + int s_fd; /* file descriptor for socket */ +}; + +#define SOCK_EVENT_READABLE 0x0001 /* interested in readable */ +#define SOCK_EVENT_WRITABLE 0x0002 /* interested in writable */ + +#define SOCK_EVENT_MASK (SOCK_EVENT_READABLE | SOCK_EVENT_WRITABLE) + +#define SOCK_ACTION_SET 0x0000 /* set interest set as follows */ +#define SOCK_ACTION_ADD 0x1000 /* add to interest set */ +#define SOCK_ACTION_DEL 0x2000 /* remove from interest set */ + +#define SOCK_ACTION_MASK 0x3000 /* mask out the actions */ + +#define s_state(sock) ((sock)->s_state) +#define s_events(sock) ((sock)->s_events) +#define s_fd(sock) ((sock)->s_fd) +#define s_data(sock) ((sock)->s_header.gh_data) +#define s_ed_int(sock) ((sock)->s_header.gh_engdata.ed_int) +#define s_ed_ptr(sock) ((sock)->s_header.gh_engdata.ed_ptr) +#define s_active(sock) ((sock)->s_header.gh_flags & GEN_ACTIVE) + +/* Note: The socket state overrides the socket event mask; that is, if + * it's an SS_CONNECTING socket, the engine selects its own definition + * of what that looks like and ignores s_events. s_events is meaningful + * only for SS_CONNECTED, SS_DATAGRAM, and SS_CONNECTDG, but may be set + * prior to the state transition, if desired. + */ + +struct Signal { + struct GenHeader sig_header; /* generator information */ + int sig_signal; /* signal number */ +}; + +#define sig_signal(sig) ((sig)->sig_signal) +#define sig_data(sig) ((sig)->sig_header.gh_data) +#define sig_ed_int(sig) ((sig)->sig_header.gh_engdata.ed_int) +#define sig_ed_ptr(sig) ((sig)->sig_header.gh_engdata.ed_ptr) +#define sig_active(sig) ((sig)->sig_header.gh_flags & GEN_ACTIVE) + +struct Timer { + struct GenHeader t_header; /* generator information */ + enum TimerType t_type; /* what type of timer this is */ + time_t t_value; /* value timer was added with */ + time_t t_expire; /* time at which timer expires */ +}; + +#define t_type(tim) ((tim)->t_type) +#define t_value(tim) ((tim)->t_value) +#define t_expire(tim) ((tim)->t_expire) +#define t_data(tim) ((tim)->t_header.gh_data) +#define t_ed_int(tim) ((tim)->t_header.gh_engdata.ed_int) +#define t_ed_ptr(tim) ((tim)->t_header.gh_engdata.ed_ptr) +#define t_active(tim) ((tim)->t_header.gh_flags & GEN_ACTIVE) + +struct Event { + struct Event* ev_next; /* linked list of events on queue */ + struct Event** ev_prev_p; + enum EventType ev_type; /* Event type */ + int ev_data; /* extra data, like errno value */ + union { + struct GenHeader* gen_header; /* Generator header */ + struct Socket* gen_socket; /* Socket generating event */ + struct Signal* gen_signal; /* Signal generating event */ + struct Timer* gen_timer; /* Timer generating event */ + } ev_gen; /* object generating event */ +}; + +#define ev_type(ev) ((ev)->ev_type) +#define ev_data(ev) ((ev)->ev_data) +#define ev_socket(ev) ((ev)->ev_gen.gen_socket) +#define ev_signal(ev) ((ev)->ev_gen.gen_signal) +#define ev_timer(ev) ((ev)->ev_gen.gen_timer) + +struct Generators { + struct Socket* g_socket; /* list of socket generators */ + struct Signal* g_signal; /* list of signal generators */ + struct Timer* g_timer; /* list of timer generators */ +}; + +/* returns 1 if successfully initialized, 0 if not */ +typedef int (*EngineInit)(int); + +/* Tell engine about new signal; set to 0 if engine doesn't know signals */ +typedef void (*EngineSignal)(struct Signal*); + +/* Tell engine about new socket */ +typedef int (*EngineAdd)(struct Socket*); + +/* Tell engine about socket's new_state */ +typedef void (*EngineState)(struct Socket*, enum SocketState new_state); + +/* Tell engine about socket's new_events */ +typedef void (*EngineEvents)(struct Socket*, unsigned int new_events); + +/* Tell engine a socket's going away */ +typedef void (*EngineDelete)(struct Socket*); + +/* The actual event loop */ +typedef void (*EngineLoop)(struct Generators*); + +struct Engine { + const char* eng_name; /* a name for the engine */ + EngineInit eng_init; /* initialize engine */ + EngineSignal eng_signal; /* express interest in a signal */ + EngineAdd eng_add; /* express interest in a socket */ + EngineState eng_state; /* mention a change in state to engine */ + EngineEvents eng_events; /* express interest in socket events */ + EngineDelete eng_closing; /* socket is being closed */ + EngineLoop eng_loop; /* actual event loop */ +}; + +#define gen_ref_inc(gen) (((struct GenHeader*) (gen))->gh_ref++) +#define gen_ref_dec(gen) \ +do { \ + struct GenHeader* _gen = (struct GenHeader*) (gen); \ + if (!--_gen->gh_ref && (_gen->gh_flags & GEN_DESTROY)) { \ + gen_dequeue(_gen); \ + event_generate(ET_DESTROY, _gen, 0); \ + } \ +} while (0) + +void gen_dequeue(void* arg); + +void event_init(int max_sockets); +void event_loop(void); +void event_generate(enum EventType type, void* arg, int data); + +void timer_add(struct Timer* timer, EventCallBack call, void* data, + enum TimerType type, time_t value); +void timer_del(struct Timer* timer); +void timer_chg(struct Timer* timer, enum TimerType type, time_t value); +void timer_run(void); +#define timer_next(gen) ((gen)->g_timer ? (gen)->g_timer->t_expire : 0) + +void signal_add(struct Signal* signal, EventCallBack call, void* data, + int sig); + +int socket_add(struct Socket* sock, EventCallBack call, void* data, + enum SocketState state, unsigned int events, int fd); +void socket_del(struct Socket* sock); +void socket_state(struct Socket* sock, enum SocketState state); +void socket_events(struct Socket* sock, unsigned int events); + +const char* engine_name(void); + +#ifdef DEBUGMODE +/* These routines pretty-print names for states and types for debug printing */ + +const char* state_to_name(enum SocketState state); +const char* timer_to_name(enum TimerType type); +const char* event_to_name(enum EventType type); +const char* gen_flags(unsigned int flags); +const char* sock_flags(unsigned int flags); + +#endif /* DEBUGMODE */ + +#endif /* INCLUDED_ircd_events_h */ diff --git a/include/ircd_osdep.h b/include/ircd_osdep.h index 981b902..2f9e463 100644 --- a/include/ircd_osdep.h +++ b/include/ircd_osdep.h @@ -37,7 +37,7 @@ extern IOResult os_sendv_nonb(int fd, struct MsgQ* buf, extern IOResult os_recvfrom_nonb(int fd, char* buf, unsigned int len, unsigned int* length_out, struct sockaddr_in* from_out); -extern int os_connect_nonb(int fd, const struct sockaddr_in* sin); +extern IOResult os_connect_nonb(int fd, const struct sockaddr_in* sin); extern int os_set_fdlimit(unsigned int max_descriptors); extern int os_set_listen(int fd, int backlog); extern int os_set_nonblocking(int fd); diff --git a/include/ircd_policy.h b/include/ircd_policy.h index 21e8b62..849aab0 100644 --- a/include/ircd_policy.h +++ b/include/ircd_policy.h @@ -98,6 +98,7 @@ #define HEAD_IN_SAND_STATS_R #define HEAD_IN_SAND_STATS_D #define HEAD_IN_SAND_STATS_d +#define HEAD_IN_SAND_STATS_E #define HEAD_IN_SAND_STATS_t #define HEAD_IN_SAND_STATS_T #define HEAD_IN_SAND_STATS_U diff --git a/include/list.h b/include/list.h index 509de68..afe4322 100644 --- a/include/list.h +++ b/include/list.h @@ -11,6 +11,7 @@ #endif struct Client; +struct Connection; struct Channel; struct ConfItem; @@ -53,6 +54,7 @@ extern struct SLink *make_link(void); extern struct SLink *find_user_link(struct SLink *lp, struct Client *ptr); extern void init_list(void); extern struct Client *make_client(struct Client *from, int status); +extern void free_connection(struct Connection *con); extern void free_client(struct Client *cptr); extern struct Server *make_server(struct Client *cptr); extern void remove_client_from_list(struct Client *cptr); diff --git a/include/listener.h b/include/listener.h index 8ba11e7..26d5e86 100644 --- a/include/listener.h +++ b/include/listener.h @@ -23,6 +23,9 @@ #ifndef INCLUDED_ircd_defs_h #include "ircd_defs.h" /* HOSTLEN */ #endif +#ifndef INCLUDED_ircd_events_h +#include "ircd_events.h" +#endif #ifndef INCLUDED_sys_types_h #include /* size_t, broken BSD system headers */ #define INCLUDED_sys_types_h @@ -46,11 +49,11 @@ struct Listener { time_t last_accept; /* last time listener accepted */ struct in_addr addr; /* virtual address or INADDR_ANY */ struct in_addr mask; /* listener hostmask */ + struct Socket socket; /* describe socket to event system */ }; extern struct Listener* ListenerPollList; /* GLOBAL - listener list */ -extern void accept_connection(struct Listener* listener); extern void add_listener(int port, const char* vaddr_ip, const char* mask, int is_server, int is_hidden); diff --git a/include/numeric.h b/include/numeric.h index a260249..4f90cd4 100644 --- a/include/numeric.h +++ b/include/numeric.h @@ -105,6 +105,7 @@ extern const struct Numeric* get_error_numeric(int err); #define RPL_SERVLIST 234 /* unused */ #define RPL_SERVLISTEND 235 /* unused */ +#define RPL_STATSENGINE 237 /* Undernet engine name */ #define RPL_STATSFLINE 238 /* Undernet feature lines */ /* RPL_STATSIAUTH 239 IRCnet extension */ /* RPL_STATSVLINE 240 IRCnet extension */ diff --git a/include/s_auth.h b/include/s_auth.h index 0b03355..d9aee6d 100644 --- a/include/s_auth.h +++ b/include/s_auth.h @@ -23,6 +23,9 @@ #include #define INCLUDED_sys_types_h #endif +#ifndef INCLUDED_ircd_events_h +#include "ircd_events.h" +#endif struct Client; @@ -32,8 +35,8 @@ struct AuthRequest { struct Client* client; /* pointer to client struct for request */ unsigned int flags; /* current state of request */ int fd; /* file descriptor for auth queries */ - int index; /* select / poll index */ - time_t timeout; /* time when query expires */ + struct Socket socket; /* socket descriptor for auth queries */ + struct Timer timeout; /* timeout timer for auth queries */ }; /* @@ -44,6 +47,11 @@ struct AuthRequest { #define AM_AUTH_PENDING 0x02 #define AM_DNS_PENDING 0x04 +#define AM_SOCKET 0x40 /* socket structure not destroyed */ +#define AM_TIMEOUT 0x80 /* timer structure not destroyed */ + +#define AM_FREE_MASK (AM_SOCKET | AM_TIMEOUT) + #define SetDNSPending(x) ((x)->flags |= AM_DNS_PENDING) #define ClearDNSPending(x) ((x)->flags &= ~AM_DNS_PENDING) #define IsDNSPending(x) ((x)->flags & AM_DNS_PENDING) @@ -63,10 +71,9 @@ struct AuthRequest { extern struct AuthRequest* AuthPollList; /* GLOBAL - auth queries pending io */ extern void start_auth(struct Client *); -extern void timeout_auth_queries(time_t now); extern void read_auth_reply(struct AuthRequest* req); extern void send_auth_query(struct AuthRequest* req); -extern void remove_auth_request(struct AuthRequest *req); +extern void destroy_auth_request(struct AuthRequest *req, int send_reports); #endif /* INCLUDED_s_auth_h */ diff --git a/include/s_bsd.h b/include/s_bsd.h index a0248c1..5952d48 100644 --- a/include/s_bsd.h +++ b/include/s_bsd.h @@ -46,6 +46,7 @@ extern const char* const SELECT_ERROR_MSG; extern const char* const CONNECT_ERROR_MSG; extern const char* const SETBUFS_ERROR_MSG; extern const char* const TOS_ERROR_MSG; +extern const char* const REGISTER_ERROR_MSG; extern int HighestFd; @@ -89,5 +90,6 @@ extern void init_server_identity(void); extern void close_connections(int close_stderr); extern int init_connection_limits(void); extern void set_virtual_host(struct in_addr addr); +extern void update_write(struct Client* cptr); #endif /* INCLUDED_s_bsd_h */ diff --git a/include/s_debug.h b/include/s_debug.h index f3bbfd7..9bc2560 100644 --- a/include/s_debug.h +++ b/include/s_debug.h @@ -27,16 +27,17 @@ struct Client; /* * defined debugging levels */ -#define DEBUG_FATAL 0 -#define DEBUG_ERROR 1 /* report_error() and other errors that are found */ -#define DEBUG_NOTICE 3 -#define DEBUG_DNS 4 /* used by all DNS related routines - a *lot* */ -#define DEBUG_INFO 5 /* general useful info */ -#define DEBUG_NUM 6 /* numerics */ -#define DEBUG_SEND 7 /* everything that is sent out */ -#define DEBUG_DEBUG 8 /* everything that is received */ -#define DEBUG_MALLOC 9 /* malloc/free calls */ -#define DEBUG_LIST 10 /* debug list use */ +#define DEBUG_FATAL 0 +#define DEBUG_ERROR 1 /* report_error() and other errors that are found */ +#define DEBUG_NOTICE 3 +#define DEBUG_DNS 4 /* used by all DNS related routines - a *lot* */ +#define DEBUG_INFO 5 /* general useful info */ +#define DEBUG_NUM 6 /* numerics */ +#define DEBUG_SEND 7 /* everything that is sent out */ +#define DEBUG_DEBUG 8 /* everything that is received */ +#define DEBUG_MALLOC 9 /* malloc/free calls */ +#define DEBUG_LIST 10 /* debug list use */ +#define DEBUG_ENGINE 11 /* debug event engine; can dump gigabyte logs */ /* * proto types diff --git a/include/uping.h b/include/uping.h index db0984c..afdf286 100644 --- a/include/uping.h +++ b/include/uping.h @@ -31,6 +31,9 @@ #ifndef INCLUDED_ircd_defs_h #include "ircd_defs.h" #endif +#ifndef INCLUDED_ircd_events_h +#include "ircd_events.h" +#endif struct Client; struct ConfItem; @@ -46,15 +49,22 @@ struct UPing char active; /* ping active flag */ struct Client* client; /* who requested the pings */ time_t lastsent; /* when last ping was sent */ - time_t timeout; /* current ping timeout time */ int ms_min; /* minimum time in milliseconds */ int ms_ave; /* average time in milliseconds */ int ms_max; /* maximum time in milliseconds */ int index; /* index into poll array */ + struct Socket socket; /* socket structure */ + struct Timer sender; /* timer telling when next to send a ping */ + struct Timer killer; /* timer to kill us */ + unsigned int freeable; /* zero when structure can be free()'d */ char name[HOSTLEN + 1]; /* server name to poing */ char buf[BUFSIZE]; /* buffer to hold ping times */ }; +#define UPING_PENDING_SOCKET 0x01 /* pending socket destruction event */ +#define UPING_PENDING_SENDER 0x02 /* pending sender destruction event */ +#define UPING_PENDING_KILLER 0x04 /* pending killer destruction event */ + extern int UPingFileDescriptor; extern int uping_init(void); diff --git a/ircd/IPcheck.c b/ircd/IPcheck.c index 3d850d8..e1f052d 100644 --- a/ircd/IPcheck.c +++ b/ircd/IPcheck.c @@ -30,6 +30,7 @@ #include "msg.h" #include "numnicks.h" /* NumNick, NumServ (GODMODE) */ #include "ircd_alloc.h" +#include "ircd_events.h" #include "s_debug.h" /* Debug */ #include "s_user.h" /* TARGET_DELAY */ #include "send.h" @@ -71,6 +72,8 @@ struct IPRegistryEntry { static struct IPRegistryEntry* hashTable[IP_REGISTRY_TABLE_SIZE]; static struct IPRegistryEntry* freeList = 0; +static struct Timer expireTimer; + static unsigned int ip_registry_hash(unsigned int ip) { return ((ip >> 16) ^ ip) & (IP_REGISTRY_TABLE_SIZE - 1); @@ -168,15 +171,16 @@ static void ip_registry_expire_entry(struct IPRegistryEntry* entry) } } -/* - * ip_registry_expire - */ -static void ip_registry_expire() +/* Callback to run an expiry of the IPcheck registry */ +static void ip_registry_expire(struct Event* ev) { int i; struct IPRegistryEntry* entry; struct IPRegistryEntry* entry_next; + assert(ET_EXPIRE == ev_type(ev)); + assert(0 != ev_timer(ev)); + for (i = 0; i < IP_REGISTRY_TABLE_SIZE; ++i) { for (entry = hashTable[i]; entry; entry = entry_next) { entry_next = entry->next; @@ -186,6 +190,16 @@ static void ip_registry_expire() } } +/* + * IPcheck_init() + * + * Initializes the registry timer + */ +void IPcheck_init(void) +{ + timer_add(&expireTimer, ip_registry_expire, 0, TT_PERIODIC, 60); +} + /* * IPcheck_local_connect * @@ -349,8 +363,8 @@ void ip_registry_connect_succeeded(struct Client *cptr) free_targets = entry->target->count; tr = " tr"; } - sendcmdto_one(&me, CMD_NOTICE, cptr, ":on %u ca %u(%u) ft %u(%u)%s", - entry->connected, entry->attempts, IPCHECK_CLONE_LIMIT, + sendcmdto_one(&me, CMD_NOTICE, cptr, "%C :on %u ca %u(%u) ft %u(%u)%s", + cptr, entry->connected, entry->attempts, IPCHECK_CLONE_LIMIT, free_targets, STARTTARGETS, tr); } @@ -554,14 +568,3 @@ unsigned short IPcheck_nr(struct Client *cptr) assert(0 != cptr); return ip_registry_count(cli_ip(cptr).s_addr); } - -void IPcheck_expire() -{ - static time_t next_expire = 0; - if (next_expire < CurrentTime) { - ip_registry_expire(); - next_expire = CurrentTime + 60; - } -} - - diff --git a/ircd/Makefile.in b/ircd/Makefile.in index 706fdad..0a4f636 100644 --- a/ircd/Makefile.in +++ b/ircd/Makefile.in @@ -40,6 +40,7 @@ MKDIR = mkdir TOUCH = touch GREP = grep OSDEP_C = @OSDEP_C@ +ENGINE_C = @ENGINE_C@ @SET_MAKE@ BINDIR = @bindir@ @@ -68,6 +69,12 @@ OSDEP_SRC = \ os_generic.c \ os_solaris.c +ENGINE_SRC = \ + engine_devpoll.c \ + engine_poll.c \ + engine_kqueue.c \ + engine_select.c + IRCD_SRC = \ IPcheck.c \ channel.c \ @@ -81,6 +88,7 @@ IRCD_SRC = \ hash.c \ ircd.c \ ircd_alloc.c \ + ircd_events.c \ ircd_features.c \ ircd_log.c \ ircd_relay.c \ @@ -188,11 +196,11 @@ IRCD_SRC = \ whocmds.c \ whowas.c -SRC = ${IRCD_SRC} ${OSDEP_C} +SRC = ${IRCD_SRC} ${OSDEP_C} ${ENGINE_C} OBJS = ${SRC:%.c=%.o} -DEP_SRC = ${IRCD_SRC} ${OSDEP_SRC} +DEP_SRC = ${IRCD_SRC} ${OSDEP_SRC} ${ENGINE_SRC} all: ( cd ..; make -f Makefile ) @@ -327,83 +335,93 @@ depend: IPcheck.o: IPcheck.c ../config.h ../include/IPcheck.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/ircd.h \ - ../include/struct.h ../include/msg.h ../include/numnicks.h \ - ../include/ircd_alloc.h ../include/s_debug.h ../include/s_user.h \ - ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd.h ../include/struct.h ../include/msg.h \ + ../include/numnicks.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/s_debug.h ../include/s_user.h ../include/send.h channel.o: channel.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_snprintf.h ../include/ircd_string.h ../include/list.h \ - ../include/match.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/querycmds.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ - ../include/s_user.h ../include/send.h ../include/sprintf_irc.h \ - ../include/support.h ../include/sys.h ../include/whowas.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_chattr.h \ + ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_string.h ../include/list.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/querycmds.h ../include/s_bsd.h ../include/s_conf.h \ + ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ + ../include/send.h ../include/sprintf_irc.h ../include/support.h \ + ../include/sys.h ../include/whowas.h class.o: class.c ../config.h ../include/class.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_features.h \ - ../include/ircd_reply.h ../include/list.h ../include/numeric.h \ - ../include/s_conf.h ../include/s_debug.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_features.h ../include/ircd_reply.h ../include/list.h \ + ../include/numeric.h ../include/s_conf.h ../include/s_debug.h \ + ../include/send.h client.o: client.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/class.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/class.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ ../include/ircd_reply.h ../include/list.h ../include/numeric.h \ ../include/s_conf.h ../include/s_debug.h ../include/send.h crule.o: crule.c ../config.h ../include/crule.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ - ../include/ircd_string.h ../include/match.h ../include/s_bsd.h \ - ../include/s_debug.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_chattr.h ../include/ircd_string.h ../include/match.h \ + ../include/s_bsd.h ../include/s_debug.h dbuf.o: dbuf.c ../config.h ../include/dbuf.h ../include/ircd_alloc.h \ - ../include/ircd_chattr.h ../include/ircd_features.h ../include/send.h \ - ../include/sys.h + ../include/fda.h ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/send.h ../include/sys.h fda.o: fda.c ../config.h fileio.o: fileio.c ../config.h ../include/fileio.h \ - ../include/ircd_alloc.h + ../include/ircd_alloc.h ../include/fda.h gline.o: gline.c ../config.h ../include/gline.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_log.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ ../include/numeric.h ../include/s_bsd.h ../include/s_debug.h \ ../include/s_misc.h ../include/send.h ../include/support.h \ ../include/msg.h ../include/numnicks.h ../include/sys.h hash.o: hash.c ../config.h ../include/hash.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/channel.h \ - ../include/ircd_chattr.h ../include/ircd_string.h ../include/ircd.h \ - ../include/struct.h ../include/msg.h ../include/send.h \ - ../include/support.h ../include/sys.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/channel.h ../include/ircd_chattr.h \ + ../include/ircd_string.h ../include/ircd.h ../include/struct.h \ + ../include/msg.h ../include/send.h ../include/support.h \ + ../include/sys.h ircd.o: ircd.c ../config.h ../include/ircd.h ../include/struct.h \ ../include/ircd_defs.h ../include/IPcheck.h ../include/class.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/crule.h ../include/hash.h \ - ../include/ircd_alloc.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_signal.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/jupe.h ../include/list.h \ - ../include/match.h ../include/motd.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/parse.h \ - ../include/res.h ../include/s_auth.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ - ../include/send.h ../include/sys.h ../include/uping.h \ - ../include/userload.h ../include/version.h ../include/whowas.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/crule.h \ + ../include/hash.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_signal.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/jupe.h \ + ../include/list.h ../include/match.h ../include/motd.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/parse.h ../include/res.h ../include/s_auth.h \ + ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \ + ../include/s_misc.h ../include/send.h ../include/sys.h \ + ../include/uping.h ../include/userload.h ../include/version.h \ + ../include/whowas.h ircd_alloc.o: ircd_alloc.c ../config.h ../include/ircd_alloc.h \ - ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/fda.h ../include/ircd_string.h ../include/ircd_chattr.h \ ../include/s_debug.h ../include/ircd_defs.h +ircd_events.o: ircd_events.c ../config.h ../include/ircd_events.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_defs.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_log.h \ + ../include/ircd_snprintf.h ../include/s_debug.h ircd_features.o: ircd_features.c ../config.h \ ../include/ircd_features.h ../include/channel.h \ ../include/ircd_defs.h ../include/class.h ../include/client.h \ - ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_log.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ ../include/motd.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/random.h ../include/s_bsd.h \ @@ -411,88 +429,91 @@ ircd_features.o: ircd_features.c ../config.h \ ../include/support.h ../include/sys.h ../include/whowas.h ircd_log.o: ircd_log.c ../config.h ../include/ircd_log.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/ircd_alloc.h \ - ../include/ircd_reply.h ../include/ircd_snprintf.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/ircd.h \ - ../include/struct.h ../include/numeric.h ../include/s_debug.h \ - ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_reply.h \ + ../include/ircd_snprintf.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/ircd.h ../include/struct.h \ + ../include/numeric.h ../include/s_debug.h ../include/send.h ircd_relay.o: ircd_relay.c ../config.h ../include/ircd_relay.h \ ../include/channel.h ../include/ircd_defs.h ../include/client.h \ - ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_reply.h \ + ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/match.h ../include/msg.h \ ../include/numeric.h ../include/numnicks.h ../include/s_debug.h \ ../include/s_misc.h ../include/s_user.h ../include/send.h ircd_reply.o: ircd_reply.c ../config.h ../include/ircd_reply.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_snprintf.h ../include/msg.h \ - ../include/numeric.h ../include/s_conf.h ../include/s_debug.h \ - ../include/send.h -ircd_signal.o: ircd_signal.c ../config.h ../include/ircd_signal.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_defs.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_snprintf.h \ + ../include/msg.h ../include/numeric.h ../include/s_conf.h \ + ../include/s_debug.h ../include/send.h +ircd_signal.o: ircd_signal.c ../config.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_defs.h ../include/ircd_events.h \ + ../include/ircd_signal.h ../include/s_conf.h ircd_snprintf.o: ircd_snprintf.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/channel.h \ - ../include/ircd_snprintf.h ../include/struct.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/channel.h ../include/ircd_snprintf.h ../include/struct.h ircd_string.o: ircd_string.c ../config.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/ircd_defs.h ../include/ircd_log.h \ chattr.tab.c ircd_xopen.o: ircd_xopen.c ../config.h ../include/ircd_xopen.h jupe.o: jupe.c ../config.h ../include/jupe.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_bsd.h \ - ../include/s_misc.h ../include/send.h ../include/support.h \ - ../include/sys.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/fda.h ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_bsd.h ../include/s_misc.h ../include/send.h \ + ../include/support.h ../include/sys.h list.o: list.c ../config.h ../include/list.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h \ - ../include/listener.h ../include/match.h ../include/numeric.h \ - ../include/res.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ - ../include/send.h ../include/support.h ../include/whowas.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/listener.h ../include/match.h \ + ../include/numeric.h ../include/res.h ../include/s_auth.h \ + ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \ + ../include/s_misc.h ../include/s_user.h ../include/send.h \ + ../include/support.h ../include/whowas.h listener.o: listener.c ../config.h ../include/listener.h \ - ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_features.h ../include/ircd_osdep.h \ + ../include/ircd_defs.h ../include/ircd_events.h ../include/client.h \ + ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/fda.h ../include/ircd_features.h ../include/ircd_osdep.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/numeric.h ../include/s_bsd.h \ ../include/s_conf.h ../include/s_misc.h ../include/send.h \ ../include/sprintf_irc.h ../include/sys.h m_admin.o: m_admin.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ - ../include/s_user.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_conf.h ../include/s_user.h m_away.o: m_away.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ - ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_user.h ../include/send.h m_burst.o: m_burst.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/list.h ../include/match.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_conf.h ../include/s_misc.h ../include/send.h \ - ../include/support.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ + ../include/match.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_conf.h ../include/s_misc.h \ + ../include/send.h ../include/support.h m_clearmode.o: m_clearmode.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/channel.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/channel.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ ../include/ircd_features.h ../include/ircd_log.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/list.h ../include/msg.h \ @@ -500,162 +521,175 @@ m_clearmode.o: m_clearmode.c ../config.h ../include/client.h \ ../include/support.h m_close.o: m_close.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_reply.h ../include/numeric.h ../include/s_bsd.h \ - ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_reply.h ../include/numeric.h \ + ../include/s_bsd.h ../include/send.h m_connect.o: m_connect.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/crule.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/jupe.h \ - ../include/match.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_user.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/crule.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/jupe.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_bsd.h ../include/s_conf.h ../include/s_user.h \ + ../include/send.h m_cprivmsg.o: m_cprivmsg.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/s_user.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/s_user.h m_create.o: m_create.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_user.h ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_user.h ../include/send.h m_defaults.o: m_defaults.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_reply.h ../include/numeric.h ../include/numnicks.h \ - ../include/send.h ../include/supported.h ../include/channel.h \ - ../include/version.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_reply.h ../include/numeric.h \ + ../include/numnicks.h ../include/send.h ../include/supported.h \ + ../include/channel.h ../include/version.h m_destruct.o: m_destruct.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h m_desynch.o: m_desynch.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_bsd.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_bsd.h \ + ../include/send.h m_die.o: m_die.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_bsd.h ../include/send.h m_endburst.o: m_endburst.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/send.h m_error.o: m_error.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_debug.h \ - ../include/s_misc.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/fda.h ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_debug.h ../include/s_misc.h ../include/send.h m_get.o: m_get.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ ../include/send.h m_gline.o: m_gline.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/gline.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ - ../include/s_misc.h ../include/send.h ../include/support.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/gline.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_conf.h ../include/s_misc.h ../include/send.h \ + ../include/support.h m_help.o: m_help.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h m_info.o: m_info.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_misc.h ../include/s_user.h \ ../include/s_conf.h ../include/send.h ../include/version.h m_invite.o: m_invite.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_user.h ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/list.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ + ../include/send.h m_ison.o: m_ison.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/numeric.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/numeric.h ../include/send.h m_join.o: m_join.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/gline.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ - ../include/ircd_reply.h ../include/ircd_string.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_debug.h \ - ../include/s_user.h ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/gline.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h \ + ../include/ircd_features.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_debug.h ../include/s_user.h \ + ../include/send.h m_jupe.o: m_jupe.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/jupe.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ - ../include/s_misc.h ../include/send.h ../include/support.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/jupe.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_features.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_conf.h ../include/s_misc.h ../include/send.h \ + ../include/support.h m_kick.o: m_kick.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/send.h m_kill.o: m_kill.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_misc.h \ - ../include/send.h ../include/whowas.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_misc.h ../include/send.h \ + ../include/whowas.h m_links.o: m_links.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_policy.h ../include/ircd_reply.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_policy.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ ../include/msg.h ../include/numeric.h ../include/numnicks.h \ ../include/s_user.h ../include/send.h m_list.o: m_list.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ - ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_chattr.h \ + ../include/ircd_features.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_bsd.h \ + ../include/send.h m_lusers.o: m_lusers.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/querycmds.h \ ../include/ircd_features.h ../include/s_user.h ../include/s_serv.h \ ../include/send.h m_map.o: m_map.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_policy.h ../include/ircd_reply.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_policy.h ../include/ircd_reply.h \ ../include/ircd_snprintf.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/list.h ../include/match.h \ ../include/msg.h ../include/numeric.h ../include/s_user.h \ @@ -663,237 +697,255 @@ m_map.o: m_map.c ../config.h ../include/client.h \ ../include/ircd_features.h m_mode.o: m_mode.c ../config.h ../include/handlers.h \ ../include/channel.h ../include/ircd_defs.h ../include/client.h \ - ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_conf.h ../include/s_debug.h \ ../include/s_user.h ../include/send.h m_motd.o: m_motd.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/match.h ../include/motd.h \ ../include/msg.h ../include/numeric.h ../include/numnicks.h \ ../include/s_conf.h ../include/class.h ../include/s_user.h \ ../include/send.h m_names.o: m_names.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ - ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_user.h ../include/send.h m_nick.o: m_nick.c ../config.h ../include/IPcheck.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_chattr.h \ - ../include/ircd_reply.h ../include/ircd_string.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_user.h ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_chattr.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_user.h ../include/send.h m_notice.o: m_notice.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd_chattr.h \ - ../include/ircd_relay.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/send.h ../include/handlers.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_chattr.h ../include/ircd_relay.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/send.h \ + ../include/handlers.h m_oper.o: m_oper.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/ircd_xopen.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ - ../include/s_conf.h ../include/s_debug.h ../include/s_user.h \ - ../include/s_misc.h ../include/send.h ../include/support.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/ircd_xopen.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/querycmds.h ../include/s_conf.h \ + ../include/s_debug.h ../include/s_user.h ../include/s_misc.h \ + ../include/send.h ../include/support.h m_opmode.o: m_opmode.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/channel.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/channel.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_features.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/send.h m_part.o: m_part.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h \ - ../include/numeric.h ../include/numnicks.h ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ + ../include/send.h m_pass.o: m_pass.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/send.h m_ping.o: m_ping.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/ircd.h \ - ../include/struct.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_debug.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/ircd.h ../include/struct.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_debug.h ../include/send.h m_pong.o: m_pong.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_user.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ + ../include/send.h m_privmsg.o: m_privmsg.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_features.h \ - ../include/ircd_relay.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h \ + ../include/ircd_features.h ../include/ircd_relay.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/send.h m_privs.o: m_privs.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ - ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h m_proto.o: m_proto.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ - ../include/ircd_reply.h ../include/ircd_string.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_debug.h \ - ../include/s_misc.h ../include/send.h ../include/supported.h \ - ../include/channel.h ../include/version.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_chattr.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_debug.h ../include/s_misc.h \ + ../include/send.h ../include/supported.h ../include/channel.h \ + ../include/version.h m_quit.o: m_quit.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/struct.h ../include/s_misc.h \ - ../include/ircd_reply.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/struct.h \ + ../include/s_misc.h ../include/ircd_reply.h m_rehash.o: m_rehash.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/motd.h \ ../include/numeric.h ../include/s_conf.h ../include/send.h m_reset.o: m_reset.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ ../include/send.h m_restart.o: m_restart.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_log.h ../include/ircd_reply.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_log.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/ircd_chattr.h \ ../include/numeric.h ../include/numnicks.h ../include/send.h m_rping.o: m_rping.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/opercmds.h ../include/s_user.h \ - ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \ + ../include/s_user.h ../include/send.h m_rpong.o: m_rpong.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/opercmds.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \ + ../include/send.h m_server.o: m_server.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_log.h ../include/ircd_features.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/jupe.h ../include/list.h \ - ../include/match.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/querycmds.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ - ../include/s_serv.h ../include/send.h ../include/userload.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_log.h \ + ../include/ircd_features.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/jupe.h \ + ../include/list.h ../include/match.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ + ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \ + ../include/s_misc.h ../include/s_serv.h ../include/send.h \ + ../include/userload.h m_set.o: m_set.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/numeric.h ../include/numnicks.h \ ../include/send.h m_settime.o: m_settime.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_reply.h ../include/ircd_snprintf.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_user.h ../include/send.h +m_silence.o: m_silence.c ../config.h ../include/channel.h \ + ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/list.h ../include/msg.h \ ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ ../include/send.h -m_silence.o: m_silence.c ../config.h ../include/channel.h \ - ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_user.h ../include/send.h m_squit.o: m_squit.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_chattr.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/numeric.h ../include/numnicks.h \ - ../include/match.h ../include/s_debug.h ../include/s_misc.h \ - ../include/s_user.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_chattr.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/numeric.h \ + ../include/numnicks.h ../include/match.h ../include/s_debug.h \ + ../include/s_misc.h ../include/s_user.h ../include/send.h m_stats.o: m_stats.c ../config.h ../include/handlers.h \ ../include/s_stats.h ../include/channel.h ../include/ircd_defs.h \ ../include/class.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/gline.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ - ../include/ircd_features.h ../include/ircd_policy.h \ - ../include/ircd_reply.h ../include/ircd_string.h ../include/list.h \ - ../include/listener.h ../include/match.h ../include/motd.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/opercmds.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_debug.h ../include/s_misc.h ../include/s_serv.h \ - ../include/s_user.h ../include/send.h ../include/userload.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/gline.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/ircd_policy.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/list.h ../include/listener.h \ + ../include/match.h ../include/motd.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \ + ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \ + ../include/s_misc.h ../include/s_serv.h ../include/s_user.h \ + ../include/send.h ../include/userload.h m_time.o: m_time.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_misc.h ../include/s_user.h \ ../include/send.h m_topic.o: m_topic.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/send.h m_trace.o: m_trace.c ../config.h ../include/class.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_bsd.h \ + ../include/s_conf.h ../include/s_user.h ../include/send.h \ + ../include/version.h +m_uping.o: m_uping.c ../config.h ../include/client.h \ + ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_bsd.h ../include/s_conf.h ../include/s_user.h \ - ../include/send.h ../include/version.h -m_uping.o: m_uping.c ../config.h ../include/client.h \ - ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ - ../include/s_user.h ../include/send.h ../include/uping.h + ../include/s_conf.h ../include/s_user.h ../include/send.h \ + ../include/uping.h m_user.o: m_user.c ../config.h ../include/handlers.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_chattr.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ - ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_chattr.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_user.h ../include/send.h m_userhost.o: m_userhost.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h \ - ../include/numeric.h ../include/s_user.h ../include/struct.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/numeric.h ../include/s_user.h \ + ../include/struct.h m_userip.o: m_userip.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h \ - ../include/numeric.h ../include/s_user.h ../include/struct.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/numeric.h ../include/s_user.h \ + ../include/struct.h m_version.o: m_version.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_features.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_features.h \ ../include/ircd_reply.h ../include/ircd_string.h \ ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ ../include/numnicks.h ../include/s_debug.h ../include/s_user.h \ @@ -901,108 +953,113 @@ m_version.o: m_version.c ../config.h ../include/client.h \ ../include/version.h m_wallchops.o: m_wallchops.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ - ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/s_user.h ../include/send.h m_wallops.o: m_wallops.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/send.h m_wallusers.o: m_wallusers.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ - ../include/numeric.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ + ../include/send.h m_who.o: m_who.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_chattr.h \ - ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/match.h ../include/numeric.h \ - ../include/numnicks.h ../include/send.h ../include/support.h \ - ../include/whocmds.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_chattr.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/match.h \ + ../include/numeric.h ../include/numnicks.h ../include/send.h \ + ../include/support.h ../include/whocmds.h m_whois.o: m_whois.c ../config.h ../include/channel.h \ ../include/ircd_defs.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_policy.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ - ../include/send.h ../include/whocmds.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_policy.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_user.h ../include/send.h ../include/whocmds.h m_whowas.o: m_whowas.c ../config.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/s_user.h ../include/s_misc.h \ - ../include/send.h ../include/whowas.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_user.h \ + ../include/s_misc.h ../include/send.h ../include/whowas.h match.o: match.c ../config.h ../include/match.h \ ../include/ircd_chattr.h motd.o: motd.c ../config.h ../include/motd.h ../include/class.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/fileio.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_features.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_conf.h ../include/s_debug.h ../include/s_user.h \ - ../include/send.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/fileio.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_features.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/match.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ + ../include/s_debug.h ../include/s_user.h ../include/send.h msgq.o: msgq.c ../config.h ../include/msgq.h ../include/ircd_defs.h \ - ../include/ircd_alloc.h ../include/ircd_snprintf.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_snprintf.h \ ../include/s_debug.h numnicks.o: numnicks.c ../config.h ../include/numnicks.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/match.h ../include/s_bsd.h \ - ../include/s_debug.h ../include/s_misc.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/fda.h ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/match.h ../include/s_bsd.h ../include/s_debug.h \ + ../include/s_misc.h opercmds.o: opercmds.c ../config.h ../include/opercmds.h \ ../include/class.h ../include/client.h ../include/ircd_defs.h \ - ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_chattr.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/listener.h ../include/match.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ - ../include/send.h + ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_chattr.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/listener.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/s_conf.h ../include/send.h packet.o: packet.c ../config.h ../include/packet.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/parse.h ../include/s_bsd.h \ - ../include/s_misc.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/parse.h \ + ../include/s_bsd.h ../include/s_misc.h ../include/send.h parse.o: parse.c ../config.h ../include/parse.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/channel.h ../include/handlers.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ - ../include/ircd_features.h ../include/ircd_policy.h \ - ../include/ircd_reply.h ../include/ircd_string.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/opercmds.h \ - ../include/querycmds.h ../include/res.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ - ../include/s_numeric.h ../include/s_user.h ../include/send.h \ - ../include/sys.h ../include/whocmds.h ../include/whowas.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/channel.h ../include/handlers.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/fda.h ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/ircd_policy.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/msg.h ../include/numeric.h \ + ../include/numnicks.h ../include/opercmds.h ../include/querycmds.h \ + ../include/res.h ../include/s_bsd.h ../include/s_conf.h \ + ../include/s_debug.h ../include/s_misc.h ../include/s_numeric.h \ + ../include/s_user.h ../include/send.h ../include/sys.h \ + ../include/whocmds.h ../include/whowas.h querycmds.o: querycmds.c ../config.h ../include/querycmds.h \ ../include/ircd_features.h random.o: random.c ../config.h ../include/random.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd_log.h \ - ../include/ircd_reply.h ../include/send.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd_log.h ../include/ircd_reply.h ../include/send.h res.o: res.c ../config.h ../include/res.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_log.h ../include/ircd_osdep.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/msg.h ../include/numeric.h \ - ../include/s_bsd.h ../include/s_debug.h ../include/s_misc.h \ - ../include/send.h ../include/sprintf_irc.h ../include/support.h \ - ../include/sys.h -s_auth.o: s_auth.c ../config.h ../include/s_auth.h ../include/client.h \ - ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/IPcheck.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_log.h ../include/ircd_osdep.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/s_bsd.h ../include/s_debug.h \ + ../include/s_misc.h ../include/send.h ../include/sprintf_irc.h \ + ../include/support.h ../include/sys.h +s_auth.o: s_auth.c ../config.h ../include/s_auth.h \ + ../include/ircd_events.h ../include/client.h ../include/ircd_defs.h \ + ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ + ../include/IPcheck.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_chattr.h \ ../include/ircd_features.h ../include/ircd_log.h \ ../include/ircd_osdep.h ../include/ircd_string.h ../include/list.h \ ../include/numeric.h ../include/querycmds.h ../include/res.h \ @@ -1010,25 +1067,25 @@ s_auth.o: s_auth.c ../config.h ../include/s_auth.h ../include/client.h \ ../include/send.h ../include/sprintf_irc.h ../include/sys.h s_bsd.o: s_bsd.c ../config.h ../include/s_bsd.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/IPcheck.h ../include/channel.h \ - ../include/class.h ../include/hash.h ../include/ircd_log.h \ - ../include/ircd_features.h ../include/ircd_osdep.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/ircd.h ../include/struct.h \ - ../include/list.h ../include/listener.h ../include/msg.h \ - ../include/numeric.h ../include/numnicks.h ../include/packet.h \ - ../include/parse.h ../include/querycmds.h ../include/res.h \ - ../include/s_auth.h ../include/s_conf.h ../include/s_debug.h \ - ../include/s_misc.h ../include/s_user.h ../include/send.h \ - ../include/sprintf_irc.h ../include/support.h ../include/sys.h \ - ../include/uping.h ../include/version.h + ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/IPcheck.h ../include/channel.h ../include/class.h \ + ../include/hash.h ../include/ircd_log.h ../include/ircd_features.h \ + ../include/ircd_osdep.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/ircd.h \ + ../include/struct.h ../include/list.h ../include/listener.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/packet.h ../include/parse.h ../include/querycmds.h \ + ../include/res.h ../include/s_auth.h ../include/s_conf.h \ + ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ + ../include/send.h ../include/sprintf_irc.h ../include/support.h \ + ../include/sys.h ../include/uping.h ../include/version.h s_conf.o: s_conf.c ../config.h ../include/s_conf.h \ ../include/IPcheck.h ../include/class.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/crule.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/crule.h \ ../include/ircd_features.h ../include/fileio.h ../include/gline.h \ ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_chattr.h \ ../include/ircd_log.h ../include/ircd_reply.h \ ../include/ircd_snprintf.h ../include/ircd_string.h ../include/list.h \ ../include/listener.h ../include/match.h ../include/motd.h \ @@ -1039,79 +1096,84 @@ s_conf.o: s_conf.c ../config.h ../include/s_conf.h \ s_debug.o: s_debug.c ../config.h ../include/s_debug.h \ ../include/ircd_defs.h ../include/channel.h ../include/class.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd_alloc.h \ - ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_osdep.h ../include/ircd_reply.h ../include/ircd.h \ - ../include/struct.h ../include/list.h ../include/numeric.h \ - ../include/numnicks.h ../include/res.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/send.h ../include/sys.h \ - ../include/whowas.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_osdep.h ../include/ircd_reply.h \ + ../include/ircd.h ../include/struct.h ../include/list.h \ + ../include/numeric.h ../include/numnicks.h ../include/res.h \ + ../include/s_bsd.h ../include/s_conf.h ../include/send.h \ + ../include/sys.h ../include/whowas.h s_err.o: s_err.c ../config.h ../include/numeric.h ../include/s_debug.h \ ../include/ircd_defs.h ../include/sprintf_irc.h s_misc.o: s_misc.c ../config.h ../include/s_misc.h \ ../include/IPcheck.h ../include/channel.h ../include/ircd_defs.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ - ../include/struct.h ../include/ircd_alloc.h ../include/ircd_log.h \ - ../include/ircd_policy.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ - ../include/match.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/parse.h ../include/querycmds.h \ - ../include/ircd_features.h ../include/res.h ../include/s_bsd.h \ - ../include/s_conf.h ../include/s_debug.h ../include/s_user.h \ - ../include/send.h ../include/sprintf_irc.h ../include/support.h \ - ../include/sys.h ../include/uping.h ../include/userload.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ + ../include/fda.h ../include/ircd_log.h ../include/ircd_policy.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/list.h ../include/match.h \ + ../include/msg.h ../include/numeric.h ../include/numnicks.h \ + ../include/parse.h ../include/querycmds.h ../include/ircd_features.h \ + ../include/res.h ../include/s_bsd.h ../include/s_conf.h \ + ../include/s_debug.h ../include/s_user.h ../include/send.h \ + ../include/sprintf_irc.h ../include/support.h ../include/sys.h \ + ../include/uping.h ../include/userload.h s_numeric.o: s_numeric.c ../config.h ../include/s_numeric.h \ ../include/channel.h ../include/ircd_defs.h ../include/client.h \ - ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_snprintf.h ../include/numnicks.h ../include/send.h + ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_snprintf.h ../include/numnicks.h \ + ../include/send.h s_serv.o: s_serv.c ../config.h ../include/s_serv.h \ ../include/IPcheck.h ../include/channel.h ../include/ircd_defs.h \ ../include/client.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/gline.h ../include/hash.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_alloc.h \ - ../include/ircd_reply.h ../include/ircd_string.h \ - ../include/ircd_chattr.h ../include/ircd_snprintf.h \ - ../include/ircd_xopen.h ../include/jupe.h ../include/list.h \ - ../include/match.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/parse.h ../include/querycmds.h \ - ../include/ircd_features.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ - ../include/send.h ../include/sprintf_irc.h ../include/sys.h \ - ../include/userload.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/gline.h \ + ../include/hash.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h \ + ../include/ircd_snprintf.h ../include/ircd_xopen.h ../include/jupe.h \ + ../include/list.h ../include/match.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/parse.h \ + ../include/querycmds.h ../include/ircd_features.h ../include/s_bsd.h \ + ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_user.h ../include/send.h ../include/sprintf_irc.h \ + ../include/sys.h ../include/userload.h s_stats.o: s_stats.c ../config.h ../include/s_stats.h \ ../include/class.h ../include/client.h ../include/ircd_defs.h \ - ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_chattr.h \ - ../include/ircd_log.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/listener.h ../include/match.h \ - ../include/msg.h ../include/numeric.h ../include/numnicks.h \ - ../include/s_conf.h ../include/s_user.h ../include/send.h + ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_chattr.h ../include/ircd_log.h \ + ../include/ircd_reply.h ../include/ircd_string.h \ + ../include/listener.h ../include/match.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ + ../include/s_user.h ../include/send.h s_user.o: s_user.c ../config.h ../include/s_user.h \ ../include/IPcheck.h ../include/channel.h ../include/ircd_defs.h \ ../include/class.h ../include/client.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/gline.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ - ../include/ircd_features.h ../include/ircd_log.h \ - ../include/ircd_policy.h ../include/ircd_reply.h \ - ../include/ircd_string.h ../include/list.h ../include/match.h \ - ../include/motd.h ../include/msg.h ../include/numeric.h \ - ../include/numnicks.h ../include/parse.h ../include/querycmds.h \ - ../include/random.h ../include/s_bsd.h ../include/s_conf.h \ - ../include/s_debug.h ../include/s_misc.h ../include/s_serv.h \ - ../include/send.h ../include/sprintf_irc.h ../include/support.h \ - ../include/supported.h ../include/sys.h ../include/userload.h \ - ../include/version.h ../include/whowas.h ../include/handlers.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/gline.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/ircd_log.h ../include/ircd_policy.h \ + ../include/ircd_reply.h ../include/ircd_string.h ../include/list.h \ + ../include/match.h ../include/motd.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/parse.h \ + ../include/querycmds.h ../include/random.h ../include/s_bsd.h \ + ../include/s_conf.h ../include/s_debug.h ../include/s_misc.h \ + ../include/s_serv.h ../include/send.h ../include/sprintf_irc.h \ + ../include/support.h ../include/supported.h ../include/sys.h \ + ../include/userload.h ../include/version.h ../include/whowas.h \ + ../include/handlers.h send.o: send.c ../config.h ../include/send.h ../include/channel.h \ ../include/ircd_defs.h ../include/class.h ../include/client.h \ - ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ - ../include/ircd.h ../include/struct.h ../include/ircd_snprintf.h \ - ../include/ircd_string.h ../include/ircd_chattr.h ../include/list.h \ - ../include/match.h ../include/msg.h ../include/numnicks.h \ - ../include/s_bsd.h ../include/s_debug.h ../include/s_misc.h \ - ../include/s_user.h ../include/sprintf_irc.h ../include/sys.h + ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_snprintf.h ../include/ircd_string.h \ + ../include/ircd_chattr.h ../include/list.h ../include/match.h \ + ../include/msg.h ../include/numnicks.h ../include/s_bsd.h \ + ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ + ../include/sprintf_irc.h ../include/sys.h sprintf_irc.o: sprintf_irc.c ../config.h ../include/sprintf_irc.h \ ../include/sys.h support.o: support.c ../config.h ../include/support.h \ @@ -1120,9 +1182,10 @@ support.o: support.c ../config.h ../include/support.h \ ../include/ircd_snprintf.h ../include/s_bsd.h ../include/s_debug.h \ ../include/send.h ../include/sprintf_irc.h ../include/sys.h uping.o: uping.c ../config.h ../include/uping.h ../include/ircd_defs.h \ - ../include/client.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_log.h ../include/ircd_osdep.h \ + ../include/ircd_events.h ../include/client.h ../include/dbuf.h \ + ../include/msgq.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_log.h ../include/ircd_osdep.h \ ../include/ircd_string.h ../include/ircd_chattr.h ../include/match.h \ ../include/msg.h ../include/numeric.h ../include/numnicks.h \ ../include/s_bsd.h ../include/s_conf.h ../include/s_debug.h \ @@ -1130,15 +1193,16 @@ uping.o: uping.c ../config.h ../include/uping.h ../include/ircd_defs.h \ ../include/sys.h userload.o: userload.c ../config.h ../include/userload.h \ ../include/client.h ../include/ircd_defs.h ../include/dbuf.h \ - ../include/msgq.h ../include/ircd_handler.h ../include/ircd.h \ - ../include/struct.h ../include/msg.h ../include/numnicks.h \ - ../include/querycmds.h ../include/ircd_features.h ../include/s_misc.h \ - ../include/send.h ../include/sys.h + ../include/msgq.h ../include/ircd_events.h ../include/ircd_handler.h \ + ../include/ircd.h ../include/struct.h ../include/msg.h \ + ../include/numnicks.h ../include/querycmds.h \ + ../include/ircd_features.h ../include/s_misc.h ../include/send.h \ + ../include/sys.h whocmds.o: whocmds.c ../config.h ../include/whocmds.h \ ../include/channel.h ../include/ircd_defs.h ../include/client.h \ - ../include/dbuf.h ../include/msgq.h ../include/ircd_handler.h \ - ../include/hash.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_chattr.h ../include/ircd_reply.h \ + ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ + ../include/ircd_handler.h ../include/hash.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_chattr.h ../include/ircd_reply.h \ ../include/ircd_string.h ../include/list.h ../include/match.h \ ../include/numeric.h ../include/numnicks.h ../include/querycmds.h \ ../include/ircd_features.h ../include/random.h ../include/s_bsd.h \ @@ -1148,12 +1212,13 @@ whocmds.o: whocmds.c ../config.h ../include/whocmds.h \ ../include/whowas.h ../include/msg.h whowas.o: whowas.c ../config.h ../include/whowas.h ../include/client.h \ ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ - ../include/ircd_handler.h ../include/ircd.h ../include/struct.h \ - ../include/ircd_alloc.h ../include/ircd_chattr.h \ - ../include/ircd_features.h ../include/ircd_string.h ../include/list.h \ - ../include/numeric.h ../include/s_debug.h ../include/s_misc.h \ - ../include/s_user.h ../include/send.h ../include/support.h \ - ../include/sys.h ../include/msg.h + ../include/ircd_events.h ../include/ircd_handler.h ../include/ircd.h \ + ../include/struct.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_chattr.h ../include/ircd_features.h \ + ../include/ircd_string.h ../include/list.h ../include/numeric.h \ + ../include/s_debug.h ../include/s_misc.h ../include/s_user.h \ + ../include/send.h ../include/support.h ../include/sys.h \ + ../include/msg.h os_bsd.o: os_bsd.c ../config.h ../include/ircd_osdep.h \ ../include/msgq.h ../include/ircd_defs.h os_linux.o: os_linux.c ../config.h ../include/ircd_osdep.h \ @@ -1164,3 +1229,18 @@ os_generic.o: os_generic.c ../config.h ../include/ircd_osdep.h \ ../include/msgq.h ../include/ircd_defs.h os_solaris.o: os_solaris.c ../config.h ../include/ircd_osdep.h \ ../include/msgq.h ../include/ircd_defs.h +engine_devpoll.o: engine_devpoll.c ../config.h \ + ../include/ircd_events.h ../include/ircd.h ../include/struct.h \ + ../include/ircd_defs.h ../include/ircd_alloc.h ../include/fda.h \ + ../include/ircd_log.h ../include/s_debug.h +engine_poll.o: engine_poll.c ../config.h ../include/ircd_events.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_defs.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_log.h \ + ../include/s_debug.h +engine_kqueue.o: engine_kqueue.c ../config.h ../include/ircd_events.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_defs.h \ + ../include/ircd_alloc.h ../include/fda.h ../include/ircd_log.h \ + ../include/s_debug.h +engine_select.o: engine_select.c ../config.h ../include/ircd_events.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_defs.h \ + ../include/ircd_log.h ../include/s_debug.h diff --git a/ircd/channel.c b/ircd/channel.c index bd13efe..38a5356 100644 --- a/ircd/channel.c +++ b/ircd/channel.c @@ -1247,6 +1247,8 @@ void list_next_channels(struct Client *cptr, int nr) (cli_listing(cptr))->chptr = chptr; chptr->mode.mode |= MODE_LISTED; } + + update_write(cptr); } /* diff --git a/ircd/engine_devpoll.c b/ircd/engine_devpoll.c new file mode 100644 index 0000000..8bd9c75 --- /dev/null +++ b/ircd/engine_devpoll.c @@ -0,0 +1,406 @@ +/* + * IRC - Internet Relay Chat, ircd/engine_devpoll.c + * Copyright (C) 2001 Kevin L. Mitchell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#include "config.h" + +#include "ircd_events.h" + +#include "ircd.h" +#include "ircd_alloc.h" +#include "ircd_log.h" +#include "s_debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVPOLL_ERROR_THRESHOLD 20 /* after 20 devpoll errors, restart */ +#define ERROR_EXPIRE_TIME 3600 /* expire errors after an hour */ + +#define POLLS_PER_DEVPOLL 20 /* get 20 pollfd's per turn */ + +/* Figure out what bits to set for read */ +#if defined(POLLMSG) && defined(POLLIN) && defined(POLLRDNORM) +# define POLLREADFLAGS (POLLMSG|POLLIN|POLLRDNORM) +#elif defined(POLLIN) && defined(POLLRDNORM) +# define POLLREADFLAGS (POLLIN|POLLRDNORM) +#elif defined(POLLIN) +# define POLLREADFLAGS POLLIN +#elif defined(POLLRDNORM) +# define POLLREADFLAGS POLLRDNORM +#endif + +/* Figure out what bits to set for write */ +#if defined(POLLOUT) && defined(POLLWRNORM) +# define POLLWRITEFLAGS (POLLOUT|POLLWRNORM) +#elif defined(POLLOUT) +# define POLLWRITEFLAGS POLLOUT +#elif defined(POLLWRNORM) +# define POLLWRITEFLAGS POLLWRNORM +#endif + +/* Figure out what bits indicate errors */ +#ifdef POLLHUP +# define POLLERRORS (POLLHUP|POLLERR) +#else +# define POLLERRORS POLLERR +#endif + +static struct Socket** sockList; +static int devpoll_max; +static int devpoll_fd; + +static int errors = 0; +static struct Timer clear_error; + +/* decrements the error count once per hour */ +static void +error_clear(struct Event* ev) +{ + if (!--errors) /* remove timer when error count reaches 0 */ + timer_del(ev_timer(ev)); +} + +/* initialize the devpoll engine */ +static int +engine_init(int max_sockets) +{ + int i; + + if ((devpoll_fd = open("/dev/poll", O_RDWR)) < 0) { + log_write(LS_SYSTEM, L_WARNING, 0, + "/dev/poll engine cannot open device: %m"); + return 0; /* engine cannot be initialized; defer */ + } + + /* allocate necessary memory */ + sockList = (struct Socket**) MyMalloc(sizeof(struct Socket*) * max_sockets); + + /* initialize the data */ + for (i = 0; i < max_sockets; i++) + sockList[i] = 0; + + devpoll_max = max_sockets; /* number of sockets allocated */ + + return 1; +} + +/* Figure out what events go with a given state */ +static unsigned int +state_to_events(enum SocketState state, unsigned int events) +{ + switch (state) { + case SS_CONNECTING: /* connecting socket */ + return SOCK_EVENT_WRITABLE; + break; + + case SS_LISTENING: /* listening socket */ + case SS_NOTSOCK: /* our signal socket */ + return SOCK_EVENT_READABLE; + break; + + case SS_CONNECTED: case SS_DATAGRAM: case SS_CONNECTDG: + return events; /* ordinary socket */ + break; + } + + /*NOTREACHED*/ + return 0; +} + +/* Reset the desired events */ +static void +set_events(struct Socket* sock, unsigned int events) +{ + struct pollfd pfd; + + pfd.fd = s_fd(sock); + + if (s_ed_int(sock)) { /* is one in /dev/poll already? */ + pfd.events = POLLREMOVE; /* First, remove old pollfd */ + + Debug((DEBUG_ENGINE, "devpoll: Removing old entry for socket %d [%p]", + s_fd(sock), sock)); + + if (write(devpoll_fd, &pfd, sizeof(pfd)) != sizeof(pfd)) { + event_generate(ET_ERROR, sock, errno); /* report error */ + return; + } + + s_ed_int(sock) = 0; /* mark that it's gone */ + } + + if (!(events & SOCK_EVENT_MASK)) /* no events, so stop here */ + return; + + pfd.events = 0; /* Now, set up new pollfd... */ + if (events & SOCK_EVENT_READABLE) + pfd.events |= POLLREADFLAGS; /* look for readable conditions */ + if (events & SOCK_EVENT_WRITABLE) + pfd.events |= POLLWRITEFLAGS; /* look for writable conditions */ + + Debug((DEBUG_ENGINE, "devpoll: Registering interest on %d [%p] (state %s, " + "mask [%s])", s_fd(sock), sock, state_to_name(s_state(sock)), + sock_flags(s_events(sock)))); + + if (write(devpoll_fd, &pfd, sizeof(pfd)) != sizeof(pfd)) { + event_generate(ET_ERROR, sock, errno); /* report error */ + return; + } + + s_ed_int(sock) = 1; /* mark that we've added a pollfd */ +} + +/* add a socket to be listened on */ +static int +engine_add(struct Socket* sock) +{ + assert(0 != sock); + assert(0 == sockList[s_fd(sock)]); + + /* bounds-check... */ + if (s_fd(sock) >= devpoll_max) { + log_write(LS_SYSTEM, L_ERROR, 0, + "Attempt to add socket %d (> %d) to event engine", s_fd(sock), + devpoll_max); + return 0; + } + + sockList[s_fd(sock)] = sock; /* add to list */ + + Debug((DEBUG_ENGINE, "devpoll: Adding socket %d [%p], state %s, to engine", + s_fd(sock), sock, state_to_name(s_state(sock)))); + + /* set the correct events */ + set_events(sock, state_to_events(s_state(sock), s_events(sock))); + + return 1; /* success */ +} + +/* socket switching to new state */ +static void +engine_state(struct Socket* sock, enum SocketState new_state) +{ + assert(0 != sock); + assert(sock == sockList[s_fd(sock)]); + + Debug((DEBUG_ENGINE, "devpoll: Changing state for socket %p to %s", sock, + state_to_name(new_state))); + + /* set the correct events */ + set_events(sock, state_to_events(new_state, s_events(sock))); +} + +/* socket events changing */ +static void +engine_events(struct Socket* sock, unsigned int new_events) +{ + assert(0 != sock); + assert(sock == sockList[s_fd(sock)]); + + Debug((DEBUG_ENGINE, "devpoll: Changing event mask for socket %p to [%s]", + sock, sock_flags(new_events))); + + /* set the correct events */ + set_events(sock, state_to_events(s_state(sock), new_events)); +} + +/* socket going away */ +static void +engine_delete(struct Socket* sock) +{ + assert(0 != sock); + assert(sock == sockList[s_fd(sock)]); + + Debug((DEBUG_ENGINE, "devpoll: Deleting socket %d [%p], state %s", + s_fd(sock), sock, state_to_name(s_state(sock)))); + + set_events(sock, 0); /* get rid of the socket */ + + sockList[s_fd(sock)] = 0; /* zero the socket list entry */ +} + +/* engine event loop */ +static void +engine_loop(struct Generators* gen) +{ + struct dvpoll dopoll; + struct pollfd polls[POLLS_PER_DEVPOLL]; + struct Socket* sock; + int nfds; + int i; + int errcode; + size_t codesize; + + while (running) { + dopoll.dp_fds = polls; /* set up the struct dvpoll */ + dopoll.dp_nfds = POLLS_PER_DEVPOLL; + + /* calculate the proper timeout */ + dopoll.dp_timeout = timer_next(gen) ? + (timer_next(gen) - CurrentTime) * 1000 : -1; + + Debug((DEBUG_INFO, "devpoll: delay: %Tu (%Tu) %d", timer_next(gen), + CurrentTime, dopoll.dp_timeout)); + + /* check for active files */ + nfds = ioctl(devpoll_fd, DP_POLL, &dopoll); + + CurrentTime = time(0); /* set current time... */ + + if (nfds < 0) { + if (errno != EINTR) { /* ignore interrupts */ + /* Log the poll error */ + log_write(LS_SOCKET, L_ERROR, 0, "ioctl(DP_POLL) error: %m"); + if (!errors++) + timer_add(&clear_error, error_clear, 0, TT_PERIODIC, + ERROR_EXPIRE_TIME); + else if (errors > DEVPOLL_ERROR_THRESHOLD) /* too many errors... */ + server_restart("too many /dev/poll errors"); + } + /* old code did a sleep(1) here; with usage these days, + * that may be too expensive + */ + continue; + } + + for (i = 0; i < nfds; i++) { + assert(-1 < polls[i].fd); + assert(0 != sockList[polls[i].fd]); + assert(s_fd(sockList[polls[i].fd]) == polls[i].fd); + + sock = sockList[polls[i].fd]; + if (!sock) /* slots may become empty while processing events */ + continue; + + gen_ref_inc(sock); /* can't have it going away on us */ + + Debug((DEBUG_ENGINE, "devpoll: Checking socket %p (fd %d) state %s, " + "events %s", sock, s_fd(sock), state_to_name(s_state(sock)), + sock_flags(s_events(sock)))); + + if (s_state(sock) != SS_NOTSOCK) { + errcode = 0; /* check for errors on socket */ + codesize = sizeof(errcode); + if (getsockopt(s_fd(sock), SOL_SOCKET, SO_ERROR, &errcode, + &codesize) < 0) + errcode = errno; /* work around Solaris implementation */ + + if (errcode) { /* an error occurred; generate an event */ + Debug((DEBUG_ENGINE, "devpoll: Error %d on fd %d, socket %p", + errcode, s_fd(sock), sock)); + event_generate(ET_ERROR, sock, errcode); + gen_ref_dec(sock); /* careful not to leak reference counts */ + continue; + } + } + + switch (s_state(sock)) { + case SS_CONNECTING: + if (polls[i].revents & POLLWRITEFLAGS) { /* connection completed */ + Debug((DEBUG_ENGINE, "devpoll: Connection completed")); + event_generate(ET_CONNECT, sock, 0); + } + break; + + case SS_LISTENING: + if (polls[i].revents & POLLREADFLAGS) { /* connect. to be accept. */ + Debug((DEBUG_ENGINE, "devpoll: Ready for accept")); + event_generate(ET_ACCEPT, sock, 0); + } + break; + + case SS_NOTSOCK: + if (polls[i].revents & POLLREADFLAGS) { /* data on socket */ + /* can't peek; it's not a socket */ + Debug((DEBUG_ENGINE, "devpoll: non-socket readable")); + event_generate(ET_READ, sock, 0); + } + break; + + case SS_CONNECTED: + if (polls[i].revents & POLLREADFLAGS) { /* data on socket */ + char c; + + switch (recv(s_fd(sock), &c, 1, MSG_PEEK)) { /* check EOF */ + case -1: /* error occurred?!? */ + if (errno == EAGAIN) { + Debug((DEBUG_ENGINE, "devpoll: Resource temporarily " + "unavailable?")); + continue; + } + Debug((DEBUG_ENGINE, "devpoll: Uncaught error!")); + event_generate(ET_ERROR, sock, errno); + break; + + case 0: /* EOF from client */ + Debug((DEBUG_ENGINE, "devpoll: EOF from client")); + event_generate(ET_EOF, sock, 0); + break; + + default: /* some data can be read */ + Debug((DEBUG_ENGINE, "devpoll: Data to be read")); + event_generate(ET_READ, sock, 0); + break; + } + } + if (polls[i].revents & POLLWRITEFLAGS) { /* socket writable */ + Debug((DEBUG_ENGINE, "devpoll: Data can be written")); + event_generate(ET_WRITE, sock, 0); + } + break; + + case SS_DATAGRAM: case SS_CONNECTDG: + if (polls[i].revents & POLLREADFLAGS) { /* socket readable */ + Debug((DEBUG_ENGINE, "devpoll: Datagram to be read")); + event_generate(ET_READ, sock, 0); + } + if (polls[i].revents & POLLWRITEFLAGS) { /* socket writable */ + Debug((DEBUG_ENGINE, "devpoll: Datagram can be written")); + event_generate(ET_WRITE, sock, 0); + } + break; + } + + assert(s_fd(sock) == polls[i].fd); + + gen_ref_dec(sock); /* we're done with it */ + } + + timer_run(); /* execute any pending timers */ + } +} + +struct Engine engine_devpoll = { + "/dev/poll", /* Engine name */ + engine_init, /* Engine initialization function */ + 0, /* Engine signal registration function */ + engine_add, /* Engine socket registration function */ + engine_state, /* Engine socket state change function */ + engine_events, /* Engine socket events mask function */ + engine_delete, /* Engine socket deletion function */ + engine_loop /* Core engine event loop */ +}; diff --git a/ircd/engine_kqueue.c b/ircd/engine_kqueue.c new file mode 100644 index 0000000..aafbb59 --- /dev/null +++ b/ircd/engine_kqueue.c @@ -0,0 +1,414 @@ +/* + * IRC - Internet Relay Chat, ircd/engine_kqueue.c + * Copyright (C) 2001 Kevin L. Mitchell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#include "config.h" + +#include "ircd_events.h" + +#include "ircd.h" +#include "ircd_alloc.h" +#include "ircd_log.h" +#include "s_debug.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define KQUEUE_ERROR_THRESHOLD 20 /* after 20 kqueue errors, restart */ +#define ERROR_EXPIRE_TIME 3600 /* expire errors after an hour */ + +#define POLLS_PER_KQUEUE 20 /* get 20 kevents per turn */ + +static struct Socket** sockList; +static int kqueue_max; +static int kqueue_id; + +static int errors = 0; +static struct Timer clear_error; + +/* decrements the error count once per hour */ +static void +error_clear(struct Event* ev) +{ + if (!--errors) /* remove timer when error count reaches 0 */ + timer_del(ev_timer(ev)); +} + +/* initialize the kqueue engine */ +static int +engine_init(int max_sockets) +{ + int i; + + if ((kqueue_id = kqueue()) < 0) { /* initialize... */ + log_write(LS_SYSTEM, L_WARNING, 0, + "kqueue() engine cannot initialize: %m"); + return 0; + } + + /* allocate necessary memory */ + sockList = (struct Socket**) MyMalloc(sizeof(struct Socket*) * max_sockets); + + /* initialize the data */ + for (i = 0; i < max_sockets; i++) + sockList[i] = 0; + + kqueue_max = max_sockets; /* number of sockets allocated */ + + return 1; /* success! */ +} + +/* add a signel to be watched for */ +static void +engine_signal(struct Signal* sig) +{ + struct kevent sigevent; + struct sigaction act; + + assert(0 != signal); + + Debug((DEBUG_ENGINE, "kqueue: Adding filter for signal %d [%p]", + sig_signal(sig), sig)); + + sigevent.ident = sig_signal(sig); /* set up the kqueue event */ + sigevent.filter = EVFILT_SIGNAL; /* looking for signals... */ + sigevent.flags = EV_ADD | EV_ENABLE; /* add and enable it */ + sigevent.fflags = 0; + sigevent.data = 0; + sigevent.udata = sig; /* store our user data */ + + if (kevent(kqueue_id, &sigevent, 1, 0, 0, 0) < 0) { /* add event */ + log_write(LS_SYSTEM, L_WARNING, 0, "Unable to trap signal %d", + sig_signal(sig)); + return; + } + + act.sa_handler = SIG_IGN; /* ignore the signal */ + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(sig_signal(sig), &act, 0); +} + +/* Figure out what events go with a given state */ +static unsigned int +state_to_events(enum SocketState state, unsigned int events) +{ + switch (state) { + case SS_CONNECTING: /* connecting socket */ + return SOCK_EVENT_WRITABLE; + break; + + case SS_LISTENING: /* listening socket */ + case SS_NOTSOCK: /* our signal socket--just in case */ + return SOCK_EVENT_READABLE; + break; + + case SS_CONNECTED: case SS_DATAGRAM: case SS_CONNECTDG: + return events; /* ordinary socket */ + break; + } + + /*NOTREACHED*/ + return 0; +} + +/* Activate kqueue filters as appropriate */ +static void +set_or_clear(struct Socket* sock, unsigned int clear, unsigned int set) +{ + int i = 0; + struct kevent chglist[2]; + + assert(0 != sock); + assert(-1 < s_fd(sock)); + + if ((clear ^ set) & SOCK_EVENT_READABLE) { /* readable has changed */ + chglist[i].ident = s_fd(sock); /* set up the change list */ + chglist[i].filter = EVFILT_READ; /* readable filter */ + chglist[i].flags = EV_ADD; /* adding it */ + chglist[i].fflags = 0; + chglist[i].data = 0; + chglist[i].udata = 0; /* I love udata, but it can't really be used here */ + + if (set & SOCK_EVENT_READABLE) /* it's set */ + chglist[i].flags |= EV_ENABLE; + else /* clear it */ + chglist[i].flags |= EV_DISABLE; + + i++; /* advance to next element */ + } + + if ((clear ^ set) & SOCK_EVENT_WRITABLE) { /* writable has changed */ + chglist[i].ident = s_fd(sock); /* set up the change list */ + chglist[i].filter = EVFILT_WRITE; /* writable filter */ + chglist[i].flags = EV_ADD; /* adding it */ + chglist[i].fflags = 0; + chglist[i].data = 0; + chglist[i].udata = 0; + + if (set & SOCK_EVENT_WRITABLE) /* it's set */ + chglist[i].flags |= EV_ENABLE; + else /* clear it */ + chglist[i].flags |= EV_DISABLE; + + i++; /* advance count... */ + } + + if (kevent(kqueue_id, chglist, i, 0, 0, 0) < 0) + event_generate(ET_ERROR, sock, errno); /* report error */ +} + +/* add a socket to be listened on */ +static int +engine_add(struct Socket* sock) +{ + assert(0 != sock); + assert(0 == sockList[s_fd(sock)]); + + /* bounds-check... */ + if (sock->s_fd >= kqueue_max) { + log_write(LS_SYSTEM, L_ERROR, 0, + "Attempt to add socket %d (> %d) to event engine", s_fd(sock), + kqueue_max); + return 0; + } + + sockList[s_fd(sock)] = sock; /* add to list */ + + Debug((DEBUG_ENGINE, "kqueue: Adding socket %d [%p], state %s, to engine", + s_fd(sock), sock, state_to_name(s_state(sock)))); + + /* Add socket to queue */ + set_or_clear(sock, 0, state_to_events(s_state(sock), s_events(sock))); + + return 1; /* success */ +} + +/* socket switching to new state */ +static void +engine_state(struct Socket* sock, enum SocketState new_state) +{ + assert(0 != sock); + assert(sock == sockList[s_fd(sock)]); + + Debug((DEBUG_ENGINE, "kqueue: Changing state for socket %p to %s", sock, + state_to_name(new_state))); + + /* set the correct events */ + set_or_clear(sock, + state_to_events(s_state(sock), s_events(sock)), /* old state */ + state_to_events(new_state, s_events(sock))); /* new state */ + +} + +/* socket events changing */ +static void +engine_events(struct Socket* sock, unsigned int new_events) +{ + assert(0 != sock); + assert(sock == sockList[s_fd(sock)]); + + Debug((DEBUG_ENGINE, "kqueue: Changing event mask for socket %p to [%s]", + sock, sock_flags(new_events))); + + /* set the correct events */ + set_or_clear(sock, + state_to_events(s_state(sock), s_events(sock)), /* old events */ + state_to_events(s_state(sock), new_events)); /* new events */ +} + +/* socket going away */ +static void +engine_delete(struct Socket* sock) +{ + struct kevent dellist[2]; + + assert(0 != sock); + assert(sock == sockList[s_fd(sock)]); + + Debug((DEBUG_ENGINE, "kqueue: Deleting socket %d [%p], state %s", + s_fd(sock), sock, state_to_name(s_state(sock)))); + + dellist[0].ident = s_fd(sock); /* set up the delete list */ + dellist[0].filter = EVFILT_READ; /* readable filter */ + dellist[0].flags = EV_DELETE; /* delete it */ + dellist[0].fflags = 0; + dellist[0].data = 0; + dellist[0].udata = 0; + + dellist[1].ident = s_fd(sock); + dellist[1].filter = EVFILT_WRITE; /* writable filter */ + dellist[1].flags = EV_DELETE; /* delete it */ + dellist[1].fflags = 0; + dellist[1].data = 0; + dellist[1].udata = 0; + + /* make it all go away */ + if (kevent(kqueue_id, dellist, 2, 0, 0, 0) < 0) + log_write(LS_SOCKET, L_WARNING, 0, + "Unable to delete kevent items for socket %d", s_fd(sock)); + + sockList[s_fd(sock)] = 0; +} + +/* engine event loop */ +static void +engine_loop(struct Generators* gen) +{ + struct kevent events[POLLS_PER_KQUEUE]; + struct Socket* sock; + struct timespec wait; + int nevs; + int i; + int errcode; + size_t codesize; + + while (running) { + /* set up the sleep time */ + wait.tv_sec = timer_next(gen) ? (timer_next(gen) - CurrentTime) : -1; + wait.tv_nsec = 0; + + Debug((DEBUG_INFO, "kqueue: delay: %Tu (%Tu) %Tu", timer_next(gen), + CurrentTime, wait.tv_sec)); + + /* check for active events */ + nevs = kevent(kqueue_id, 0, 0, events, POLLS_PER_KQUEUE, + wait.tv_sec < 0 ? 0 : &wait); + + CurrentTime = time(0); /* set current time... */ + + if (nevs < 0) { + if (errno != EINTR) { /* ignore kevent interrupts */ + /* Log the kqueue error */ + log_write(LS_SOCKET, L_ERROR, 0, "kevent() error: %m"); + if (!errors++) + timer_add(&clear_error, error_clear, 0, TT_PERIODIC, + ERROR_EXPIRE_TIME); + else if (errors > KQUEUE_ERROR_THRESHOLD) /* too many errors... */ + server_restart("too many kevent errors"); + } + /* old code did a sleep(1) here; with usage these days, + * that may be too expensive + */ + continue; + } + + for (i = 0; i < nevs; i++) { + if (events[i].filter == EVFILT_SIGNAL) { + /* it's a signal; deal appropriately */ + event_generate(ET_SIGNAL, events[i].udata, events[i].ident); + continue; /* skip socket processing loop */ + } + + assert(events[i].filter == EVFILT_READ || + events[i].filter == EVFILT_WRITE); + + sock = sockList[events[i].ident]; + if (!sock) /* slots may become empty while processing events */ + continue; + + assert(s_fd(sock) == events[i].ident); + + gen_ref_inc(sock); /* can't have it going away on us */ + + Debug((DEBUG_ENGINE, "kqueue: Checking socket %p (fd %d) state %s, " + "events %s", sock, s_fd(sock), state_to_name(s_state(sock)), + sock_flags(s_events(sock)))); + + if (s_state(sock) != SS_NOTSOCK) { + errcode = 0; /* check for errors on socket */ + codesize = sizeof(errcode); + if (getsockopt(s_fd(sock), SOL_SOCKET, SO_ERROR, &errcode, + &codesize) < 0) + errcode = errno; /* work around Solaris implementation */ + + if (errcode) { /* an error occurred; generate an event */ + Debug((DEBUG_ENGINE, "kqueue: Error %d on fd %d, socket %p", errcode, + s_fd(sock), sock)); + event_generate(ET_ERROR, sock, errcode); + gen_ref_dec(sock); /* careful not to leak reference counts */ + continue; + } + } + + switch (s_state(sock)) { + case SS_CONNECTING: + if (events[i].filter == EVFILT_WRITE) { /* connection completed */ + Debug((DEBUG_ENGINE, "kqueue: Connection completed")); + event_generate(ET_CONNECT, sock, 0); + } + break; + + case SS_LISTENING: + if (events[i].filter == EVFILT_READ) { /* connect. to be accept. */ + Debug((DEBUG_ENGINE, "kqueue: Ready for accept")); + event_generate(ET_ACCEPT, sock, 0); + } + break; + + case SS_NOTSOCK: /* doing nothing socket-specific */ + case SS_CONNECTED: + if (events[i].filter == EVFILT_READ) { /* data on socket */ + Debug((DEBUG_ENGINE, "kqueue: EOF or data to be read")); + event_generate(events[i].flags & EV_EOF ? ET_EOF : ET_READ, sock, 0); + } + if (events[i].filter == EVFILT_WRITE) { /* socket writable */ + Debug((DEBUG_ENGINE, "kqueue: Data can be written")); + event_generate(ET_WRITE, sock, 0); + } + break; + + case SS_DATAGRAM: case SS_CONNECTDG: + if (events[i].filter == EVFILT_READ) { /* socket readable */ + Debug((DEBUG_ENGINE, "kqueue: Datagram to be read")); + event_generate(ET_READ, sock, 0); + } + if (events[i].filter == EVFILT_WRITE) { /* socket writable */ + Debug((DEBUG_ENGINE, "kqueue: Datagram can be written")); + event_generate(ET_WRITE, sock, 0); + } + break; + } + + assert(s_fd(sock) == events[i].ident); + + gen_ref_dec(sock); /* we're done with it */ + } + + timer_run(); /* execute any pending timers */ + } +} + +struct Engine engine_kqueue = { + "kqueue()", /* Engine name */ + engine_init, /* Engine initialization function */ + engine_signal, /* Engine signal registration function */ + engine_add, /* Engine socket registration function */ + engine_state, /* Engine socket state change function */ + engine_events, /* Engine socket events mask function */ + engine_delete, /* Engine socket deletion function */ + engine_loop /* Core engine event loop */ +}; diff --git a/ircd/engine_poll.c b/ircd/engine_poll.c new file mode 100644 index 0000000..aa8dc2a --- /dev/null +++ b/ircd/engine_poll.c @@ -0,0 +1,404 @@ +/* + * IRC - Internet Relay Chat, ircd/engine_poll.c + * Copyright (C) 2001 Kevin L. Mitchell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#include "config.h" + +#include "ircd_events.h" + +#include "ircd.h" +#include "ircd_alloc.h" +#include "ircd_log.h" +#include "s_debug.h" + +#include +#include +#include +#include +#include +#include +#include + +#define POLL_ERROR_THRESHOLD 20 /* after 20 poll errors, restart */ +#define ERROR_EXPIRE_TIME 3600 /* expire errors after an hour */ + +/* Figure out what bits to set for read */ +#if defined(POLLMSG) && defined(POLLIN) && defined(POLLRDNORM) +# define POLLREADFLAGS (POLLMSG|POLLIN|POLLRDNORM) +#elif defined(POLLIN) && defined(POLLRDNORM) +# define POLLREADFLAGS (POLLIN|POLLRDNORM) +#elif defined(POLLIN) +# define POLLREADFLAGS POLLIN +#elif defined(POLLRDNORM) +# define POLLREADFLAGS POLLRDNORM +#endif + +/* Figure out what bits to set for write */ +#if defined(POLLOUT) && defined(POLLWRNORM) +# define POLLWRITEFLAGS (POLLOUT|POLLWRNORM) +#elif defined(POLLOUT) +# define POLLWRITEFLAGS POLLOUT +#elif defined(POLLWRNORM) +# define POLLWRITEFLAGS POLLWRNORM +#endif + +/* Figure out what bits indicate errors */ +#ifdef POLLHUP +# define POLLERRORS (POLLHUP|POLLERR) +#else +# define POLLERRORS POLLERR +#endif + +static struct Socket** sockList; +static struct pollfd* pollfdList; +static unsigned int poll_count; +static unsigned int poll_max; + +static int errors = 0; +static struct Timer clear_error; + +/* decrements the error count once per hour */ +static void +error_clear(struct Event* ev) +{ + if (!--errors) /* remove timer when error count reaches 0 */ + timer_del(ev_timer(ev)); +} + +/* initialize the poll engine */ +static int +engine_init(int max_sockets) +{ + int i; + + /* allocate necessary memory */ + sockList = (struct Socket**) MyMalloc(sizeof(struct Socket*) * max_sockets); + pollfdList = (struct pollfd*) MyMalloc(sizeof(struct pollfd) * max_sockets); + + /* initialize the data */ + for (i = 0; i < max_sockets; i++) { + sockList[i] = 0; + pollfdList[i].fd = -1; + pollfdList[i].events = 0; + pollfdList[i].revents = 0; + } + + poll_count = 0; /* nothing in set */ + poll_max = max_sockets; /* number of sockets allocated */ + + return 1; +} + +/* Figure out what events go with a given state */ +static unsigned int +state_to_events(enum SocketState state, unsigned int events) +{ + switch (state) { + case SS_CONNECTING: /* connecting socket */ + return SOCK_EVENT_WRITABLE; + break; + + case SS_LISTENING: /* listening socket */ + case SS_NOTSOCK: /* our signal socket */ + return SOCK_EVENT_READABLE; + break; + + case SS_CONNECTED: case SS_DATAGRAM: case SS_CONNECTDG: + return events; /* ordinary socket */ + break; + } + + /*NOTREACHED*/ + return 0; +} + +/* Toggle bits in the pollfd structs correctly */ +static void +set_or_clear(int idx, unsigned int clear, unsigned int set) +{ + if ((clear ^ set) & SOCK_EVENT_READABLE) { /* readable has changed */ + if (set & SOCK_EVENT_READABLE) /* it's set */ + pollfdList[idx].events |= POLLREADFLAGS; + else /* clear it */ + pollfdList[idx].events &= ~POLLREADFLAGS; + } + + if ((clear ^ set) & SOCK_EVENT_WRITABLE) { /* writable has changed */ + if (set & SOCK_EVENT_WRITABLE) /* it's set */ + pollfdList[idx].events |= POLLWRITEFLAGS; + else /* clear it */ + pollfdList[idx].events &= ~POLLWRITEFLAGS; + } +} + +/* add a socket to be listened on */ +static int +engine_add(struct Socket* sock) +{ + int i; + + assert(0 != sock); + + for (i = 0; sockList[i] && i < poll_count; i++) /* Find an empty slot */ + ; + + Debug((DEBUG_ENGINE, "poll: Looking at slot %d, contents %p", i, + sockList[i])); + + if (i >= poll_count) { /* ok, need to allocate another off the list */ + if (poll_count >= poll_max) { /* bounds-check... */ + log_write(LS_SYSTEM, L_ERROR, 0, + "Attempt to add socket %d (> %d) to event engine", sock->s_fd, + poll_max); + return 0; + } + + i = poll_count++; + Debug((DEBUG_ENGINE, "poll: Allocating a new slot: %d", i)); + } + + s_ed_int(sock) = i; /* set engine data */ + sockList[i] = sock; /* enter socket into data structures */ + pollfdList[i].fd = s_fd(sock); + + Debug((DEBUG_ENGINE, "poll: Adding socket %d to engine on %d [%p], state %s", + s_fd(sock), s_ed_int(sock), sock, state_to_name(s_state(sock)))); + + /* set the appropriate bits */ + set_or_clear(i, 0, state_to_events(s_state(sock), s_events(sock))); + + return 1; /* success */ +} + +/* socket switching to new state */ +static void +engine_state(struct Socket* sock, enum SocketState new_state) +{ + assert(0 != sock); + assert(sock == sockList[s_ed_int(sock)]); + assert(s_fd(sock) == pollfdList[s_ed_int(sock)].fd); + + Debug((DEBUG_ENGINE, "poll: Changing state for socket %p to %s", sock, + state_to_name(new_state))); + + /* set the correct events */ + set_or_clear(s_ed_int(sock), + state_to_events(s_state(sock), s_events(sock)), /* old state */ + state_to_events(new_state, s_events(sock))); /* new state */ +} + +/* socket events changing */ +static void +engine_events(struct Socket* sock, unsigned int new_events) +{ + assert(0 != sock); + assert(sock == sockList[s_ed_int(sock)]); + assert(s_fd(sock) == pollfdList[s_ed_int(sock)].fd); + + Debug((DEBUG_ENGINE, "poll: Changing event mask for socket %p to [%s]", sock, + sock_flags(new_events))); + + /* set the correct events */ + set_or_clear(s_ed_int(sock), + state_to_events(s_state(sock), s_events(sock)), /* old events */ + state_to_events(s_state(sock), new_events)); /* new events */ +} + +/* socket going away */ +static void +engine_delete(struct Socket* sock) +{ + assert(0 != sock); + assert(sock == sockList[s_ed_int(sock)]); + assert(s_fd(sock) == pollfdList[s_ed_int(sock)].fd); + + Debug((DEBUG_ENGINE, "poll: Deleting socket %d (%d) [%p], state %s", + s_fd(sock), s_ed_int(sock), sock, state_to_name(s_state(sock)))); + + /* clear the events */ + pollfdList[s_ed_int(sock)].fd = -1; + pollfdList[s_ed_int(sock)].events = 0; + + /* zero the socket list entry */ + sockList[s_ed_int(sock)] = 0; + + /* update poll_count */ + while (poll_count > 0 && sockList[poll_count - 1] == 0) + poll_count--; +} + +/* socket event loop */ +static void +engine_loop(struct Generators* gen) +{ + int wait; + int nfds; + int i; + int errcode; + size_t codesize; + struct Socket *sock; + + while (running) { + wait = timer_next(gen) ? (timer_next(gen) - CurrentTime) * 1000 : -1; + + Debug((DEBUG_INFO, "poll: delay: %Tu (%Tu) %d", timer_next(gen), + CurrentTime, wait)); + + /* check for active files */ + nfds = poll(pollfdList, poll_count, wait); + + CurrentTime = time(0); /* set current time... */ + + if (nfds < 0) { + if (errno != EINTR) { /* ignore poll interrupts */ + /* Log the poll error */ + log_write(LS_SOCKET, L_ERROR, 0, "poll() error: %m"); + if (!errors++) + timer_add(&clear_error, error_clear, 0, TT_PERIODIC, + ERROR_EXPIRE_TIME); + else if (errors > POLL_ERROR_THRESHOLD) /* too many errors... */ + server_restart("too many poll errors"); + } + /* old code did a sleep(1) here; with usage these days, + * that may be too expensive + */ + continue; + } + + for (i = 0; nfds && i < poll_count; i++) { + if (!(sock = sockList[i])) /* skip empty socket elements */ + continue; + + assert(s_fd(sock) == pollfdList[i].fd); + + gen_ref_inc(sock); /* can't have it going away on us */ + + Debug((DEBUG_ENGINE, "poll: Checking socket %p (fd %d, index %d, " + "state %s, events %s", sock, s_fd(sock), i, + state_to_name(s_state(sock)), sock_flags(s_events(sock)))); + + if (s_state(sock) != SS_NOTSOCK) { + errcode = 0; /* check for errors on socket */ + codesize = sizeof(errcode); + if (getsockopt(s_fd(sock), SOL_SOCKET, SO_ERROR, &errcode, + &codesize) < 0) + errcode = errno; /* work around Solaris implementation */ + + if (errcode) { /* an error occurred; generate an event */ + Debug((DEBUG_ENGINE, "poll: Error %d on fd %d (index %d), socket %p", + errcode, s_fd(sock), i, sock)); + event_generate(ET_ERROR, sock, errcode); + gen_ref_dec(sock); /* careful not to leak ref counts */ + nfds--; + continue; + } + } + + switch (s_state(sock)) { + case SS_CONNECTING: + if (pollfdList[i].revents & POLLWRITEFLAGS) { /* connect completed */ + Debug((DEBUG_ENGINE, "poll: Connection completed")); + event_generate(ET_CONNECT, sock, 0); + nfds--; + } + break; + + case SS_LISTENING: + if (pollfdList[i].revents & POLLREADFLAGS) { /* ready for accept */ + Debug((DEBUG_ENGINE, "poll: Ready for accept")); + event_generate(ET_ACCEPT, sock, 0); + nfds--; + } + break; + + case SS_NOTSOCK: + if (pollfdList[i].revents & POLLREADFLAGS) { /* data on socket */ + /* can't peek; it's not a socket */ + Debug((DEBUG_ENGINE, "poll: non-socket readable")); + event_generate(ET_READ, sock, 0); + nfds--; + } + break; + + case SS_CONNECTED: + if (pollfdList[i].revents & POLLREADFLAGS) { /* data on socket */ + char c; + + switch (recv(s_fd(sock), &c, 1, MSG_PEEK)) { /* check EOF */ + case -1: /* error occurred?!? */ + if (errno == EAGAIN) { + Debug((DEBUG_ENGINE, "poll: Resource temporarily unavailable?")); + continue; + } + Debug((DEBUG_ENGINE, "poll: Uncaught error!")); + event_generate(ET_ERROR, sock, errno); + break; + + case 0: /* EOF from client */ + Debug((DEBUG_ENGINE, "poll: EOF from client")); + event_generate(ET_EOF, sock, 0); + break; + + default: /* some data can be read */ + Debug((DEBUG_ENGINE, "poll: Data to be read")); + event_generate(ET_READ, sock, 0); + break; + } + } + if (pollfdList[i].revents & POLLWRITEFLAGS) { /* socket writable */ + Debug((DEBUG_ENGINE, "poll: Data can be written")); + event_generate(ET_WRITE, sock, 0); + } + if (pollfdList[i].revents & (POLLREADFLAGS | POLLWRITEFLAGS)) + nfds--; + break; + + case SS_DATAGRAM: case SS_CONNECTDG: + if (pollfdList[i].revents & POLLREADFLAGS) { /* socket readable */ + Debug((DEBUG_ENGINE, "poll: Datagram to be read")); + event_generate(ET_READ, sock, 0); + } + if (pollfdList[i].revents & POLLWRITEFLAGS) { /* socket writable */ + Debug((DEBUG_ENGINE, "poll: Datagram can be written")); + event_generate(ET_WRITE, sock, 0); + } + if (pollfdList[i].revents & (POLLREADFLAGS | POLLWRITEFLAGS)) + nfds--; + break; + } + + assert(s_fd(sock) == pollfdList[i].fd); + + gen_ref_dec(sock); /* we're done with it */ + } + + timer_run(); /* execute any pending timers */ + } +} + +struct Engine engine_poll = { + "poll()", /* Engine name */ + engine_init, /* Engine initialization function */ + 0, /* Engine signal registration function */ + engine_add, /* Engine socket registration function */ + engine_state, /* Engine socket state change function */ + engine_events, /* Engine socket events mask function */ + engine_delete, /* Engine socket deletion function */ + engine_loop /* Core engine event loop */ +}; diff --git a/ircd/engine_select.c b/ircd/engine_select.c new file mode 100644 index 0000000..f09c771 --- /dev/null +++ b/ircd/engine_select.c @@ -0,0 +1,375 @@ +/* + * IRC - Internet Relay Chat, ircd/engine_select.c + * Copyright (C) 2001 Kevin L. Mitchell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#include "config.h" + +#include "ircd_events.h" + +#include "ircd.h" +#include "ircd_log.h" +#include "s_debug.h" + +/* On BSD, define FD_SETSIZE to what we want before including sys/types.h */ +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__bsdi__) +# if !defined(FD_SETSIZE) +# define FD_SETSIZE MAXCONNECTIONS +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include + +#define SELECT_ERROR_THRESHOLD 20 /* after 20 select errors, restart */ +#define ERROR_EXPIRE_TIME 3600 /* expire errors after an hour */ + +static struct Socket* sockList[FD_SETSIZE]; +static int highest_fd; +static fd_set global_read_set; +static fd_set global_write_set; + +static int errors = 0; +static struct Timer clear_error; + +/* decrements the error count once per hour */ +static void +error_clear(struct Event* ev) +{ + if (!--errors) /* remove timer when error count reaches 0 */ + timer_del(ev_timer(ev)); +} + +/* initialize the select engine */ +static int +engine_init(int max_sockets) +{ + int i; + + if (max_sockets > FD_SETSIZE) { /* too many sockets */ + log_write(LS_SYSTEM, L_WARNING, 0, + "select() engine cannot handle %d sockets (> %d)", + max_sockets, FD_SETSIZE); + return 0; + } + + FD_ZERO(&global_read_set); /* zero the global fd sets */ + FD_ZERO(&global_write_set); + + for (i = 0; i < FD_SETSIZE; i++) /* zero the sockList */ + sockList[i] = 0; + + highest_fd = -1; /* No fds in set */ + + return 1; /* initialization successful */ +} + +/* Figure out what events go with a given state */ +static unsigned int +state_to_events(enum SocketState state, unsigned int events) +{ + switch (state) { + case SS_CONNECTING: /* connecting socket */ + return SOCK_EVENT_WRITABLE; + break; + + case SS_LISTENING: /* listening socket */ + case SS_NOTSOCK: /* our signal socket */ + return SOCK_EVENT_READABLE; + break; + + case SS_CONNECTED: case SS_DATAGRAM: case SS_CONNECTDG: + return events; /* ordinary socket */ + break; + } + + /*NOTREACHED*/ + return 0; +} + +/* Toggle bits in the global fd sets appropriately */ +static void +set_or_clear(int fd, unsigned int clear, unsigned int set) +{ + if ((clear ^ set) & SOCK_EVENT_READABLE) { /* readable has changed */ + if (set & SOCK_EVENT_READABLE) /* it's set */ + FD_SET(fd, &global_read_set); + else /* clear it */ + FD_CLR(fd, &global_read_set); + } + + if ((clear ^ set) & SOCK_EVENT_WRITABLE) { /* writable has changed */ + if (set & SOCK_EVENT_WRITABLE) /* it's set */ + FD_SET(fd, &global_write_set); + else /* clear it */ + FD_CLR(fd, &global_write_set); + } +} + +/* add a socket to be listened on */ +static int +engine_add(struct Socket* sock) +{ + assert(0 != sock); + assert(0 == sockList[s_fd(sock)]); + + /* bounds-check... */ + if (s_fd(sock) >= FD_SETSIZE) { + log_write(LS_SYSTEM, L_ERROR, 0, + "Attempt to add socket %d (> %d) to event engine", s_fd(sock), + FD_SETSIZE); + return 0; + } + + sockList[s_fd(sock)] = sock; /* add to list */ + + if (s_fd(sock) >= highest_fd) /* update highest_fd */ + highest_fd = s_fd(sock); + + Debug((DEBUG_ENGINE, "select: Adding socket %d to engine [%p], state %s", + s_fd(sock), sock, state_to_name(s_state(sock)))); + + /* set the fd set bits */ + set_or_clear(s_fd(sock), 0, state_to_events(s_state(sock), s_events(sock))); + + return 1; /* success */ +} + +/* socket switching to new state */ +static void +engine_state(struct Socket* sock, enum SocketState new_state) +{ + assert(0 != sock); + assert(sock == sockList[s_fd(sock)]); + + Debug((DEBUG_ENGINE, "select: Changing state for socket %p to %s", sock, + state_to_name(new_state))); + + /* set the correct events */ + set_or_clear(s_fd(sock), + state_to_events(s_state(sock), s_events(sock)), /* old state */ + state_to_events(new_state, s_events(sock))); /* new state */ +} + +/* socket events changing */ +static void +engine_events(struct Socket* sock, unsigned int new_events) +{ + assert(0 != sock); + assert(sock == sockList[s_fd(sock)]); + + Debug((DEBUG_ENGINE, "select: Changing event mask for socket %p to [%s]", + sock, sock_flags(new_events))); + + /* set the correct events */ + set_or_clear(s_fd(sock), + state_to_events(s_state(sock), s_events(sock)), /* old events */ + state_to_events(s_state(sock), new_events)); /* new events */ +} + +/* socket going away */ +static void +engine_delete(struct Socket* sock) +{ + assert(0 != sock); + assert(sock == sockList[s_fd(sock)]); + + Debug((DEBUG_ENGINE, "select: Deleting socket %d [%p], state %s", s_fd(sock), + sock, state_to_name(s_state(sock)))); + + FD_CLR(s_fd(sock), &global_read_set); /* clear event set bits */ + FD_CLR(s_fd(sock), &global_write_set); + + sockList[s_fd(sock)] = 0; /* zero the socket list entry */ + + while (highest_fd > -1 && sockList[highest_fd] == 0) /* update highest_fd */ + highest_fd--; +} + +/* engine event loop */ +static void +engine_loop(struct Generators* gen) +{ + struct timeval wait; + fd_set read_set; + fd_set write_set; + int nfds; + int i; + int errcode; + size_t codesize; + struct Socket *sock; + + while (running) { + read_set = global_read_set; /* all hail structure copy!! */ + write_set = global_write_set; + + /* set up the sleep time */ + wait.tv_sec = timer_next(gen) ? (timer_next(gen) - CurrentTime) : -1; + wait.tv_usec = 0; + + Debug((DEBUG_INFO, "select: delay: %Tu (%Tu) %Tu", timer_next(gen), + CurrentTime, wait.tv_sec)); + + /* check for active files */ + nfds = select(highest_fd + 1, &read_set, &write_set, 0, + wait.tv_sec < 0 ? 0 : &wait); + + CurrentTime = time(0); /* set current time... */ + + if (nfds < 0) { + if (errno != EINTR) { /* ignore select interrupts */ + /* Log the select error */ + log_write(LS_SOCKET, L_ERROR, 0, "select() error: %m"); + if (!errors++) + timer_add(&clear_error, error_clear, 0, TT_PERIODIC, + ERROR_EXPIRE_TIME); + else if (errors > SELECT_ERROR_THRESHOLD) /* too many errors... */ + server_restart("too many select errors"); + } + /* old code did a sleep(1) here; with usage these days, + * that may be too expensive + */ + continue; + } + + for (i = 0; nfds && i <= highest_fd; i++) { + if (!(sock = sockList[i])) /* skip empty socket elements */ + continue; + + assert(s_fd(sock) == i); + + gen_ref_inc(sock); /* can't have it going away on us */ + + Debug((DEBUG_ENGINE, "select: Checking socket %p (fd %d) state %s, " + "events %s", sock, i, state_to_name(s_state(sock)), + sock_flags(s_events(sock)))); + + if (s_state(sock) != SS_NOTSOCK) { + errcode = 0; /* check for errors on socket */ + codesize = sizeof(errcode); + if (getsockopt(i, SOL_SOCKET, SO_ERROR, &errcode, &codesize) < 0) + errcode = errno; /* work around Solaris implementation */ + + if (errcode) { /* an error occurred; generate an event */ + Debug((DEBUG_ENGINE, "select: Error %d on fd %d, socket %p", errcode, + i, sock)); + event_generate(ET_ERROR, sock, errcode); + gen_ref_dec(sock); /* careful not to leak reference counts */ + continue; + } + } + + switch (s_state(sock)) { + case SS_CONNECTING: + if (FD_ISSET(i, &write_set)) { /* connection completed */ + Debug((DEBUG_ENGINE, "select: Connection completed")); + event_generate(ET_CONNECT, sock, 0); + nfds--; + continue; + } + break; + + case SS_LISTENING: + if (FD_ISSET(i, &read_set)) { /* connection to be accepted */ + Debug((DEBUG_ENGINE, "select: Ready for accept")); + event_generate(ET_ACCEPT, sock, 0); + nfds--; + } + break; + + case SS_NOTSOCK: + if (FD_ISSET(i, &read_set)) { /* data on socket */ + /* can't peek; it's not a socket */ + Debug((DEBUG_ENGINE, "select: non-socket readable")); + event_generate(ET_READ, sock, 0); + nfds--; + } + break; + + case SS_CONNECTED: + if (FD_ISSET(i, &read_set)) { /* data to be read from socket */ + char c; + + switch (recv(i, &c, 1, MSG_PEEK)) { /* check for EOF */ + case -1: /* error occurred?!? */ + if (errno == EAGAIN) { + Debug((DEBUG_ENGINE, "select: Resource temporarily " + "unavailable?")); + continue; + } + Debug((DEBUG_ENGINE, "select: Uncaught error!")); + event_generate(ET_ERROR, sock, errno); + break; + + case 0: /* EOF from client */ + Debug((DEBUG_ENGINE, "select: EOF from client")); + event_generate(ET_EOF, sock, 0); + break; + + default: /* some data can be read */ + Debug((DEBUG_ENGINE, "select: Data to be read")); + event_generate(ET_READ, sock, 0); + break; + } + } + if (FD_ISSET(i, &write_set)) { /* data can be written to socket */ + Debug((DEBUG_ENGINE, "select: Data can be written")); + event_generate(ET_WRITE, sock, 0); + } + if (FD_ISSET(i, &read_set) || FD_ISSET(i, &write_set)) + nfds--; + break; + + case SS_DATAGRAM: case SS_CONNECTDG: + if (FD_ISSET(i, &read_set)) { /* data to be read from socket */ + Debug((DEBUG_ENGINE, "select: Datagram to be read")); + event_generate(ET_READ, sock, 0); + } + if (FD_ISSET(i, &write_set)) { /* data can be written to socket */ + Debug((DEBUG_ENGINE, "select: Datagram can be written")); + event_generate(ET_WRITE, sock, 0); + } + if (FD_ISSET(i, &read_set) || FD_ISSET(i, &write_set)) + nfds--; + break; + } + + assert(s_fd(sock) == i); + + gen_ref_dec(sock); /* we're done with it */ + } + + timer_run(); /* execute any pending timers */ + } +} + +struct Engine engine_select = { + "select()", /* Engine name */ + engine_init, /* Engine initialization function */ + 0, /* Engine signal registration function (none) */ + engine_add, /* Engine socket registration function */ + engine_state, /* Engine socket state change function */ + engine_events, /* Engine socket events mask function */ + engine_delete, /* Engine socket deletion function */ + engine_loop /* Core engine event loop */ +}; diff --git a/ircd/ircd.c b/ircd/ircd.c index 97ff9f1..cfee4af 100644 --- a/ircd/ircd.c +++ b/ircd/ircd.c @@ -28,6 +28,7 @@ #include "crule.h" #include "hash.h" #include "ircd_alloc.h" +#include "ircd_events.h" #include "ircd_features.h" #include "ircd_log.h" #include "ircd_reply.h" @@ -100,11 +101,12 @@ int debuglevel = -1; /* Server debug level */ char *debugmode = ""; /* Server debug level */ static char *dpath = DPATH; -time_t nextconnect = 1; /* time for next try_connections call */ -time_t nextping = 1; /* same as above for check_pings() */ +static struct Timer connect_timer; /* timer structure for try_connections() */ +static struct Timer ping_timer; /* timer structure for check_pings() */ static struct Daemon thisServer = { 0, 0, 0, 0, 0, 0, 0, -1, 0, 0, 0 }; +int running = 1; /*---------------------------------------------------------------------------- @@ -115,7 +117,7 @@ void server_die(const char* message) { log_write(LS_SYSTEM, L_CRIT, 0, "Server terminating: %s", message); flush_connections(0); close_connections(1); - thisServer.running = 0; + running = 0; } @@ -215,7 +217,7 @@ static int check_pid(void) * function should be made latest. (No harm done if this * is called earlier or later...) *--------------------------------------------------------------------------*/ -static time_t try_connections(void) { +static void try_connections(struct Event* ev) { struct ConfItem* aconf; struct Client* cptr; struct ConfItem** pconf; @@ -227,6 +229,9 @@ static time_t try_connections(void) { struct Jupe* ajupe; unsigned int con_class = 0; + assert(ET_EXPIRE == ev_type(ev)); + assert(0 != ev_timer(ev)); + connecting = FALSE; Debug((DEBUG_NOTICE, "Connection check at : %s", myctime(CurrentTime))); for (aconf = GlobalConfList; aconf; aconf = aconf->next) { @@ -286,8 +291,12 @@ static time_t try_connections(void) { con_conf->name); } + if (next == 0) + next = CurrentTime + feature_int(FEAT_CONNECTFREQUENCY); + Debug((DEBUG_NOTICE, "Next connection check : %s", myctime(next))); - return(next); + + timer_add(&connect_timer, try_connections, 0, TT_ABSOLUTE, next); } @@ -298,12 +307,15 @@ static time_t try_connections(void) { * get right down to it. Can't really be done until the server is more * modular, however... *--------------------------------------------------------------------------*/ -static time_t check_pings(void) { - int expire = 0; +static void check_pings(struct Event* ev) { + int expire = 0; int next_check = CurrentTime; int max_ping = 0; int i; + assert(ET_EXPIRE == ev_type(ev)); + assert(0 != ev_timer(ev)); + next_check += feature_int(FEAT_PINGFREQUENCY); /* Scan through the client table */ @@ -326,7 +338,8 @@ static time_t check_pings(void) { feature_int(FEAT_CONNECTTIMEOUT); Debug((DEBUG_DEBUG, "check_pings(%s)=status:%s limit: %d current: %d", - cli_name(cptr), (cli_flags(cptr) & FLAGS_PINGSENT) ? "[Ping Sent]" : "[]", + cli_name(cptr), + (cli_flags(cptr) & FLAGS_PINGSENT) ? "[Ping Sent]" : "[]", max_ping, (int)(CurrentTime - cli_lasttime(cptr)))); @@ -345,7 +358,8 @@ static time_t check_pings(void) { /* If it was a server, then tell ops about it. */ if (IsServer(cptr) || IsConnecting(cptr) || IsHandshake(cptr)) sendto_opmask_butone(0, SNO_OLDSNO, - "No response from %s, closing link", cli_name(cptr)); + "No response from %s, closing link", + cli_name(cptr)); exit_client_msg(cptr, cptr, &me, "Ping timeout"); continue; } @@ -395,7 +409,7 @@ static time_t check_pings(void) { Debug((DEBUG_DEBUG, "[%i] check_pings() again in %is", CurrentTime, next_check-CurrentTime)); - return next_check; + timer_add(&ping_timer, check_pings, 0, TT_ABSOLUTE, next_check); } @@ -468,71 +482,6 @@ static void daemon_init(int no_fork) { setsid(); } - -/*---------------------------------------------------------------------------- - * event_loop - *--------------------------------------------------------------------------*/ -static void event_loop(void) { - time_t nextdnscheck = 0; - time_t delay = 0; - - thisServer.running = 1; - while (thisServer.running) { - /* We only want to connect if a connection is due, not every time through. - * Note, if there are no active C lines, this call to Tryconnections is - * made once only; it will return 0. - avalon - */ - if (nextconnect && CurrentTime >= nextconnect) - nextconnect = try_connections(); - - /* DNS checks. One to timeout queries, one for cache expiries. */ - nextdnscheck = timeout_resolver(CurrentTime); - - /* Take the smaller of the two 'timed' event times as the time of next - * event (stops us being late :) - avalon - * WARNING - nextconnect can return 0! - */ - if (nextconnect) - delay = IRCD_MIN(nextping, nextconnect); - else - delay = nextping; - - delay = IRCD_MIN(nextdnscheck, delay) - CurrentTime; - - /* Adjust delay to something reasonable [ad hoc values] (one might think - * something more clever here... --msa) We don't really need to check that - * often and as long as we don't delay too long, everything should be ok. - * waiting too long can cause things to timeout... i.e. PINGS -> a - * disconnection :( - avalon - */ - if (delay < 1) - read_message(1); - else - read_message(IRCD_MIN(delay, feature_int(FEAT_TIMESEC))); - - /* ...perhaps should not do these loops every time, but only if there is - * some chance of something happening (but, note that conf->hold times may - * be changed elsewhere--so precomputed next event time might be too far - * away... (similarly with ping times) --msa - */ - if (CurrentTime >= nextping) - nextping = check_pings(); - - /* timeout pending queries that haven't been responded to */ - timeout_auth_queries(CurrentTime); - - IPcheck_expire(); - - if (GlobalRehashFlag) { - rehash(&me, 1); - GlobalRehashFlag = 0; - } - - if (GlobalRestartFlag) - server_restart("caught signal: SIGINT"); - } -} - /*---------------------------------------------------------------------------- * check_file_access: random helper function to make sure that a file is * accessible in a certain way, and complain if not. @@ -672,6 +621,7 @@ int main(int argc, char **argv) { debug_init(thisServer.bootopt & BOOT_TTY); daemon_init(thisServer.bootopt & BOOT_TTY); + event_init(MAXCONNECTIONS); setup_signals(); feature_init(); /* initialize features... */ @@ -709,9 +659,14 @@ int main(int argc, char **argv) { uping_init(); + IPcheck_init(); + timer_add(&connect_timer, try_connections, 0, TT_RELATIVE, 1); + timer_add(&ping_timer, check_pings, 0, TT_RELATIVE, 1); + CurrentTime = time(NULL); SetMe(&me); + cli_magic(&me) = CLIENT_MAGIC; cli_from(&me) = &me; make_server(&me); diff --git a/ircd/ircd_events.c b/ircd/ircd_events.c new file mode 100644 index 0000000..6befeae --- /dev/null +++ b/ircd/ircd_events.c @@ -0,0 +1,736 @@ +/* + * IRC - Internet Relay Chat, ircd/ircd_events.c + * Copyright (C) 2001 Kevin L. Mitchell + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ +#include "config.h" + +#include "ircd_events.h" + +#include "ircd.h" +#include "ircd_alloc.h" +#include "ircd_log.h" +#include "ircd_snprintf.h" +#include "s_debug.h" + +#include +#include +#include + +#define SIGS_PER_SOCK 10 /* number of signals to process per socket + readable event */ + +#ifdef USE_KQUEUE +extern struct Engine engine_kqueue; +#define ENGINE_KQUEUE &engine_kqueue, +#else +#define ENGINE_KQUEUE +#endif /* USE_KQUEUE */ + +#ifdef USE_DEVPOLL +extern struct Engine engine_devpoll; +#define ENGINE_DEVPOLL &engine_devpoll, +#else +#define ENGINE_DEVPOLL +#endif /* USE_DEVPOLL */ + +#ifdef USE_POLL +extern struct Engine engine_poll; +#define ENGINE_FALLBACK &engine_poll, +#else +extern struct Engine engine_select; +#define ENGINE_FALLBACK &engine_select, +#endif /* USE_POLL */ + +/* list of engines to try */ +static const struct Engine *evEngines[] = { + ENGINE_KQUEUE + ENGINE_DEVPOLL + ENGINE_FALLBACK + 0 +}; + +/* signal routines pipe data */ +static struct { + int fd; /* signal routine's fd */ + struct Socket sock; /* and its struct Socket */ +} sigInfo = { -1 }; + +/* All the thread info */ +static struct { + struct Generators gens; /* List of all generators */ + struct Event* events_free; /* struct Event free list */ + unsigned int events_alloc; /* count of allocated struct Events */ + const struct Engine* engine; /* core engine being used */ +#ifdef IRCD_THREADED + struct GenHeader* genq_head; /* head of generator event queue */ + struct GenHeader* genq_tail; /* tail of generator event queue */ + unsigned int genq_count; /* count of generators on queue */ +#endif +} evInfo = { + { 0, 0, 0 }, + 0, 0, 0 +#ifdef IRCD_THREADED + , 0, 0, 0 +#endif +}; + +/* Initialize a struct GenHeader */ +static void +gen_init(struct GenHeader* gen, EventCallBack call, void* data, + struct GenHeader* next, struct GenHeader** prev_p) +{ + assert(0 != gen); + + gen->gh_next = next; + gen->gh_prev_p = prev_p; +#ifdef IRCD_THREADED + gen->gh_qnext = 0; + gen->gh_qprev_p = 0; + gen->gh_head = 0; + gen->gh_tail = 0; +#endif + gen->gh_flags = GEN_ACTIVE; + gen->gh_ref = 0; + gen->gh_call = call; + gen->gh_data = data; + gen->gh_engdata.ed_int = 0; + + if (prev_p) { /* Going to link into list? */ + if (next) /* do so */ + next->gh_prev_p = &gen->gh_next; + *prev_p = gen; + } +} + +/* Execute an event; optimizations should inline this */ +static void +event_execute(struct Event* event) +{ + assert(0 != event); + assert(0 == event->ev_prev_p); /* must be off queue first */ + assert(event->ev_gen.gen_header->gh_flags & GEN_ACTIVE); + + if (event->ev_type == ET_DESTROY) /* turn off active flag *before* destroy */ + event->ev_gen.gen_header->gh_flags &= ~GEN_ACTIVE; + + (*event->ev_gen.gen_header->gh_call)(event); /* execute the event */ + + /* The logic here is very careful; if the event was an ET_DESTROY, + * then we must assume the generator is now invalid; fortunately, we + * don't need to do anything to it if so. Otherwise, we decrement + * the reference count; if reference count goes to zero, AND we need + * to destroy the generator, THEN we generate a DESTROY event. + */ + if (event->ev_type != ET_DESTROY) + gen_ref_dec(event->ev_gen.gen_header); + + event->ev_gen.gen_header = 0; /* clear event data */ + event->ev_type = ET_DESTROY; + + event->ev_next = evInfo.events_free; /* add to free list */ + evInfo.events_free = event; +} + +#ifndef IRCD_THREADED +/* we synchronously execute the event when not threaded */ +#define event_add(event) \ +do { \ + struct Event* _ev = (event); \ + _ev->ev_next = 0; \ + _ev->ev_prev_p = 0; \ + event_execute(_ev); \ +} while (0) + +#else +/* add an event to the work queue */ +/* This is just a placeholder; don't expect ircd to be threaded soon */ +/* There should be locks all over the place in here */ +static void +event_add(struct Event* event) +{ + struct GenHeader* gen; + + assert(0 != event); + + gen = event->ev_gen.gen_header; + + /* First, place event on generator's event queue */ + event->ev_next = 0; + if (gen->gh_head) { + assert(0 != gen->gh_tail); + + event->ev_prev_p = &gen->gh_tail->ev_next; + gen->gh_tail->ev_next = event; + gen->gh_tail = event; + } else { /* queue was empty */ + assert(0 == gen->gh_tail); + + event->ev_prev_p = &gen->gh_head; + gen->gh_head = event; + gen->gh_tail = event; + } + + /* Now, if the generator isn't on the queue yet... */ + if (!gen->gh_qprev_p) { + gen->gh_qnext = 0; + if (evInfo.genq_head) { + assert(0 != evInfo.genq_tail); + + gen->gh_qprev_p = &evInfo.genq_tail->gh_qnext; + evInfo.genq_tail->gh_qnext = gen; + evInfo.genq_tail = gen; + } else { /* queue was empty */ + assert(0 == evInfo.genq_tail); + + gen->gh_qprev_p = &evInfo.genq_head; + evInfo.genq_head = gen; + evInfo.genq_tail = gen; + } + + /* We'd also have to signal the work crew here */ + } +} +#endif /* IRCD_THREADED */ + +/* Place a timer in the correct spot on the queue */ +static void +timer_enqueue(struct Timer* timer) +{ + struct Timer** ptr_p; + + assert(0 != timer); + assert(0 == timer->t_header.gh_prev_p); /* not already on queue */ + + /* Calculate expire time */ + switch (timer->t_type) { + case TT_ABSOLUTE: /* no need to consider it relative */ + timer->t_expire = timer->t_value; + break; + + case TT_RELATIVE: case TT_PERIODIC: /* relative timer */ + timer->t_expire = timer->t_value + CurrentTime; + break; + } + + /* Find a slot to insert timer */ + for (ptr_p = &evInfo.gens.g_timer; ; + ptr_p = (struct Timer**) &(*ptr_p)->t_header.gh_next) + if (!*ptr_p || timer->t_expire < (*ptr_p)->t_expire) + break; + + /* link it in the right place */ + timer->t_header.gh_next = (struct GenHeader*) *ptr_p; + timer->t_header.gh_prev_p = (struct GenHeader**) ptr_p; + if (*ptr_p) + (*ptr_p)->t_header.gh_prev_p = &timer->t_header.gh_next; + *ptr_p = timer; +} + +/* signal handler for writing signal notification to pipe */ +static void +signal_handler(int sig) +{ + unsigned char c; + + assert(sigInfo.fd >= 0); + + c = (unsigned char) sig; /* only write 1 byte to identify sig */ + + write(sigInfo.fd, &c, 1); +} + +/* callback for signal "socket" events */ +static void +signal_callback(struct Event* event) +{ + unsigned char sigstr[SIGS_PER_SOCK]; + int sig, n_sigs, i; + struct Signal* ptr; + + assert(event->ev_type == ET_READ); /* readable events only */ + + n_sigs = read(event->ev_gen.gen_socket->s_fd, sigstr, sizeof(sigstr)); + + for (i = 0; i < n_sigs; i++) { + sig = (int) sigstr[i]; /* get signal */ + + for (ptr = evInfo.gens.g_signal; ptr; + ptr = (struct Signal*) ptr->sig_header.gh_next) + if (ptr->sig_signal == sig) /* find its descriptor... */ + break; + + if (ptr) + event_generate(ET_SIGNAL, ptr, sig); /* generate signal event */ + } +} + +/* Remove something from its queue */ +void +gen_dequeue(void* arg) +{ + struct GenHeader* gen = (struct GenHeader*) arg; + + if (gen->gh_next) /* clip it out of the list */ + gen->gh_next->gh_prev_p = gen->gh_prev_p; + if (gen->gh_prev_p) + *gen->gh_prev_p = gen->gh_next; + + gen->gh_next = 0; /* mark that it's not in the list anymore */ + gen->gh_prev_p = 0; +} + +/* Initializes the event system */ +void +event_init(int max_sockets) +{ + int i, p[2]; + + for (i = 0; evEngines[i]; i++) { /* look for an engine... */ + assert(0 != evEngines[i]->eng_name); + assert(0 != evEngines[i]->eng_init); + + if ((*evEngines[i]->eng_init)(max_sockets)) + break; /* Found an engine that'll work */ + } + + assert(0 != evEngines[i]); + + evInfo.engine = evEngines[i]; /* save engine */ + + if (!evInfo.engine->eng_signal) { /* engine can't do signals */ + if (pipe(p)) { + log_write(LS_SYSTEM, L_CRIT, 0, "Failed to open signal pipe"); + exit(8); + } + + sigInfo.fd = p[1]; /* write end of pipe */ + socket_add(&sigInfo.sock, signal_callback, 0, SS_NOTSOCK, + SOCK_EVENT_READABLE, p[0]); /* read end of pipe */ + } +} + +/* Do the event loop */ +void +event_loop(void) +{ + assert(0 != evInfo.engine); + assert(0 != evInfo.engine->eng_loop); + + (*evInfo.engine->eng_loop)(&evInfo.gens); +} + +/* Generate an event and add it to the queue (or execute it) */ +void +event_generate(enum EventType type, void* arg, int data) +{ + struct Event* ptr; + struct GenHeader* gen = (struct GenHeader*) arg; + + assert(0 != gen); + + /* don't create events (other than ET_DESTROY) for destroyed generators */ + if (type != ET_DESTROY && (gen->gh_flags & GEN_DESTROY)) + return; + + Debug((DEBUG_LIST, "Generating event type %s for generator %p (%s)", + event_to_name(type), gen, gen_flags(gen->gh_flags))); + + if ((ptr = evInfo.events_free)) + evInfo.events_free = ptr->ev_next; /* pop one off the freelist */ + else { /* allocate another structure */ + ptr = (struct Event*) MyMalloc(sizeof(struct Event)); + evInfo.events_alloc++; /* count of allocated events */ + } + + ptr->ev_type = type; /* Record event type */ + ptr->ev_data = data; + + ptr->ev_gen.gen_header = (struct GenHeader*) gen; + ptr->ev_gen.gen_header->gh_ref++; + + event_add(ptr); /* add event to queue */ +} + +/* Add a timer to be processed */ +void +timer_add(struct Timer* timer, EventCallBack call, void* data, + enum TimerType type, time_t value) +{ + assert(0 != timer); + assert(0 != call); + + Debug((DEBUG_LIST, "Adding timer %p; time out %Tu (type %s)", timer, value, + timer_to_name(type))); + + /* initialize a timer... */ + gen_init((struct GenHeader*) timer, call, data, 0, 0); + + timer->t_type = type; + timer->t_value = value; + timer->t_expire = 0; + + timer_enqueue(timer); /* and enqueue it */ +} + +/* Remove a timer from the processing queue */ +void +timer_del(struct Timer* timer) +{ + assert(0 != timer); + + if (timer->t_header.gh_flags & GEN_MARKED) + return; /* timer already marked for destruction */ + + timer->t_header.gh_flags |= GEN_DESTROY; + + Debug((DEBUG_LIST, "Deleting timer %p (type %s)", timer, + timer_to_name(timer->t_type))); + + if (!timer->t_header.gh_ref) { /* not in use; destroy right now */ + gen_dequeue(timer); + event_generate(ET_DESTROY, timer, 0); + } +} + +/* Change the time a timer expires */ +void +timer_chg(struct Timer* timer, enum TimerType type, time_t value) +{ + assert(0 != timer); + assert(0 != value); + assert(TT_PERIODIC != timer->t_type); + assert(TT_PERIODIC != type); + + Debug((DEBUG_LIST, "Changing timer %p from type %s timeout %Tu to type %s " + "timeout %Tu", timer, timer_to_name(timer->t_type), timer->t_value, + timer_to_name(type), value)); + + gen_dequeue(timer); /* remove the timer from the queue */ + + timer->t_type = type; /* Set the new type and value */ + timer->t_value = value; + timer->t_expire = 0; + + timer_enqueue(timer); /* re-queue the timer */ +} + +/* Execute all expired timers */ +void +timer_run(void) +{ + struct Timer* ptr; + struct Timer* next = 0; + + /* go through queue... */ + for (ptr = evInfo.gens.g_timer; ptr; ptr = next) { + next = (struct Timer*) ptr->t_header.gh_next; + if (CurrentTime < ptr->t_expire) + break; /* processed all pending timers */ + + gen_dequeue(ptr); /* must dequeue timer here */ + if (ptr->t_type == TT_ABSOLUTE || ptr->t_type == TT_RELATIVE) { + Debug((DEBUG_LIST, "Marking timer %p for later destruction", ptr)); + ptr->t_header.gh_flags |= GEN_MARKED; /* mark for destruction */ + } + event_generate(ET_EXPIRE, ptr, 0); /* generate expire event */ + + if (ptr->t_header.gh_flags & (GEN_MARKED | GEN_DESTROY)) { + Debug((DEBUG_LIST, "Destroying timer %p", ptr)); + event_generate(ET_DESTROY, ptr, 0); + } else if (ptr->t_type == TT_PERIODIC) { + Debug((DEBUG_LIST, "Re-enqueuing periodic timer %p", ptr)); + timer_enqueue(ptr); /* re-queue periodic timer */ + } + } +} + +/* Adds a signal to the event callback system */ +void +signal_add(struct Signal* signal, EventCallBack call, void* data, int sig) +{ + struct sigaction act; + + assert(0 != signal); + assert(0 != call); + assert(0 != evInfo.engine); + + /* set up struct */ + gen_init((struct GenHeader*) signal, call, data, + (struct GenHeader*) evInfo.gens.g_signal, + (struct GenHeader**) &evInfo.gens.g_signal); + + signal->sig_signal = sig; + + if (evInfo.engine->eng_signal) + (*evInfo.engine->eng_signal)(signal); /* tell engine */ + else { + act.sa_handler = signal_handler; /* set up signal handler */ + act.sa_flags = 0; + sigemptyset(&act.sa_mask); + sigaction(sig, &act, 0); + } +} + +/* Adds a socket to the event system */ +int +socket_add(struct Socket* sock, EventCallBack call, void* data, + enum SocketState state, unsigned int events, int fd) +{ + assert(0 != sock); + assert(0 != call); + assert(fd >= 0); + assert(0 != evInfo.engine); + assert(0 != evInfo.engine->eng_add); + + /* set up struct */ + gen_init((struct GenHeader*) sock, call, data, + (struct GenHeader*) evInfo.gens.g_socket, + (struct GenHeader**) &evInfo.gens.g_socket); + + sock->s_state = state; + sock->s_events = events & SOCK_EVENT_MASK; + sock->s_fd = fd; + + return (*evInfo.engine->eng_add)(sock); /* tell engine about it */ +} + +/* deletes (or marks for deletion) a socket */ +void +socket_del(struct Socket* sock) +{ + assert(0 != sock); + assert(!(sock->s_header.gh_flags & GEN_DESTROY)); + assert(0 != evInfo.engine); + assert(0 != evInfo.engine->eng_closing); + + /* tell engine socket is going away */ + (*evInfo.engine->eng_closing)(sock); + + sock->s_header.gh_flags |= GEN_DESTROY; + + if (!sock->s_header.gh_ref) { /* not in use; destroy right now */ + gen_dequeue(sock); + event_generate(ET_DESTROY, sock, 0); + } +} + +/* Sets the socket state to something else */ +void +socket_state(struct Socket* sock, enum SocketState state) +{ + assert(0 != sock); + assert(0 != evInfo.engine); + assert(0 != evInfo.engine->eng_state); + + /* assertions for invalid socket state transitions */ + assert(sock->s_state != state); /* not changing states ?! */ + assert(sock->s_state != SS_LISTENING); /* listening socket to...?! */ + assert(sock->s_state != SS_CONNECTED); /* connected socket to...?! */ + /* connecting socket now connected */ + assert(sock->s_state != SS_CONNECTING || state == SS_CONNECTED); + /* unconnected datagram socket now connected */ + assert(sock->s_state != SS_DATAGRAM || state == SS_CONNECTDG); + /* connected datagram socket now unconnected */ + assert(sock->s_state != SS_CONNECTDG || state == SS_DATAGRAM); + + if (sock->s_header.gh_flags & GEN_DESTROY) /* socket's been destroyed */ + return; + + /* tell engine we're changing socket state */ + (*evInfo.engine->eng_state)(sock, state); + + sock->s_state = state; /* set new state */ +} + +/* sets the events a socket's interested in */ +void +socket_events(struct Socket* sock, unsigned int events) +{ + unsigned int new_events = 0; + + assert(0 != sock); + assert(0 != evInfo.engine); + assert(0 != evInfo.engine->eng_events); + + if (sock->s_header.gh_flags & GEN_DESTROY) /* socket's been destroyed */ + return; + + switch (events & SOCK_ACTION_MASK) { + case SOCK_ACTION_SET: /* set events to given set */ + new_events = events & SOCK_EVENT_MASK; + break; + + case SOCK_ACTION_ADD: /* add some events */ + new_events = sock->s_events | (events & SOCK_EVENT_MASK); + break; + + case SOCK_ACTION_DEL: /* remove some events */ + new_events = sock->s_events & ~(events & SOCK_EVENT_MASK); + break; + } + + if (sock->s_events == new_events) + return; /* no changes have been made */ + + /* tell engine about event mask change */ + (*evInfo.engine->eng_events)(sock, new_events); + + sock->s_events = new_events; /* set new events */ +} + +/* Returns an engine's name for informational purposes */ +const char* +engine_name(void) +{ + assert(0 != evInfo.engine); + assert(0 != evInfo.engine->eng_name); + + return evInfo.engine->eng_name; +} + +#ifdef DEBUGMODE +/* These routines pretty-print names for states and types for debug printing */ + +#define NS(TYPE) \ +struct { \ + char *name; \ + TYPE value; \ +} + +#define NM(name) { #name, name } + +#define NE { 0, 0 } + +const char* +state_to_name(enum SocketState state) +{ + int i; + NS(enum SocketState) map[] = { + NM(SS_CONNECTING), + NM(SS_LISTENING), + NM(SS_CONNECTED), + NM(SS_DATAGRAM), + NM(SS_CONNECTDG), + NM(SS_NOTSOCK), + NE + }; + + for (i = 0; map[i].name; i++) + if (map[i].value == state) + return map[i].name; + + return "Undefined socket state"; +} + +const char* +timer_to_name(enum TimerType type) +{ + int i; + NS(enum TimerType) map[] = { + NM(TT_ABSOLUTE), + NM(TT_RELATIVE), + NM(TT_PERIODIC), + NE + }; + + for (i = 0; map[i].name; i++) + if (map[i].value == type) + return map[i].name; + + return "Undefined timer type"; +} + +const char* +event_to_name(enum EventType type) +{ + int i; + NS(enum EventType) map[] = { + NM(ET_READ), + NM(ET_WRITE), + NM(ET_ACCEPT), + NM(ET_CONNECT), + NM(ET_EOF), + NM(ET_ERROR), + NM(ET_SIGNAL), + NM(ET_EXPIRE), + NM(ET_DESTROY), + NE + }; + + for (i = 0; map[i].name; i++) + if (map[i].value == type) + return map[i].name; + + return "Undefined event type"; +} + +const char* +gen_flags(unsigned int flags) +{ + int i, loc = 0; + static char buf[256]; + NS(unsigned int) map[] = { + NM(GEN_DESTROY), + NM(GEN_MARKED), + NE + }; + + buf[0] = '\0'; + + for (i = 0; map[i].name; i++) + if (map[i].value & flags) { + if (loc != 0) + buf[loc++] = ' '; + loc += ircd_snprintf(0, buf + loc, sizeof(buf) - loc, "%s", map[i].name); + if (loc >= sizeof(buf)) + return buf; /* overflow case */ + } + + return buf; +} + +const char* +sock_flags(unsigned int flags) +{ + int i, loc = 0; + static char buf[256]; + NS(unsigned int) map[] = { + NM(SOCK_EVENT_READABLE), + NM(SOCK_EVENT_WRITABLE), + NM(SOCK_ACTION_SET), + NM(SOCK_ACTION_ADD), + NM(SOCK_ACTION_DEL), + NE + }; + + buf[0] = '\0'; + + for (i = 0; map[i].name; i++) + if (map[i].value & flags) { + if (loc != 0) + buf[loc++] = ' '; + loc += ircd_snprintf(0, buf + loc, sizeof(buf) - loc, "%s", map[i].name); + if (loc >= sizeof(buf)) + return buf; /* overflow case */ + } + + return buf; +} + +#endif /* DEBUGMODE */ diff --git a/ircd/ircd_signal.c b/ircd/ircd_signal.c index 00e09f5..a250dd9 100644 --- a/ircd/ircd_signal.c +++ b/ircd/ircd_signal.c @@ -21,9 +21,12 @@ */ #include "config.h" -#include "ircd_signal.h" #include "ircd.h" +#include "ircd_events.h" +#include "ircd_signal.h" +#include "s_conf.h" +#include #include static struct tag_SignalCounter { @@ -31,25 +34,44 @@ static struct tag_SignalCounter { unsigned int hup; } SignalCounter; -void sigalrm_handler(int sig) +static struct Signal sig_hup; +static struct Signal sig_int; +static struct Signal sig_term; + +static void sigalrm_handler(int sig) { ++SignalCounter.alrm; } -void sigterm_handler(int sig) +static void sigterm_callback(struct Event* ev) { + assert(0 != ev_signal(ev)); + assert(ET_SIGNAL == ev_type(ev)); + assert(SIGTERM == sig_signal(ev_signal(ev))); + assert(SIGTERM == ev_data(ev)); + server_die("received signal SIGTERM"); } -static void sighup_handler(int sig) +static void sighup_callback(struct Event* ev) { + assert(0 != ev_signal(ev)); + assert(ET_SIGNAL == ev_type(ev)); + assert(SIGHUP == sig_signal(ev_signal(ev))); + assert(SIGHUP == ev_data(ev)); + ++SignalCounter.hup; - GlobalRehashFlag = 1; + rehash(&me, 1); } -static void sigint_handler(int sig) +static void sigint_callback(struct Event* ev) { - GlobalRestartFlag = 1; + assert(0 != ev_signal(ev)); + assert(ET_SIGNAL == ev_type(ev)); + assert(SIGINT == sig_signal(ev_signal(ev))); + assert(SIGINT == ev_data(ev)); + + server_restart("caught signal: SIGINT"); } void setup_signals(void) @@ -70,16 +92,9 @@ void setup_signals(void) act.sa_handler = sigalrm_handler; sigaction(SIGALRM, &act, 0); - sigemptyset(&act.sa_mask); - - act.sa_handler = sighup_handler; - sigaction(SIGHUP, &act, 0); - - act.sa_handler = sigint_handler; - sigaction(SIGINT, &act, 0); - - act.sa_handler = sigterm_handler; - sigaction(SIGTERM, &act, 0); + signal_add(&sig_hup, sighup_callback, 0, SIGHUP); + signal_add(&sig_int, sigint_callback, 0, SIGINT); + signal_add(&sig_term, sigterm_callback, 0, SIGTERM); #ifdef HAVE_RESTARTABLE_SYSCALLS /* diff --git a/ircd/list.c b/ircd/list.c index 581a3ce..b85597d 100644 --- a/ircd/list.c +++ b/ircd/list.c @@ -31,6 +31,7 @@ #include "match.h" #include "numeric.h" #include "res.h" +#include "s_auth.h" #include "s_bsd.h" #include "s_conf.h" #include "s_debug.h" @@ -111,12 +112,17 @@ static struct Client* alloc_client(void) static void dealloc_client(struct Client* cptr) { + assert(cli_verify(cptr)); + assert(0 == cli_connect(cptr)); + #ifdef DEBUGMODE --clients.inuse; #endif cli_next(cptr) = clientFreeList; clientFreeList = cptr; + + cli_magic(cptr) = 0; } static struct Connection* alloc_connection(void) @@ -140,6 +146,10 @@ static struct Connection* alloc_connection(void) static void dealloc_connection(struct Connection* con) { + assert(con_verify(con)); + + Debug((DEBUG_LIST, "Deallocating connection %p", con)); + if (con_dns_reply(con)) --(con_dns_reply(con)->ref_count); if (-1 < con_fd(con)) @@ -156,6 +166,8 @@ static void dealloc_connection(struct Connection* con) con_next(con) = connectionFreeList; connectionFreeList = con; + + con_magic(con) = 0; } /* @@ -172,16 +184,23 @@ struct Client* make_client(struct Client *from, int status) struct Client* cptr = 0; struct Connection* con = 0; + assert(!from || cli_verify(from)); + cptr = alloc_client(); assert(0 != cptr); + assert(!cli_magic(cptr)); + assert(0 == from || 0 != cli_connect(from)); if (!from) { /* local client, allocate a struct Connection */ con = alloc_connection(); assert(0 != con); + assert(!con_magic(con)); + con_magic(con) = CONNECTION_MAGIC; con_fd(con) = -1; /* initialize struct Connection */ + con_freeflag(con) = 0; con_nextnick(con) = CurrentTime - NICK_DELAY; con_nexttarget(con) = CurrentTime - (TARGET_DELAY * (STARTTARGETS - 1)); con_handler(con) = UNREGISTERED_HANDLER; @@ -194,7 +213,9 @@ struct Client* make_client(struct Client *from, int status) con = cli_connect(from); /* use 'from's connection */ assert(0 != con); + assert(con_verify(con)); + cli_magic(cptr) = CLIENT_MAGIC; cli_connect(cptr) = con; /* set the connection and other fields */ cli_status(cptr) = status; cli_hnext(cptr) = cptr; @@ -203,6 +224,17 @@ struct Client* make_client(struct Client *from, int status) return cptr; } +void free_connection(struct Connection* con) +{ + if (!con) + return; + + assert(con_verify(con)); + assert(0 == con_client(con)); + + dealloc_connection(con); /* deallocate the connection */ +} + void free_client(struct Client* cptr) { if (!cptr) @@ -210,17 +242,39 @@ void free_client(struct Client* cptr) /* * forget to remove the client from the hash table? */ + assert(cli_verify(cptr)); assert(cli_hnext(cptr) == cptr); - if (cli_from(cptr) == cptr) /* in other words, we're local */ - dealloc_connection(cli_connect(cptr)); /* deallocate the connection... */ - dealloc_client(cptr); /* deallocate the client */ + Debug((DEBUG_LIST, "Freeing client %s [%p], connection %p", cli_name(cptr), + cptr, cli_connect(cptr))); + + if (cli_auth(cptr)) + destroy_auth_request(cli_auth(cptr), 0); + + if (cli_from(cptr) == cptr) { /* in other words, we're local */ + cli_from(cptr) = 0; + /* timer must be marked as not active */ + if (!cli_freeflag(cptr) && !t_active(&(cli_proc(cptr)))) + dealloc_connection(cli_connect(cptr)); /* connection not open anymore */ + else { + if (-1 < cli_fd(cptr) && cli_freeflag(cptr) & FREEFLAG_SOCKET) + socket_del(&(cli_socket(cptr))); /* queue a socket delete */ + if (cli_freeflag(cptr) & FREEFLAG_TIMER) + timer_del(&(cli_proc(cptr))); /* queue a timer delete */ + } + } + + cli_connect(cptr) = 0; + + dealloc_client(cptr); /* actually destroy the client */ } struct Server *make_server(struct Client *cptr) { struct Server *serv = cli_serv(cptr); + assert(cli_verify(cptr)); + if (!serv) { serv = (struct Server*) MyMalloc(sizeof(struct Server)); @@ -243,11 +297,15 @@ struct Server *make_server(struct Client *cptr) */ void remove_client_from_list(struct Client *cptr) { + assert(cli_verify(cptr)); + assert(con_verify(cli_connect(cptr))); + if (cli_prev(cptr)) cli_next(cli_prev(cptr)) = cli_next(cptr); else { GlobalClientList = cli_next(cptr); - cli_prev(GlobalClientList) = 0; + if (GlobalClientList) + cli_prev(GlobalClientList) = 0; } if (cli_next(cptr)) cli_prev(cli_next(cptr)) = cli_prev(cptr); @@ -287,6 +345,7 @@ void remove_client_from_list(struct Client *cptr) */ void add_client_to_list(struct Client *cptr) { + assert(cli_verify(cptr)); /* * Since we always insert new clients to the top of the list, * this should mean the "me" is the bottom most item in the list. diff --git a/ircd/listener.c b/ircd/listener.c index 75f4add..f780287 100644 --- a/ircd/listener.c +++ b/ircd/listener.c @@ -24,6 +24,7 @@ #include "client.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_events.h" #include "ircd_features.h" #include "ircd_osdep.h" #include "ircd_reply.h" @@ -52,6 +53,8 @@ struct Listener* ListenerPollList = 0; +static void accept_connection(struct Event* ev); + static struct Listener* make_listener(int port, struct in_addr addr) { struct Listener* listener = @@ -222,6 +225,14 @@ static int inetport(struct Listener* listener) if (!os_set_tos(fd,feature_int((listener->server)?FEAT_TOS_SERVER : FEAT_TOS_CLIENT))) { report_error(TOS_ERROR_MSG, get_listener_name(listener), errno); } + + if (!socket_add(&listener->socket, accept_connection, (void*) listener, + SS_LISTENING, 0, fd)) { + /* Error should already have been reported to the logs */ + close(fd); + return 0; + } + listener->fd = fd; return 1; @@ -370,7 +381,7 @@ void close_listener(struct Listener* listener) } if (-1 < listener->fd) close(listener->fd); - free_listener(listener); + socket_del(&listener->socket); } /* @@ -401,77 +412,88 @@ void release_listener(struct Listener* listener) /* * accept_connection - accept a connection on a listener */ -void accept_connection(struct Listener* listener) +static void accept_connection(struct Event* ev) { + struct Listener* listener; struct sockaddr_in addr = { 0 }; unsigned int addrlen = sizeof(struct sockaddr_in); int fd; - assert(0 != listener); + assert(0 != ev_socket(ev)); + assert(0 != s_data(ev_socket(ev))); - listener->last_accept = CurrentTime; - /* - * There may be many reasons for error return, but - * in otherwise correctly working environment the - * probable cause is running out of file descriptors - * (EMFILE, ENFILE or others?). The man pages for - * accept don't seem to list these as possible, - * although it's obvious that it may happen here. - * Thus no specific errors are tested at this - * point, just assume that connections cannot - * be accepted until some old is closed first. - */ - if (-1 == (fd = accept(listener->fd, (struct sockaddr*) &addr, &addrlen))) { - /* Lotsa admins seem to have problems with not giving enough file descriptors - * to their server so we'll add a generic warning mechanism here. If it - * turns out too many messages are generated for meaningless reasons we - * can filter them back. + listener = s_data(ev_socket(ev)); + + if (ev_type(ev) == ET_DESTROY) /* being destroyed */ + free_listener(listener); + else { + assert(ev_type(ev) == ET_ACCEPT); + + listener->last_accept = CurrentTime; + /* + * There may be many reasons for error return, but + * in otherwise correctly working environment the + * probable cause is running out of file descriptors + * (EMFILE, ENFILE or others?). The man pages for + * accept don't seem to list these as possible, + * although it's obvious that it may happen here. + * Thus no specific errors are tested at this + * point, just assume that connections cannot + * be accepted until some old is closed first. */ - sendto_opmask_butone(0, SNO_TCPCOMMON, "Unable to accept connection: %m"); - return; - } - /* - * check for connection limit - */ - if (fd > MAXCLIENTS - 1) { - ++ServerStats->is_ref; - send(fd, "ERROR :All connections in use\r\n", 32, 0); - close(fd); - return; - } - /* - * check to see if listener is shutting down - */ - if (!listener->active) { - ++ServerStats->is_ref; - send(fd, "ERROR :Use another port\r\n", 25, 0); - close(fd); - return; - } - /* - * check to see if connection is allowed for this address mask - */ - if (!connection_allowed((const char*) &addr, (const char*) &listener->mask)) { - ++ServerStats->is_ref; - send(fd, "ERROR :Use another port\r\n", 25, 0); - close(fd); - return; - } + if (-1 == (fd = accept(listener->fd, (struct sockaddr*) &addr, + &addrlen))) { + /* Lotsa admins seem to have problems with not giving enough file + * descriptors to their server so we'll add a generic warning mechanism + * here. If it turns out too many messages are generated for + * meaningless reasons we can filter them back. + */ + sendto_opmask_butone(0, SNO_TCPCOMMON, + "Unable to accept connection: %m"); + return; + } + /* + * check for connection limit + */ + if (fd > MAXCLIENTS - 1) { + ++ServerStats->is_ref; + send(fd, "ERROR :All connections in use\r\n", 32, 0); + close(fd); + return; + } + /* + * check to see if listener is shutting down + */ + if (!listener->active) { + ++ServerStats->is_ref; + send(fd, "ERROR :Use another port\r\n", 25, 0); + close(fd); + return; + } + /* + * check to see if connection is allowed for this address mask + */ + if (!connection_allowed((const char*) &addr, + (const char*) &listener->mask)) { + ++ServerStats->is_ref; + send(fd, "ERROR :Use another port\r\n", 25, 0); + close(fd); + return; + } #if 0 - /* - * check conf for ip address access - */ - if (!conf_connect_allowed(addr.sin_addr)) { - ++ServerStats->is_ref; - send(fd, "ERROR :Not authorized\r\n", 23, 0); - close(fd); - return; - } + /* + * check conf for ip address access + */ + if (!conf_connect_allowed(addr.sin_addr)) { + ++ServerStats->is_ref; + send(fd, "ERROR :Not authorized\r\n", 23, 0); + close(fd); + return; + } #endif - ++ServerStats->is_ac; - nextping = CurrentTime; + ++ServerStats->is_ac; +/* nextping = CurrentTime; */ - add_connection(listener, fd); + add_connection(listener, fd); + } } - - diff --git a/ircd/m_list.c b/ircd/m_list.c index eaf9707..e4c3a5d 100644 --- a/ircd/m_list.c +++ b/ircd/m_list.c @@ -102,6 +102,7 @@ #include "msg.h" #include "numeric.h" #include "numnicks.h" +#include "s_bsd.h" #include "send.h" #include @@ -287,6 +288,7 @@ int m_list(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) MyFree(cli_listing(sptr)); cli_listing(sptr) = 0; send_reply(sptr, RPL_LISTEND); + update_write(sptr); if (parc < 2) return 0; /* Let LIST abort a listing. */ } diff --git a/ircd/m_stats.c b/ircd/m_stats.c index e212494..d0bba30 100644 --- a/ircd/m_stats.c +++ b/ircd/m_stats.c @@ -94,6 +94,7 @@ #include "ircd.h" #include "ircd_alloc.h" #include "ircd_chattr.h" +#include "ircd_events.h" #include "ircd_features.h" #include "ircd_policy.h" #include "ircd_reply.h" @@ -263,6 +264,15 @@ int m_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) #endif break; + case 'E': + case 'e': /* report engine name */ +#ifdef HEAD_IN_SAND_STATS_E + return m_not_oper(sptr,cptr,parc,parv); +#else + send_reply(sptr, RPL_STATSENGINE, engine_name()); +#endif + break; + case 'G': case 'g': /* send glines */ #ifdef HEAD_IN_SAND_STATS_G @@ -590,6 +600,10 @@ int ms_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) case 'c': report_configured_links(sptr, CONF_SERVER); break; + case 'E': + case 'e': /* report engine name */ + send_reply(sptr, RPL_STATSENGINE, engine_name()); + break; case 'G': case 'g': /* send glines */ gline_stats(sptr); @@ -809,6 +823,10 @@ int mo_stats(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) case 'c': report_configured_links(sptr, CONF_SERVER); break; + case 'E': + case 'e': /* report engine name */ + send_reply(sptr, RPL_STATSENGINE, engine_name()); + break; case 'G': case 'g': /* send glines */ gline_stats(sptr); diff --git a/ircd/os_bsd.c b/ircd/os_bsd.c index f26cb73..2f3bd66 100644 --- a/ircd/os_bsd.c +++ b/ircd/os_bsd.c @@ -359,13 +359,11 @@ IOResult os_sendv_nonb(int fd, struct MsgQ* buf, unsigned int* count_in, return IO_FAILURE; } -int os_connect_nonb(int fd, const struct sockaddr_in* sin) +IOResult os_connect_nonb(int fd, const struct sockaddr_in* sin) { - if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) { - if (errno != EINPROGRESS) - return 0; - } - return 1; + if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) + return (errno == EINPROGRESS) ? IO_BLOCKED : IO_FAILURE; + return IO_SUCCESS; } int os_get_sockname(int fd, struct sockaddr_in* sin_out) diff --git a/ircd/os_generic.c b/ircd/os_generic.c index 73c2f79..b996ecd 100644 --- a/ircd/os_generic.c +++ b/ircd/os_generic.c @@ -220,6 +220,16 @@ int os_set_sockbufs(int fd, unsigned int size) (const char*) &opt, sizeof(opt))); } +int os_set_tos(int fd,int tos) +{ +#if defined(IP_TOS) && defined(IPPROTO_IP) + unsigned int opt = tos; + return (0 == setsockopt(fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt))); +#else + return 1; +#endif +} + int os_disable_options(int fd) { #if defined(IP_OPTIONS) && defined(IPPROTO_IP) @@ -355,13 +365,11 @@ IOResult os_sendv_nonb(int fd, struct MsgQ* buf, unsigned int* count_in, return IO_FAILURE; } -int os_connect_nonb(int fd, const struct sockaddr_in* sin) +IOResult os_connect_nonb(int fd, const struct sockaddr_in* sin) { - if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) { - if (errno != EINPROGRESS) - return 0; - } - return 1; + if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) + return (errno == EINPROGRESS) ? IO_BLOCKED : IO_FAILURE; + return IO_SUCCESS; } int os_get_sockname(int fd, struct sockaddr_in* sin_out) diff --git a/ircd/os_linux.c b/ircd/os_linux.c index 7e37129..9ea434b 100644 --- a/ircd/os_linux.c +++ b/ircd/os_linux.c @@ -303,13 +303,11 @@ IOResult os_sendv_nonb(int fd, struct MsgQ* buf, unsigned int* count_in, } -int os_connect_nonb(int fd, const struct sockaddr_in* sin) +IOResult os_connect_nonb(int fd, const struct sockaddr_in* sin) { - if (connect(fd, (const struct sockaddr*) sin, sizeof(struct sockaddr_in))) { - if (errno != EINPROGRESS) - return 0; - } - return 1; + if (connect(fd, (const struct sockaddr*) sin, sizeof(struct sockaddr_in))) + return (errno == EINPROGRESS) ? IO_BLOCKED : IO_FAILURE; + return IO_SUCCESS; } int os_get_sockname(int fd, struct sockaddr_in* sin_out) diff --git a/ircd/os_openbsd.c b/ircd/os_openbsd.c index 805d87f..bf02113 100644 --- a/ircd/os_openbsd.c +++ b/ircd/os_openbsd.c @@ -367,13 +367,11 @@ IOResult os_sendv_nonb(int fd, struct MsgQ* buf, unsigned int* count_in, return IO_FAILURE; } -int os_connect_nonb(int fd, const struct sockaddr_in* sin) +IOResult os_connect_nonb(int fd, const struct sockaddr_in* sin) { - if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) { - if (errno != EINPROGRESS) - return 0; - } - return 1; + if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) + return (errno == EINPROGRESS) ? IO_BLOCKED : IO_FAILURE; + return IO_SUCCESS; } int os_get_sockname(int fd, struct sockaddr_in* sin_out) diff --git a/ircd/os_solaris.c b/ircd/os_solaris.c index e4ba40f..c94fd38 100644 --- a/ircd/os_solaris.c +++ b/ircd/os_solaris.c @@ -21,8 +21,6 @@ */ #include "config.h" -#define _XOPEN_SOURCE /* make limits.h #define IOV_MAX */ - #include "ircd_osdep.h" #include "msgq.h" @@ -32,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -135,6 +134,12 @@ int os_set_sockbufs(int fd, unsigned int size) (const char*) &opt, sizeof(opt))); } +int os_set_tos(int fd,int tos) +{ + unsigned int opt = tos; + return (0 == setsockopt(fd, IPPROTO_IP, IP_TOS, &opt, sizeof(opt))); +} + int os_disable_options(int fd) { return (0 == setsockopt(fd, IPPROTO_IP, IP_OPTIONS, NULL, 0)); @@ -249,13 +254,11 @@ IOResult os_sendv_nonb(int fd, struct MsgQ* buf, unsigned int* count_in, return IO_FAILURE; } -int os_connect_nonb(int fd, const struct sockaddr_in* sin) +IOResult os_connect_nonb(int fd, const struct sockaddr_in* sin) { - if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) { - if (errno != EINPROGRESS) - return 0; - } - return 1; + if (connect(fd, (struct sockaddr*) sin, sizeof(struct sockaddr_in))) + return (errno == EINPROGRESS) ? IO_BLOCKED : IO_FAILURE; + return IO_SUCCESS; } int os_get_sockname(int fd, struct sockaddr_in* sin_out) diff --git a/ircd/res.c b/ircd/res.c index d9eb035..3ded4cc 100644 --- a/ircd/res.c +++ b/ircd/res.c @@ -16,6 +16,7 @@ #include "client.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_events.h" #include "ircd_log.h" #include "ircd_osdep.h" #include "ircd_reply.h" @@ -200,6 +201,10 @@ struct CacheTable { int ResolverFileDescriptor = -1; /* GLOBAL - used in s_bsd.c */ +static struct Socket resSock; /* Socket describing resolver */ +static struct Timer resExpireDNS; /* Timer for DNS expiration */ +static struct Timer resExpireCache; /* Timer for cache expiration */ + static time_t nextDNSCheck = 0; static time_t nextCacheExpire = 1; @@ -222,6 +227,8 @@ static struct ResRequest* requestListTail; /* tail of resolver request list */ static void add_request(struct ResRequest* request); static void rem_request(struct ResRequest* request); static struct ResRequest* make_request(const struct DNSQuery* query); +static time_t timeout_query_list(time_t now); +static time_t expire_cache(time_t now); static void rem_cache(struct CacheEntry*); static void do_query_name(const struct DNSQuery* query, const char* name, @@ -298,6 +305,14 @@ res_ourserver(const struct __res_state* statp, const struct sockaddr_in* inp) return (0); } +/* Socket callback for resolver */ +static void res_callback(struct Event* ev) +{ + assert(ev_type(ev) == ET_READ); + + resolver_read(); +} + /* * start_resolver - do everything we need to read the resolv.conf file * and initialize the resolver file descriptor if needed @@ -340,9 +355,33 @@ static void start_resolver(void) if (!os_set_nonblocking(ResolverFileDescriptor)) report_error("Resolver: error setting non-blocking for %s: %s", cli_name(&me), errno); + if (!socket_add(&resSock, res_callback, 0, SS_DATAGRAM, + SOCK_EVENT_READABLE, ResolverFileDescriptor)) + report_error("Resolver: unable to queue resolver file descriptor for %s", + cli_name(&me), ENFILE); } } +/* Call the query timeout function */ +static void expire_DNS_callback(struct Event* ev) +{ + time_t next; + + next = timeout_query_list(CurrentTime); + + timer_add(&resExpireDNS, expire_DNS_callback, 0, TT_ABSOLUTE, next); +} + +/* Call the cache expire function */ +static void expire_cache_callback(struct Event* ev) +{ + time_t next; + + next = expire_cache(CurrentTime); + + timer_add(&resExpireCache, expire_cache_callback, 0, TT_ABSOLUTE, next); +} + /* * init_resolver - initialize resolver and resolver library */ @@ -358,6 +397,10 @@ int init_resolver(void) requestListHead = requestListTail = 0; + /* initiate the resolver timers */ + timer_add(&resExpireDNS, expire_DNS_callback, 0, TT_RELATIVE, 1); + timer_add(&resExpireCache, expire_cache_callback, 0, TT_RELATIVE, 1); + errno = h_errno = 0; start_resolver(); diff --git a/ircd/s_auth.c b/ircd/s_auth.c index 01c207a..5ac1702 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -35,6 +35,7 @@ #include "ircd.h" #include "ircd_alloc.h" #include "ircd_chattr.h" +#include "ircd_events.h" #include "ircd_features.h" #include "ircd_log.h" #include "ircd_osdep.h" @@ -102,6 +103,118 @@ static struct AuthRequest* AuthIncompleteList = 0; enum { AUTH_TIMEOUT = 60 }; +static void release_auth_client(struct Client* client); +static void unlink_auth_request(struct AuthRequest* request, + struct AuthRequest** list); +void free_auth_request(struct AuthRequest* auth); + +/* + * auth_timeout - timeout a given auth request + */ +static void auth_timeout_callback(struct Event* ev) +{ + struct AuthRequest* auth; + + assert(0 != ev_timer(ev)); + assert(0 != t_data(ev_timer(ev))); + + auth = t_data(ev_timer(ev)); + + if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ + auth->flags &= ~AM_TIMEOUT; + + if (!(auth->flags & AM_FREE_MASK)) { + Debug((DEBUG_LIST, "Freeing auth from timeout callback; %p [%p]", auth, + ev_timer(ev))); + MyFree(auth); /* done with it, finally */ + } + } else { + assert(ev_type(ev) == ET_EXPIRE); + + destroy_auth_request(auth, 1); + } +} + +/* + * auth_sock_callback - called when an event occurs on the socket + */ +static void auth_sock_callback(struct Event* ev) +{ + struct AuthRequest* auth; + + assert(0 != ev_socket(ev)); + assert(0 != s_data(ev_socket(ev))); + + auth = s_data(ev_socket(ev)); + + switch (ev_type(ev)) { + case ET_DESTROY: /* being destroyed */ + auth->flags &= ~AM_SOCKET; + + if (!(auth->flags & AM_FREE_MASK)) { + Debug((DEBUG_LIST, "Freeing auth from sock callback; %p [%p]", auth, + ev_socket(ev))); + MyFree(auth); /* done with it finally */ + } + break; + + case ET_CONNECT: /* socket connection completed */ + Debug((DEBUG_LIST, "Connection completed for auth %p [%p]; sending query", + auth, ev_socket(ev))); + socket_state(&auth->socket, SS_CONNECTED); + send_auth_query(auth); + break; + + case ET_READ: /* socket is readable */ + case ET_EOF: /* end of file on socket */ + case ET_ERROR: /* error on socket */ + Debug((DEBUG_LIST, "Auth socket %p [%p] readable", auth, ev_socket(ev))); + read_auth_reply(auth); + break; + + default: +#ifndef NDEBUG + abort(); /* unrecognized event */ +#endif + break; + } +} + +/* + * destroy_auth_request - stop an auth request completely + */ +void destroy_auth_request(struct AuthRequest* auth, int send_reports) +{ + struct AuthRequest** authList; + + if (IsDoingAuth(auth)) { + authList = &AuthPollList; + if (-1 < auth->fd) { + close(auth->fd); + auth->fd = -1; + socket_del(&auth->socket); + } + + if (send_reports && IsUserPort(auth->client)) + sendheader(auth->client, REPORT_FAIL_ID); + } else + authList = &AuthIncompleteList; + + if (IsDNSPending(auth)) { + delete_resolver_queries(auth); + if (send_reports && IsUserPort(auth->client)) + sendheader(auth->client, REPORT_FAIL_DNS); + } + + if (send_reports) + log_write(LS_RESOLVER, L_INFO, 0, "DNS/AUTH timeout %s", + get_client_name(auth->client, HIDE_IP)); + + release_auth_client(auth->client); + unlink_auth_request(auth, authList); + free_auth_request(auth); +} + /* * make_auth_request - allocate a new auth request */ @@ -111,9 +224,12 @@ static struct AuthRequest* make_auth_request(struct Client* client) (struct AuthRequest*) MyMalloc(sizeof(struct AuthRequest)); assert(0 != auth); memset(auth, 0, sizeof(struct AuthRequest)); + auth->flags = AM_TIMEOUT; auth->fd = -1; auth->client = client; - auth->timeout = CurrentTime + AUTH_TIMEOUT; + cli_auth(client) = auth; + timer_add(&auth->timeout, auth_timeout_callback, (void*) auth, TT_RELATIVE, + AUTH_TIMEOUT); return auth; } @@ -122,9 +238,13 @@ static struct AuthRequest* make_auth_request(struct Client* client) */ void free_auth_request(struct AuthRequest* auth) { - if (-1 < auth->fd) + if (-1 < auth->fd) { close(auth->fd); - MyFree(auth); + Debug((DEBUG_LIST, "Deleting auth socket for %p", auth->client)); + socket_del(&auth->socket); + } + Debug((DEBUG_LIST, "Deleting auth timeout timer for %p", auth->client)); + timer_del(&auth->timeout); } /* @@ -162,12 +282,14 @@ static void link_auth_request(struct AuthRequest* request, static void release_auth_client(struct Client* client) { assert(0 != client); + cli_auth(client) = 0; cli_lasttime(client) = cli_since(client) = CurrentTime; if (cli_fd(client) > HighestFd) HighestFd = cli_fd(client); LocalClientArray[cli_fd(client)] = client; add_client_to_list(client); + socket_events(&(cli_socket(client)), SOCK_ACTION_SET | SOCK_EVENT_READABLE); Debug((DEBUG_INFO, "Auth: release_auth_client %s@%s[%s]", cli_username(client), cli_sockhost(client), cli_sock_ip(client))); } @@ -263,6 +385,7 @@ static void auth_error(struct AuthRequest* auth, int kill) assert(0 != auth); close(auth->fd); auth->fd = -1; + socket_del(&auth->socket); if (IsUserPort(auth->client)) sendheader(auth->client, REPORT_FAIL_ID); @@ -301,6 +424,7 @@ static int start_auth_query(struct AuthRequest* auth) struct sockaddr_in remote_addr; struct sockaddr_in local_addr; int fd; + IOResult result; assert(0 != auth); assert(0 != auth->client); @@ -353,7 +477,10 @@ static int start_auth_query(struct AuthRequest* auth) remote_addr.sin_port = htons(113); remote_addr.sin_family = AF_INET; - if (!os_connect_nonb(fd, &remote_addr)) { + if ((result = os_connect_nonb(fd, &remote_addr)) == IO_FAILURE || + !socket_add(&auth->socket, auth_sock_callback, (void*) auth, + result == IO_SUCCESS ? SS_CONNECTED : SS_CONNECTING, + SOCK_EVENT_READABLE, fd)) { ServerStats->is_abad++; /* * No error report from this... @@ -364,9 +491,13 @@ static int start_auth_query(struct AuthRequest* auth) return 0; } + auth->flags |= AM_SOCKET; auth->fd = fd; SetAuthConnect(auth); + if (result == IO_SUCCESS) + send_auth_query(auth); /* this does a SetAuthPending(auth) for us */ + return 1; } @@ -524,6 +655,8 @@ void start_auth(struct Client* client) auth = make_auth_request(client); assert(0 != auth); + Debug((DEBUG_INFO, "Beginning auth request on client %p", client)); + if (!feature_bool(FEAT_NODNS)) { if (LOOPBACK == inet_netof(cli_ip(client))) strcpy(cli_sockhost(client), cli_name(&me)); @@ -545,69 +678,28 @@ void start_auth(struct Client* client) HOSTLEN); if (IsUserPort(auth->client)) sendheader(client, REPORT_FIN_DNSC); + Debug((DEBUG_LIST, "DNS entry for %p was cached", auth->client)); } else SetDNSPending(auth); } } - if (start_auth_query(auth)) + if (start_auth_query(auth)) { + Debug((DEBUG_LIST, "identd query for %p initiated successfully", + auth->client)); link_auth_request(auth, &AuthPollList); - else if (IsDNSPending(auth)) + } else if (IsDNSPending(auth)) { + Debug((DEBUG_LIST, "identd query for %p not initiated successfully; " + "waiting on DNS", auth->client)); link_auth_request(auth, &AuthIncompleteList); - else { + } else { + Debug((DEBUG_LIST, "identd query for %p not initiated successfully; " + "no DNS pending; releasing immediately", auth->client)); free_auth_request(auth); release_auth_client(client); } } -/* - * timeout_auth_queries - timeout resolver and identd requests - * allow clients through if requests failed - */ -void timeout_auth_queries(time_t now) -{ - struct AuthRequest* auth; - struct AuthRequest* auth_next = 0; - - for (auth = AuthPollList; auth; auth = auth_next) { - auth_next = auth->next; - if (auth->timeout < CurrentTime) { - if (-1 < auth->fd) { - close(auth->fd); - auth->fd = -1; - } - - if (IsUserPort(auth->client)) - sendheader(auth->client, REPORT_FAIL_ID); - if (IsDNSPending(auth)) { - delete_resolver_queries(auth); - if (IsUserPort(auth->client)) - sendheader(auth->client, REPORT_FAIL_DNS); - } - log_write(LS_RESOLVER, L_INFO, 0, "DNS/AUTH timeout %s", - get_client_name(auth->client, HIDE_IP)); - - release_auth_client(auth->client); - unlink_auth_request(auth, &AuthPollList); - free_auth_request(auth); - } - } - for (auth = AuthIncompleteList; auth; auth = auth_next) { - auth_next = auth->next; - if (auth->timeout < CurrentTime) { - delete_resolver_queries(auth); - if (IsUserPort(auth->client)) - sendheader(auth->client, REPORT_FAIL_DNS); - log_write(LS_RESOLVER, L_INFO, 0, "DNS timeout %s", - get_client_name(auth->client, HIDE_IP)); - - release_auth_client(auth->client); - unlink_auth_request(auth, &AuthIncompleteList); - free_auth_request(auth); - } - } -} - /* * send_auth_query - send the ident server a query giving "theirport , ourport" * The write is only attempted *once* so it is deemed to be a fail if the @@ -660,14 +752,19 @@ void read_auth_reply(struct AuthRequest* auth) assert(0 != auth); assert(0 != auth->client); + assert(auth = cli_auth(auth->client)); if (IO_SUCCESS == os_recv_nonb(auth->fd, buf, BUFSIZE, &len)) { buf[len] = '\0'; + Debug((DEBUG_LIST, "Auth %p [%p] reply: %s", auth, &auth->socket, buf)); username = check_ident_reply(buf); + Debug((DEBUG_LIST, "Username: %s", username)); } close(auth->fd); auth->fd = -1; + Debug((DEBUG_LIST, "Deleting auth [%p] socket %p", auth, &auth->socket)); + socket_del(&auth->socket); ClearAuth(auth); if (!EmptyString(username)) { diff --git a/ircd/s_bsd.c b/ircd/s_bsd.c index 020336e..9d15648 100644 --- a/ircd/s_bsd.c +++ b/ircd/s_bsd.c @@ -96,6 +96,7 @@ const char* const LISTEN_ERROR_MSG = "listen error for %s: %s"; const char* const NONB_ERROR_MSG = "error setting non-blocking for %s: %s"; const char* const PEERNAME_ERROR_MSG = "getpeername failed for %s: %s"; const char* const POLL_ERROR_MSG = "poll error for %s: %s"; +const char* const REGISTER_ERROR_MSG = "registering %s: %s"; const char* const REUSEADDR_ERROR_MSG = "error setting SO_REUSEADDR for %s: %s"; const char* const SELECT_ERROR_MSG = "select error for %s: %s"; const char* const SETBUFS_ERROR_MSG = "error setting buffer size for %s: %s"; @@ -103,6 +104,9 @@ const char* const SOCKET_ERROR_MSG = "error creating socket for %s: %s"; const char* const TOS_ERROR_MSG = "error setting TOS for %s: %s"; +static void client_sock_callback(struct Event* ev); +static void client_timer_callback(struct Event* ev); + #if !defined(USE_POLL) #if FD_SETSIZE < (MAXCONNECTIONS + 4) /* @@ -226,6 +230,7 @@ int init_connection_limits(void) static int connect_inet(struct ConfItem* aconf, struct Client* cptr) { static struct sockaddr_in sin; + IOResult result; assert(0 != aconf); assert(0 != cptr); /* @@ -264,6 +269,8 @@ static int connect_inet(struct ConfItem* aconf, struct Client* cptr) bind(cli_fd(cptr), (struct sockaddr*) &VirtualHost, sizeof(VirtualHost))) { report_error(BIND_ERROR_MSG, cli_name(cptr), errno); + close(cli_fd(cptr)); + cli_fd(cptr) = -1; return 0; } @@ -283,6 +290,8 @@ static int connect_inet(struct ConfItem* aconf, struct Client* cptr) if (!os_set_sockbufs(cli_fd(cptr), SERVER_TCP_WINDOW)) { cli_error(cptr) = errno; report_error(SETBUFS_ERROR_MSG, cli_name(cptr), errno); + close(cli_fd(cptr)); + cli_fd(cptr) = -1; return 0; } /* @@ -291,13 +300,28 @@ static int connect_inet(struct ConfItem* aconf, struct Client* cptr) if (!os_set_nonblocking(cli_fd(cptr))) { cli_error(cptr) = errno; report_error(NONB_ERROR_MSG, cli_name(cptr), errno); + close(cli_fd(cptr)); + cli_fd(cptr) = -1; return 0; } - if (!os_connect_nonb(cli_fd(cptr), &sin)) { + if ((result = os_connect_nonb(cli_fd(cptr), &sin)) == IO_FAILURE) { cli_error(cptr) = errno; report_error(CONNECT_ERROR_MSG, cli_name(cptr), errno); + close(cli_fd(cptr)); + cli_fd(cptr) = -1; return 0; } + if (!socket_add(&(cli_socket(cptr)), client_sock_callback, + (void*) cli_connect(cptr), + (result == IO_SUCCESS) ? SS_CONNECTED : SS_CONNECTING, + SOCK_EVENT_READABLE, cli_fd(cptr))) { + cli_error(cptr) = ENFILE; + report_error(REGISTER_ERROR_MSG, cli_name(cptr), ENFILE); + close(cli_fd(cptr)); + cli_fd(cptr) = -1; + return 0; + } + cli_freeflag(cptr) |= FREEFLAG_SOCKET; return 1; } @@ -409,6 +433,8 @@ static int completed_connection(struct Client* cptr) sendto_opmask_butone(0, SNO_OLDSNO, "Lost Server Line for %s", cli_name(cptr)); return 0; } + if (s_state(&(cli_socket(cptr))) == SS_CONNECTING) + socket_state(&(cli_socket(cptr)), SS_CONNECTED); if (!EmptyString(aconf->passwd)) sendrawto_one(cptr, MSG_PASS " :%s", aconf->passwd); @@ -481,8 +507,8 @@ void close_connection(struct Client *cptr) aconf->hold += ((aconf->hold - cli_since(cptr) > feature_int(FEAT_HANGONGOODLINK)) ? feature_int(FEAT_HANGONRETRYDELAY) : ConfConFreq(aconf)); - if (nextconnect > aconf->hold) - nextconnect = aconf->hold; +/* if (nextconnect > aconf->hold) */ +/* nextconnect = aconf->hold; */ } } else if (IsUser(cptr)) { @@ -508,6 +534,7 @@ void close_connection(struct Client *cptr) flush_connections(cptr); LocalClientArray[cli_fd(cptr)] = 0; close(cli_fd(cptr)); + socket_del(&(cli_socket(cptr))); /* queue a socket delete */ cli_fd(cptr) = -1; } cli_flags(cptr) |= FLAGS_DEADSOCKET; @@ -564,6 +591,8 @@ void add_connection(struct Listener* listener, int fd) { const char* const throttle_message = "ERROR :Your host is trying to (re)connect too fast -- throttled\r\n"; /* 12345678901234567890123456789012345679012345678901234567890123456 */ + const char* const register_message = + "ERROR :Unable to complete your registration\r\n"; assert(0 != listener); @@ -607,6 +636,15 @@ void add_connection(struct Listener* listener, int fd) { cli_nexttarget(new_client) = next_target; cli_fd(new_client) = fd; + if (!socket_add(&(cli_socket(new_client)), client_sock_callback, + (void*) cli_connect(new_client), SS_CONNECTED, 0, fd)) { + ++ServerStats->is_ref; + write(fd, register_message, strlen(register_message)); + close(fd); + cli_fd(new_client) = -1; + return; + } + cli_freeflag(new_client) |= FREEFLAG_SOCKET; cli_listener(new_client) = listener; ++listener->ref_count; @@ -615,6 +653,23 @@ void add_connection(struct Listener* listener, int fd) { start_auth(new_client); } +/* + * update_write + * + * Determines whether to tell the events engine we're interested in + * writable events + */ +void update_write(struct Client* cptr) +{ + /* If there are messages that need to be sent along, or if the client + * is in the middle of a /list, then we need to tell the engine that + * we're interested in writable events--otherwise, we need to drop + * that interest. + */ + socket_events(&(cli_socket(cptr)), + ((MsgQLength(&cli_sendQ(cptr)) || cli_listing(cptr)) ? + SOCK_ACTION_ADD : SOCK_ACTION_DEL) | SOCK_EVENT_WRITABLE); +} /* * read_packet @@ -703,580 +758,19 @@ static int read_packet(struct Client *cptr, int socket_ready) else if (CPTR_KILLED == client_dopacket(cptr, dolen)) return CPTR_KILLED; } - } - return 1; -} -static int on_write_unblocked(struct Client* cptr) -{ - /* - * ...room for writing, empty some queue then... - */ - cli_flags(cptr) &= ~FLAGS_BLOCKED; - if (IsConnecting(cptr)) { - if (!completed_connection(cptr)) - return 0; - } - else if (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048) - list_next_channels(cptr, 64); - send_queued(cptr); - return 1; -} - -/* - * Select / Poll Read Algorithm for ircd - * - * We need to check the file descriptors for all the different types - * of things that use them, so check for reads on everything but connects - * and writes on connects and descriptors that are blocked - * - * for each (client in local) { - * if (not connecting) - * check for read; - * if (connecting or blocked) - * check for write; - * } - * wait for activity; - * - * for each (client in local) { - * if (there are descriptors to check) { - * if (write activity) - * send data; - * if (read activity) - * read data; - * } - * process data read; - * } - * Note we must always process data read whether or not there has been - * read activity or file descriptors set, since data is buffered by the client. - */ - - -#ifdef USE_POLL - -/* - * poll macros - */ -#if defined(POLLMSG) && defined(POLLIN) && defined(POLLRDNORM) -# define POLLREADFLAGS (POLLMSG|POLLIN|POLLRDNORM) -#else -# if defined(POLLIN) && defined(POLLRDNORM) -# define POLLREADFLAGS (POLLIN|POLLRDNORM) -# else -# if defined(POLLIN) -# define POLLREADFLAGS POLLIN -# else -# if defined(POLLRDNORM) -# define POLLREADFLAGS POLLRDNORM -# endif -# endif -# endif -#endif - -#if defined(POLLOUT) && defined(POLLWRNORM) -#define POLLWRITEFLAGS (POLLOUT|POLLWRNORM) -#else -# if defined(POLLOUT) -# define POLLWRITEFLAGS POLLOUT -# else -# if defined(POLLWRNORM) -# define POLLWRITEFLAGS POLLWRNORM -# endif -# endif -#endif - -#ifdef POLLHUP -#define POLLERRORS (POLLHUP|POLLERR) -#else -#define POLLERRORS POLLERR -#endif - -/* - * NOTE: pfd and pfd_count are local variable names in read_message - */ -#define PFD_SETR(xfd) \ - do { CHECK_ADD_PFD(xfd) pfd->events |= POLLREADFLAGS; } while(0) -#define PFD_SETW(xfd) \ - do { CHECK_ADD_PFD(xfd) pfd->events |= POLLWRITEFLAGS; } while(0) - -#define CHECK_ADD_PFD(xfd) \ - if (pfd->fd != xfd) { \ - pfd = &poll_fds[pfd_count++]; \ - poll_fds[pfd_count].fd = -1; \ - pfd->fd = xfd; \ - pfd->events = 0; \ - } - -/* - * Check all connections for new connections and input data that is to be - * processed. Also check for connections with data queued and whether we can - * write it out. - * - * Don't ever use ZERO for `delay', unless you mean to poll and then - * you have to have sleep/wait somewhere else in the code.--msa - */ -int read_message(time_t delay) -{ - struct pollfd poll_fds[MAXCONNECTIONS + 1]; - struct Client* cptr; - struct Listener* listener = 0; - struct AuthRequest* auth = 0; - struct AuthRequest* auth_next = 0; - struct UPing* uping = 0; - struct UPing* uping_next = 0; - time_t delay2 = delay; - int nfds; - int length; - int i; - int res = 0; - int pfd_count; - struct pollfd* pfd; - struct pollfd* res_pfd; - struct pollfd* uping_pfd; - int read_ready; - int write_ready; - - unsigned int timeout; - - for ( ; ; ) { - pfd_count = 0; - pfd = poll_fds; - res_pfd = 0; - uping_pfd = 0; - pfd->fd = -1; - - if (-1 < ResolverFileDescriptor) { - PFD_SETR(ResolverFileDescriptor); - res_pfd = pfd; - } - if (-1 < UPingFileDescriptor) { - PFD_SETR(UPingFileDescriptor); - uping_pfd = pfd; - } - /* - * add uping descriptors - */ - for (uping = uping_begin(); uping; uping = uping_next) { - uping_next = uping->next; - if (uping->active) { - delay2 = 1; - if (uping->lastsent && CurrentTime > uping->timeout) { - uping_end(uping); - continue; - } - uping->index = pfd_count; - PFD_SETR(uping->fd); - } - } - /* - * add auth file descriptors - */ - for (auth = AuthPollList; auth; auth = auth->next) { - assert(-1 < auth->fd); - auth->index = pfd_count; - if (IsAuthConnect(auth)) - PFD_SETW(auth->fd); - else - PFD_SETR(auth->fd); - } - /* - * add listener file descriptors - */ - for (listener = ListenerPollList; listener; listener = listener->next) { - assert(-1 < listener->fd); - /* - * pfd_count is incremented by PFD_SETR so we need to save the - * index first - */ - listener->index = pfd_count; - PFD_SETR(listener->fd); - } - - for (i = HighestFd; -1 < i; --i) { - if ((cptr = LocalClientArray[i])) { - - if (DBufLength(&(cli_recvQ(cptr)))) - delay2 = 1; - if (DBufLength(&(cli_recvQ(cptr))) < 4088 || IsServer(cptr)) { - PFD_SETR(i); - } - if (MsgQLength(&(cli_sendQ(cptr))) || IsConnecting(cptr) || - (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048)) { - PFD_SETW(i); - } - } - } - - Debug((DEBUG_INFO, "poll: %d %d", delay, delay2)); - - timeout = (IRCD_MIN(delay2, delay)) * 1000; - - nfds = poll(poll_fds, pfd_count, timeout); - - CurrentTime = time(0); - if (-1 < nfds) - break; - - if (EINTR == errno) - return -1; - report_error(POLL_ERROR_MSG, cli_name(&me), errno); - ++res; - if (res > 5) - server_restart("too many poll errors"); - sleep(1); - CurrentTime = time(0); - } - - if (uping_pfd && (uping_pfd->revents & (POLLREADFLAGS | POLLERRORS))) { - uping_echo(); - --nfds; - } - /* - * check uping replies - */ - for (uping = uping_begin(); uping; uping = uping_next) { - uping_next = uping->next; - if (uping->active) { - assert(-1 < uping->index); - if (poll_fds[uping->index].revents) { - uping_read(uping); - if (0 == --nfds) - break; - } - else if (CurrentTime > uping->lastsent) { - uping->lastsent = CurrentTime; - uping_send(uping); - } - } - } - - if (res_pfd && (res_pfd->revents & (POLLREADFLAGS | POLLERRORS))) { - resolver_read(); - --nfds; - } - /* - * check auth queries - */ - for (auth = AuthPollList; auth; auth = auth_next) { - auth_next = auth->next; - i = auth->index; - /* - * check for any event, we only ask for one at a time - */ - if (poll_fds[i].revents) { - if (IsAuthConnect(auth)) - send_auth_query(auth); - else - read_auth_reply(auth); - if (0 == --nfds) - break; - } - } - /* - * check listeners - */ - for (listener = ListenerPollList; listener; listener = listener->next) { - i = listener->index; - if (poll_fds[i].revents) { - accept_connection(listener); - if (0 == --nfds) - break; + /* If there's still data to process, wait 2 seconds first */ + if (DBufLength(&(cli_recvQ(cptr))) && !NoNewLine(cptr) && + !(cli_freeflag(cptr) & FREEFLAG_TIMER)) { + Debug((DEBUG_LIST, "Adding client process timer for %C", cptr)); + cli_freeflag(cptr) |= FREEFLAG_TIMER; + timer_add(&(cli_proc(cptr)), client_timer_callback, cli_connect(cptr), + TT_RELATIVE, 2); } } - /* - * i contains the next non-auth/non-listener index, since we put the - * resolver, auth and listener, file descriptors in poll_fds first, - * the very next one should be the start of the clients - */ - pfd = &poll_fds[++i]; - - for ( ; (i < pfd_count); ++i, ++pfd) { - if (!(cptr = LocalClientArray[pfd->fd])) - continue; - read_ready = write_ready = 0; - - if (0 < nfds && pfd->revents) { - --nfds; - - read_ready = pfd->revents & POLLREADFLAGS; - write_ready = pfd->revents & POLLWRITEFLAGS; - - if (pfd->revents & POLLERRORS) { - if (pfd->events & POLLREADFLAGS) - ++read_ready; - if (pfd->events & POLLWRITEFLAGS) - ++write_ready; - } - } - if (write_ready) { - if (!on_write_unblocked(cptr) || IsDead(cptr)) { - const char* msg = (cli_error(cptr)) ? strerror(cli_error(cptr)) : cli_info(cptr); - if (!msg) - msg = "Unknown error"; - exit_client(cptr, cptr, &me, msg); - continue; - } - } - length = 1; /* for fall through case */ - if ((!NoNewLine(cptr) || read_ready) && !IsDead(cptr)) { - if (CPTR_KILLED == (length = read_packet(cptr, read_ready))) - continue; - } -#if 0 - /* Bullshit, why would we want to flush sockets while using non-blocking? - * This uses > 4% cpu! --Run */ - if (length > 0) - flush_connections(poll_cptr[i]); -#endif - if (IsDead(cptr)) { - const char* msg = (cli_error(cptr)) ? strerror(cli_error(cptr)) : cli_info(cptr); - if (!msg) - msg = "Unknown error"; - exit_client(cptr, cptr, &me, (char*) msg); - continue; - } - if (length > 0) - continue; - cli_flags(cptr) |= FLAGS_DEADSOCKET; - /* - * ...hmm, with non-blocking sockets we might get - * here from quite valid reasons, although.. why - * would select report "data available" when there - * wasn't... So, this must be an error anyway... --msa - * actually, EOF occurs when read() returns 0 and - * in due course, select() returns that fd as ready - * for reading even though it ends up being an EOF. -avalon - */ - Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d %d", pfd->fd, errno, length)); - - if ((IsServer(cptr) || IsHandshake(cptr)) && cli_error(cptr) == 0 && length == 0) - exit_client_msg(cptr, cptr, &me, "Server %s closed the connection (%s)", - cli_name(cptr), cli_serv(cptr)->last_error_msg); - else { - const char* msg = (cli_error(cptr)) ? strerror(cli_error(cptr)) : "EOF from client"; - if (!msg) - msg = "Unknown error"; - exit_client_msg(cptr, cptr, &me, "Read error: %s", msg); - } - } - return 0; -} -#else /* USE_SELECT */ - -/* - * Check all connections for new connections and input data that is to be - * processed. Also check for connections with data queued and whether we can - * write it out. - * - * Don't ever use ZERO for `delay', unless you mean to poll and then - * you have to have sleep/wait somewhere else in the code.--msa - */ -int read_message(time_t delay) -{ - struct Client* cptr; - struct Listener* listener; - struct AuthRequest* auth = 0; - struct AuthRequest* auth_next = 0; - struct UPing* uping; - struct UPing* uping_next; - int nfds; - struct timeval wait; - time_t delay2 = delay; - unsigned int usec = 0; - int res = 0; - int length; - int i; - int read_ready; - fd_set read_set; - fd_set write_set; - - for ( ; ; ) - { - FD_ZERO(&read_set); - FD_ZERO(&write_set); - - if (-1 < ResolverFileDescriptor) - FD_SET(ResolverFileDescriptor, &read_set); - if (-1 < UPingFileDescriptor) - FD_SET(UPingFileDescriptor, &read_set); - /* - * set up uping file descriptors - */ - for (uping = uping_begin(); uping; uping = uping_next) { - uping_next = uping->next; - if (uping->active) { - delay2 = 1; - if (uping->lastsent && CurrentTime > uping->timeout) { - uping_end(uping); - continue; - } - assert(-1 < uping->fd); - FD_SET(uping->fd, &read_set); - } - } - /* - * set auth file descriptors - */ - for (auth = AuthPollList; auth; auth = auth->next) { - assert(-1 < auth->fd); - if (IsAuthConnect(auth)) - FD_SET(auth->fd, &write_set); - else /* if (IsAuthPending(auth)) */ - FD_SET(auth->fd, &read_set); - } - /* - * set listener file descriptors - */ - for (listener = ListenerPollList; listener; listener = listener->next) { - assert(-1 < listener->fd); - FD_SET(listener->fd, &read_set); - } - - for (i = HighestFd; i > -1; --i) { - if ((cptr = LocalClientArray[i])) { - if (DBufLength(&(cli_recvQ(cptr)))) - delay2 = 1; - if (DBufLength(&(cli_recvQ(cptr))) < 4088 || IsServer(cptr)) - FD_SET(i, &read_set); - if (MsgQLength(&(cli_sendQ(cptr))) || IsConnecting(cptr) || - (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048)) - FD_SET(i, &write_set); - } - } - - wait.tv_sec = IRCD_MIN(delay2, delay); - wait.tv_usec = usec; - - Debug((DEBUG_INFO, "select: %d %d", delay, delay2)); - - nfds = select(FD_SETSIZE, &read_set, &write_set, 0, &wait); - - CurrentTime = time(0); - - if (-1 < nfds) - break; - - if (errno == EINTR) - return -1; - report_error(SELECT_ERROR_MSG, cli_name(&me), errno); - if (++res > 5) - server_restart("too many select errors"); - sleep(1); - CurrentTime = time(0); - } - - if (-1 < UPingFileDescriptor && FD_ISSET(UPingFileDescriptor, &read_set)) { - uping_echo(); - --nfds; - } - for (uping = uping_begin(); uping; uping = uping_next) { - uping_next = uping->next; - if (uping->active) { - assert(-1 < uping->fd); - if (FD_ISSET(uping->fd, &read_set)) { - uping_read(uping); - if (0 == --nfds) - break; - } - else if (CurrentTime > uping->lastsent) { - uping->lastsent = CurrentTime; - uping_send(uping); - } - } - } - if (-1 < ResolverFileDescriptor && FD_ISSET(ResolverFileDescriptor, &read_set)) { - resolver_read(); - --nfds; - } - /* - * Check fd sets for the auth fd's (if set and valid!) first - * because these can not be processed using the normal loops below. - * -avalon - */ - for (auth = AuthPollList; auth; auth = auth_next) { - auth_next = auth->next; - assert(-1 < auth->fd); - if (IsAuthConnect(auth) && FD_ISSET(auth->fd, &write_set)) { - send_auth_query(auth); - if (0 == --nfds) - break; - } - else if (FD_ISSET(auth->fd, &read_set)) { - read_auth_reply(auth); - if (0 == --nfds) - break; - } - } - /* - * next accept connections from active listeners - */ - for (listener = ListenerPollList; listener; listener = listener->next) { - assert(-1 < listener->fd); - if (0 < nfds && FD_ISSET(listener->fd, &read_set)) - accept_connection(listener); - } - - for (i = HighestFd; -1 < i; --i) { - if (!(cptr = LocalClientArray[i])) - continue; - read_ready = 0; - if (0 < nfds) { - if (FD_ISSET(i, &write_set)) { - --nfds; - if (!on_write_unblocked(cptr) || IsDead(cptr)) { - const char* msg = (cli_error(cptr)) ? strerror(cli_error(cptr)) : cli_info(cptr); - if (!msg) - msg = "Unknown error"; - if (FD_ISSET(i, &read_set)) - --nfds; - exit_client(cptr, cptr, &me, msg); - continue; - } - } - if ((read_ready = FD_ISSET(i, &read_set))) - --nfds; - } - length = 1; /* for fall through case */ - if ((!NoNewLine(cptr) || read_ready) && !IsDead(cptr)) { - if (CPTR_KILLED == (length = read_packet(cptr, read_ready))) - continue; - } - if (IsDead(cptr)) { - const char* msg = (cli_error(cptr)) ? strerror(cli_error(cptr)) : cli_info(cptr); - if (!msg) - msg = "Unknown error"; - exit_client(cptr, cptr, &me, msg); - continue; - } - if (length > 0) - continue; - - /* - * ...hmm, with non-blocking sockets we might get - * here from quite valid reasons, although.. why - * would select report "data available" when there - * wasn't... So, this must be an error anyway... --msa - * actually, EOF occurs when read() returns 0 and - * in due course, select() returns that fd as ready - * for reading even though it ends up being an EOF. -avalon - */ - Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d %d", i, cli_error(cptr), length)); - - if ((IsServer(cptr) || IsHandshake(cptr)) && cli_error(cptr) == 0 && length == 0) - exit_client_msg(cptr, cptr, &me, "Server %s closed the connection (%s)", - cli_name(cptr), cli_serv(cptr)->last_error_msg); - else { - const char* msg = (cli_error(cptr)) ? strerror(cli_error(cptr)) : "EOF from client"; - if (!msg) - msg = "Unknown error"; - exit_client_msg(cptr, cptr, &me, "Read error: %s", msg); - } - } - return 0; + return 1; } -#endif /* USE_SELECT */ - /* * connect_server - start or complete a connection to another server * returns true (1) if successful, false (0) otherwise @@ -1420,9 +914,10 @@ int connect_server(struct ConfItem* aconf, struct Client* by, */ add_client_to_list(cptr); hAddClient(cptr); - nextping = CurrentTime; +/* nextping = CurrentTime; */ - return 1; + return (s_state(&cli_socket(cptr)) == SS_CONNECTED) ? + completed_connection(cptr) : 1; } /* @@ -1449,4 +944,125 @@ void init_server_identity(void) SetYXXServerName(&me, conf->numeric); } +/* + * Process events on a client socket + */ +static void client_sock_callback(struct Event* ev) +{ + struct Client* cptr; + struct Connection* con; + char *fmt = "%s"; + char *fallback = 0; + + assert(0 != ev_socket(ev)); + assert(0 != s_data(ev_socket(ev))); + + con = s_data(ev_socket(ev)); + + assert(0 != con_client(con) || ev_type(ev) == ET_DESTROY); + + cptr = con_client(con); + + assert(0 == cptr || con == cli_connect(cptr)); + + switch (ev_type(ev)) { + case ET_DESTROY: + con_freeflag(con) &= ~FREEFLAG_SOCKET; + + if (!con_freeflag(con) && !cptr) + free_connection(con); + break; + + case ET_CONNECT: /* socket connection completed */ + if (!completed_connection(cptr) || IsDead(cptr)) + fallback = cli_info(cptr); + break; + + case ET_ERROR: /* an error occurred */ + fallback = cli_info(cptr); + cli_error(cptr) = ev_data(ev); + if (s_state(&(con_socket(con))) == SS_CONNECTING) { + completed_connection(cptr); + break; + } + /*FALLTHROUGH*/ + case ET_EOF: /* end of file on socket */ + Debug((DEBUG_ERROR, "READ ERROR: fd = %d %d", cli_fd(cptr), + cli_error(cptr))); + cli_flags(cptr) |= FLAGS_DEADSOCKET; + if ((IsServer(cptr) || IsHandshake(cptr)) && cli_error(cptr) == 0) { + exit_client_msg(cptr, cptr, &me, "Server %s closed the connection (%s)", + cli_name(cptr), cli_serv(cptr)->last_error_msg); + return; + } else { + fmt = "Read error: %s"; + fallback = "EOF from client"; + } + break; + + case ET_WRITE: /* socket is writable */ + cli_flags(cptr) &= ~FLAGS_BLOCKED; + if (cli_listing(cptr) && MsgQLength(&(cli_sendQ(cptr))) < 2048) + list_next_channels(cptr, 64); + Debug((DEBUG_SEND, "Sending queued data to %C", cptr)); + send_queued(cptr); + break; + + case ET_READ: /* socket is readable */ + if (!IsDead(cptr)) { + Debug((DEBUG_DEBUG, "Reading data from %C", cptr)); + if (read_packet(cptr, 1) == 0) /* error while reading packet */ + fallback = "EOF from client"; + } + break; + + default: +#ifndef NDEBUG + abort(); /* unrecognized event */ +#endif + break; + } + + assert(0 == cptr || 0 == cli_connect(cptr) || con == cli_connect(cptr)); + + if (fallback) { + const char* msg = (cli_error(cptr)) ? strerror(cli_error(cptr)) : fallback; + if (!msg) + msg = "Unknown error"; + exit_client_msg(cptr, cptr, &me, fmt, msg); + } +} + +/* + * Process a timer on client socket + */ +static void client_timer_callback(struct Event* ev) +{ + struct Client* cptr; + struct Connection* con; + + assert(0 != ev_timer(ev)); + assert(0 != t_data(ev_timer(ev))); + assert(ET_DESTROY == ev_type(ev) || ET_EXPIRE == ev_type(ev)); + + con = t_data(ev_timer(ev)); + assert(0 != con_client(con) || ev_type(ev) == ET_DESTROY); + + cptr = con_client(con); + + assert(0 == cptr || con == cli_connect(cptr)); + + con_freeflag(con) &= ~FREEFLAG_TIMER; /* timer has expired... */ + + if (ev_type(ev)== ET_DESTROY) { + if (!con_freeflag(con) && !cptr) + free_connection(con); /* client is being destroyed */ + } else { + Debug((DEBUG_LIST, "Client process timer for %C expired; processing", + cptr)); + read_packet(cptr, 0); /* read_packet will re-add timer if needed */ + } + + assert(0 == cptr || 0 == cli_connect(cptr) || con == cli_connect(cptr)); +} diff --git a/ircd/s_conf.c b/ircd/s_conf.c index 49f5649..05cd7ce 100644 --- a/ircd/s_conf.c +++ b/ircd/s_conf.c @@ -1231,7 +1231,7 @@ int read_configuration_file(void) if (aconf) free_conf(aconf); fbclose(file); - nextping = nextconnect = CurrentTime; +/* nextping = nextconnect = CurrentTime; */ feature_mark(); /* reset unmarked features */ return 1; } diff --git a/ircd/s_err.c b/ircd/s_err.c index d070265..7a4fda3 100644 --- a/ircd/s_err.c +++ b/ircd/s_err.c @@ -507,7 +507,7 @@ static Numeric replyTable[] = { /* 236 */ { 0 }, /* 237 */ - { 0 }, + { RPL_STATSENGINE, "%s :Event loop engine", "237" }, /* 238 */ { RPL_STATSFLINE, "%c %s %s", "238" }, /* 239 */ diff --git a/ircd/s_serv.c b/ircd/s_serv.c index 4777df1..ff5d2e0 100644 --- a/ircd/s_serv.c +++ b/ircd/s_serv.c @@ -137,7 +137,7 @@ int server_estab(struct Client *cptr, struct ConfItem *aconf, SetBurst(cptr); - nextping = CurrentTime; +/* nextping = CurrentTime; */ /* * NOTE: check for acptr->user == cptr->serv->user is necessary to insure diff --git a/ircd/s_stats.c b/ircd/s_stats.c index 38ecc7c..8743ae4 100644 --- a/ircd/s_stats.c +++ b/ircd/s_stats.c @@ -73,6 +73,7 @@ const char *statsinfo[] = { "g - Global bans (G-lines).", "k - Local bans (K-Lines).", "o - Operator information.", + "e - Report server event loop engine.", "f - Feature settings.", "m - Message usage information.", "t - Local connection statistics (Total SND/RCV, etc).", diff --git a/ircd/s_user.c b/ircd/s_user.c index 0a71c4a..6d7cc91 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -535,7 +535,7 @@ int register_user(struct Client *cptr, struct Client *sptr, m_lusers(sptr, sptr, 1, parv); update_load(); motd_signon(sptr); - nextping = CurrentTime; +/* nextping = CurrentTime; */ if (cli_snomask(sptr) & SNO_NOISY) set_snomask(sptr, cli_snomask(sptr) & SNO_NOISY, SNO_ADD); IPcheck_connect_succeeded(sptr); diff --git a/ircd/send.c b/ircd/send.c index 89ee2b9..bf8335d 100644 --- a/ircd/send.c +++ b/ircd/send.c @@ -140,8 +140,10 @@ void send_queued(struct Client *to) if ((len = deliver_it(to, &(cli_sendQ(to))))) { msgq_delete(&(cli_sendQ(to)), len); cli_lastsq(to) = MsgQLength(&(cli_sendQ(to))) / 1024; - if (IsBlocked(to)) + if (IsBlocked(to)) { + update_write(to); return; + } } else { if (IsDead(to)) { @@ -155,6 +157,7 @@ void send_queued(struct Client *to) /* Ok, sendq is now empty... */ client_drop_sendq(cli_connect(to)); + update_write(to); } void send_buffer(struct Client* to, struct MsgBuf* buf, int prio) @@ -184,6 +187,7 @@ void send_buffer(struct Client* to, struct MsgBuf* buf, int prio) msgq_add(&(cli_sendQ(to)), buf, prio); client_add_sendq(cli_connect(to), &send_queues); + update_write(to); /* * Update statistics. The following is slightly incorrect diff --git a/ircd/uping.c b/ircd/uping.c index 1c35a7f..a83c57e 100644 --- a/ircd/uping.c +++ b/ircd/uping.c @@ -24,6 +24,7 @@ #include "client.h" #include "ircd.h" #include "ircd_alloc.h" +#include "ircd_events.h" #include "ircd_log.h" #include "ircd_osdep.h" #include "ircd_string.h" @@ -59,6 +60,8 @@ static struct UPing* pingList = 0; int UPingFileDescriptor = -1; /* UDP listener socket for upings */ +static struct Socket upingSock; + /* * pings_begin - iterator function for ping list */ @@ -88,6 +91,14 @@ static void uping_erase(struct UPing* p) } } +/* Called when the event engine detects activity on the UPing socket */ +static void uping_echo_callback(struct Event* ev) +{ + assert(ev_type(ev) == ET_READ); + + uping_echo(); +} + /* * Setup a UDP socket and listen for incoming packets */ @@ -129,6 +140,12 @@ int uping_init(void) close(fd); return -1; } + if (!socket_add(&upingSock, uping_echo_callback, 0, SS_DATAGRAM, + SOCK_EVENT_READABLE, fd)) { + Debug((DEBUG_ERROR, "UPING: Unable to queue fd to event system")); + close(fd); + return -1; + } UPingFileDescriptor = fd; return fd; } @@ -168,6 +185,85 @@ void uping_echo() } +/* Callback when socket has data to read */ +static void uping_read_callback(struct Event* ev) +{ + struct UPing *pptr; + + assert(0 != ev_socket(ev)); + assert(0 != s_data(ev_socket(ev))); + + pptr = s_data(ev_socket(ev)); + + Debug((DEBUG_SEND, "uping_read_callback called, %p (%d)", pptr, + ev_type(ev))); + + if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ + pptr->freeable &= ~UPING_PENDING_SOCKET; + + if (!pptr->freeable) + MyFree(pptr); /* done with it, finally */ + } else { + assert(ev_type(ev) == ET_READ); + + uping_read(pptr); /* read uping response */ + } +} + +/* Callback to send another ping */ +static void uping_sender_callback(struct Event* ev) +{ + struct UPing *pptr; + + assert(0 != ev_timer(ev)); + assert(0 != t_data(ev_timer(ev))); + + pptr = t_data(ev_timer(ev)); + + Debug((DEBUG_SEND, "uping_sender_callback called, %p (%d)", pptr, + ev_type(ev))); + + if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ + pptr->freeable &= ~UPING_PENDING_SENDER; + + if (!pptr->freeable) + MyFree(pptr); /* done with it, finally */ + } else { + assert(ev_type(ev) == ET_EXPIRE); + + pptr->lastsent = CurrentTime; /* store last ping time */ + uping_send(pptr); /* send a ping */ + + if (pptr->sent == pptr->count) /* done sending pings, don't send more */ + timer_del(ev_timer(ev)); + } +} + +/* Callback to kill a ping */ +static void uping_killer_callback(struct Event* ev) +{ + struct UPing *pptr; + + assert(0 != ev_timer(ev)); + assert(0 != t_data(ev_timer(ev))); + + pptr = t_data(ev_timer(ev)); + + Debug((DEBUG_SEND, "uping_killer_callback called, %p (%d)", pptr, + ev_type(ev))); + + if (ev_type(ev) == ET_DESTROY) { /* being destroyed */ + pptr->freeable &= ~UPING_PENDING_KILLER; + + if (!pptr->freeable) + MyFree(pptr); /* done with it, finally */ + } else { + assert(ev_type(ev) == ET_EXPIRE); + + uping_end(pptr); /* kill the uping, kill the uping! */ + } +} + /* * start_ping */ @@ -175,10 +271,15 @@ static void uping_start(struct UPing* pptr) { assert(0 != pptr); + timer_add(&pptr->sender, uping_sender_callback, (void*) pptr, + TT_PERIODIC, 1); + timer_add(&pptr->killer, uping_killer_callback, (void*) pptr, + TT_RELATIVE, UPINGTIMEOUT); + pptr->freeable |= UPING_PENDING_SENDER | UPING_PENDING_KILLER; + sendcmdto_one(&me, CMD_NOTICE, pptr->client, "%C :Sending %d ping%s to %s", pptr->client, pptr->count, (pptr->count == 1) ? "" : "s", pptr->name); - pptr->timeout = CurrentTime + UPINGTIMEOUT; pptr->active = 1; } @@ -264,11 +365,8 @@ void uping_read(struct UPing* pptr) pptr->ms_min = pingtime; if (pingtime > pptr->ms_max) pptr->ms_max = pingtime; - - pptr->timeout = CurrentTime + UPINGTIMEOUT; - Debug((DEBUG_SEND, "read_ping: %d bytes, ti %lu: [%s %s] %lu ms", - len, pptr->timeout, buf, (buf + strlen(buf) + 1), pingtime)); + timer_chg(&pptr->killer, TT_RELATIVE, UPINGTIMEOUT); s = pptr->buf + strlen(pptr->buf); sprintf(s, " %u", pingtime); @@ -311,6 +409,15 @@ int uping_server(struct Client* sptr, struct ConfItem* aconf, int port, int coun assert(0 != pptr); memset(pptr, 0, sizeof(struct UPing)); + if (!socket_add(&pptr->socket, uping_read_callback, (void*) pptr, + SS_DATAGRAM, SOCK_EVENT_READABLE, fd)) { + sendcmdto_one(&me, CMD_NOTICE, sptr, "%C :UPING: Can't queue fd for " + "reading", sptr); + close(fd); + MyFree(pptr); + return 0; + } + pptr->fd = fd; pptr->sin.sin_port = htons(port); pptr->sin.sin_addr.s_addr = aconf->ipnum.s_addr; @@ -318,6 +425,7 @@ int uping_server(struct Client* sptr, struct ConfItem* aconf, int port, int coun pptr->count = IRCD_MIN(20, count); pptr->client = sptr; pptr->index = -1; + pptr->freeable = UPING_PENDING_SOCKET; strcpy(pptr->name, aconf->name); pptr->next = pingList; @@ -356,7 +464,12 @@ void uping_end(struct UPing* pptr) uping_erase(pptr); if (pptr->client) ClearUPing(pptr->client); - MyFree(pptr); + if (pptr->freeable & UPING_PENDING_SOCKET) + socket_del(&pptr->socket); + if (pptr->freeable & UPING_PENDING_SENDER) + timer_del(&pptr->sender); + if (pptr->freeable & UPING_PENDING_KILLER) + timer_del(&pptr->killer); } void uping_cancel(struct Client *sptr, struct Client* acptr) -- 2.20.1