diff options
| author | rburchell <rburchell@5417fbe8-f217-4b02-8779-1006273d7864> | 2009-06-10 22:29:59 +0000 |
|---|---|---|
| committer | rburchell <rburchell@5417fbe8-f217-4b02-8779-1006273d7864> | 2009-06-10 22:29:59 +0000 |
| commit | 695644d0c479228feb92e2cd9501d15819778c24 (patch) | |
| tree | ec3389db1a9fa7a957618d1a02765a4df3c79aa0 /src | |
| parent | c8c89c7af098ad8825309dea4e118413b368a1d6 (diff) | |
New timer infrastructure, can be used inside modules. Replaces old ENFORCE/COLLIDE/inhabit timers, too. Patch by Adam.
git-svn-id: http://anope.svn.sourceforge.net/svnroot/anope/trunk@2317 5417fbe8-f217-4b02-8779-1006273d7864
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 8 | ||||
| -rw-r--r-- | src/chanserv.c | 43 | ||||
| -rw-r--r-- | src/main.c | 5 | ||||
| -rw-r--r-- | src/nickserv.c | 286 | ||||
| -rw-r--r-- | src/timeout.c | 106 |
5 files changed, 138 insertions, 310 deletions
diff --git a/src/Makefile b/src/Makefile index 72b9776b9..6f2944b90 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,13 +1,13 @@ OBJS = actions.o base64.o bots.o botserv.o channels.o chanserv.o command.o commands.o compat.o \ config.o datafiles.o encrypt.o hashcomp.o hostserv.o init.o ircd.o language.o log.o mail.o main.o \ memory.o memoserv.o messages.o misc.o modules.o news.o nickserv.o operserv.o \ - process.o protocol.o send.o servers.o sessions.o slist.o sockutil.o opertype.o timeout.o users.o module.o modulemanager.o configreader.o \ - wildcard.o nickcore.o nickalias.o + process.o protocol.o send.o servers.o sessions.o slist.o sockutil.o opertype.o users.o module.o modulemanager.o configreader.o \ + wildcard.o nickcore.o nickalias.o timers.o INCLUDES = ../include/commands.h ../include/defs.h ../include/language.h \ ../include/pseudo.h ../include/sysconf.h ../include/config.h \ ../include/encrypt.h ../include/messages.h ../include/services.h \ - ../include/timeout.h ../include/datafiles.h ../include/extern.h \ + ../include/timers.h ../include/datafiles.h ../include/extern.h \ ../include/modules.h ../include/slist.h ../include/hashcomp.h MAKEARGS = 'CFLAGS=${CFLAGS}' 'CC=${CC}' 'ANOPELIBS=${ANOPELIBS}' \ @@ -33,6 +33,7 @@ services: $(OBJS) mod_version @$(MAKEBIN) $(CC) $(CFLAGS) $(OBJS) $(ANOPELIBS) $(MLIBS) -o $@ $(LDFLAGS) $(OBJS): Makefile +timers.o: timers.cpp $(INCLUDES) nickcore.o: nickcore.cpp $(INCLUDES) nickalias.o: nickalias.cpp $(INCLUDES) actions.o: actions.c $(INCLUDES) @@ -72,7 +73,6 @@ sessions.o: sessions.c $(INCLUDES) slist.o: slist.c $(INCLUDES) sockutil.o: sockutil.c $(INCLUDES) opertype.o: opertype.cpp $(INCLUDES) -timeout.o: timeout.c $(INCLUDES) users.o: users.c $(INCLUDES) vsnprintf.o: vsnprintf.c $(INCLUDES) wildcard.o: wildcard.cpp $(INCLUDES) diff --git a/src/chanserv.c b/src/chanserv.c index 91432defe..abebb6f61 100644 --- a/src/chanserv.c +++ b/src/chanserv.c @@ -127,6 +127,28 @@ void moduleAddChanServCmds() { /* *INDENT-ON* */ /*************************************************************************/ + +class ChanServTimer : public Timer +{ + private: + std::string channel; + + public: + ChanServTimer(long delay, const std::string &chan) : Timer(delay), channel(chan) + { + } + + void Tick(time_t ctime) + { + ChannelInfo *ci = cs_findchan(channel.c_str()); + + if (ci) + ci->flags &= ~CI_INHABIT; + + ircdproto->SendPart(findbot(s_ChanServ), channel.c_str(), NULL); + } +}; + /*************************************************************************/ /* Returns modes for mlock in a nice way. */ @@ -1083,21 +1105,6 @@ int check_should_protect(User * user, char *chan) /*************************************************************************/ -/* Tiny helper routine to get ChanServ out of a channel after it went in. */ - -static void timeout_leave(Timeout * to) -{ - const char *chan = static_cast<const char *>(to->data); - ChannelInfo *ci = cs_findchan(chan); - - if (ci) /* Check cos the channel may be dropped in the meantime */ - ci->flags &= ~CI_INHABIT; - - ircdproto->SendPart(findbot(s_ChanServ), chan, NULL); - delete [] static_cast<const char *>(to->data); -} - - /* Check whether a user is permitted to be on a channel. If so, return 0; * else, kickban the user with an appropriate message (could be either * AKICK or restricted access) and return 1. Note that this is called @@ -1118,7 +1125,7 @@ int check_kick(User * user, const char *chan, time_t chants) char buf[BUFSIZE]; char mask[BUFSIZE]; const char *reason; - Timeout *t; + ChanServTimer *t; if (!ci) return 0; @@ -1207,8 +1214,8 @@ int check_kick(User * user, const char *chan, time_t chants) { ircdproto->SendMode(findbot(s_ChanServ), chan, "+ntsi"); } - t = add_timeout(CSInhabit, timeout_leave, 0); - t->data = sstrdup(chan); + + t = new ChanServTimer(CSInhabit, chan); ci->flags |= CI_INHABIT; } diff --git a/src/main.c b/src/main.c index afc893b81..b3ab606d9 100644 --- a/src/main.c +++ b/src/main.c @@ -27,7 +27,7 @@ */ #include "services.h" -#include "timeout.h" +#include "timers.h" #include "version.h" #include "datafiles.h" #include "modules.h" @@ -91,7 +91,6 @@ const char version_build[] = /* the space is needed cause if you build with nothing it will complain */ const char version_flags[] = " " VER_OS VER_MODULE; - /******** Local variables! ********/ /* Set to 1 after we've set everything up */ @@ -479,7 +478,7 @@ int main(int ac, char **av, char **envp) ModuleManager::RunCallbacks(); if (t - last_check >= TimeoutCheck) { - check_timeouts(); + TimerManager::TickTimers(t); last_check = t; } diff --git a/src/nickserv.c b/src/nickserv.c index 21c3205fe..38384d0b0 100644 --- a/src/nickserv.c +++ b/src/nickserv.c @@ -31,7 +31,94 @@ unsigned int guestnum; /* Current guest number */ /*************************************************************************/ -static void add_ns_timeout(NickAlias * na, int type, time_t delay); +class NickServCollide; +class NickServRelease; + +static std::map<NickAlias *, NickServCollide *> NickServCollides; +static std::map<NickAlias *, NickServRelease *> NickServReleases; + +class NickServCollide : public Timer +{ + public: + NickAlias *na; + + NickServCollide(NickAlias *nickalias, time_t delay) : Timer(delay), na(nickalias) + { + NickServCollides.insert(std::make_pair(nickalias, this)); + } + + void Tick(time_t ctime) + { + /* If they identified or don't exist anymore, don't kill them. */ + if ((na->status & NS_IDENTIFIED) || !finduser(na->nick) + || finduser(na->nick)->my_signon > this->GetSetTime()) + return; + /* The RELEASE timeout will always add to the beginning of the + * list, so we won't see it. Which is fine because it can't be + * triggered yet anyway. */ + collide(na, 1); + } + + static void ClearTimers(NickAlias *na) + { + std::map<NickAlias *, NickServCollide *>::iterator i = NickServCollides.find(na); + NickServCollide *t; + + if (i != NickServCollides.end()) + { + t = i->second; + + NickServCollides.erase(i); + TimerManager::DelTimer(t); + } + } +}; + +class NickServRelease : public Timer +{ + public: + NickAlias *na; + std::string uid; + + NickServRelease(NickAlias *nickalias, time_t delay) : Timer(delay), na(nickalias) + { + NickServReleases.insert(std::make_pair(nickalias, this)); + } + + void Tick(time_t ctime) + { + if (ircd->svshold) + { + ircdproto->SendSVSHoldDel(na->nick); + } + else + { + if (ircd->ts6 && !uid.empty()) + ircdproto->SendQuit(uid.c_str(), NULL); + else + ircdproto->SendQuit(na->nick, NULL); + } + na->status &= ~NS_KILL_HELD; + } + + static void ClearTimers(NickAlias *na, bool dorelease = false) + { + std::map<NickAlias *, NickServRelease *>::iterator i = NickServReleases.find(na); + NickServRelease *t; + + if (i != NickServReleases.end()) + { + t = i->second; + + NickServReleases.erase(i); + + if (dorelease) + release(na, 1); + + TimerManager::DelTimer(t); + } + } +}; /*************************************************************************/ /* *INDENT-OFF* */ @@ -536,6 +623,7 @@ int validate_user(User * u) { NickAlias *na; NickRequest *nr; + NickServCollide *t; int on_access; @@ -598,12 +686,12 @@ int validate_user(User * u) else if (na->nc->flags & NI_KILL_QUICK) { notice_lang(s_NickServ, u, FORCENICKCHANGE_IN_20_SECONDS); - add_ns_timeout(na, TO_COLLIDE, 20); + t = new NickServCollide(na, 20); } else { notice_lang(s_NickServ, u, FORCENICKCHANGE_IN_1_MINUTE); - add_ns_timeout(na, TO_COLLIDE, 60); + t = new NickServCollide(na, 60); } } @@ -618,6 +706,8 @@ int validate_user(User * u) void cancel_user(User * u) { NickAlias *na = findnick(u->nick); + NickServRelease *t; + std::string uid; if (na) { @@ -629,8 +719,10 @@ void cancel_user(User * u) } else if (ircd->svsnick) { - ircdproto->SendClientIntroduction(u->nick, NSEnforcerUser, NSEnforcerHost, "Services Enforcer", "+", ts6_uid_retrieve()); - add_ns_timeout(na, TO_RELEASE, NSReleaseTimeout); + uid = ts6_uid_retrieve(); + ircdproto->SendClientIntroduction(u->nick, NSEnforcerUser, NSEnforcerHost, "Services Enforcer", "+", uid.c_str()); + t = new NickServRelease(na, NSReleaseTimeout); + t->uid = uid; } else { @@ -644,7 +736,7 @@ void cancel_user(User * u) na->status &= ~NS_TEMPORARY; } - del_ns_timeout(na, TO_COLLIDE); + NickServCollide::ClearTimers(na); } } @@ -1102,7 +1194,8 @@ int delnick(NickAlias * na) { User *u = NULL; /* First thing to do: remove any timeout belonging to the nick we're deleting */ - clean_ns_timeouts(na); + NickServCollide::ClearTimers(na); + NickServRelease::ClearTimers(na, true); /* Second thing to do: look for an user using the alias * being deleted, and make appropriate changes */ @@ -1171,7 +1264,7 @@ void collide(NickAlias * na, int from_timeout) char guestnick[NICKMAX]; if (!from_timeout) - del_ns_timeout(na, TO_COLLIDE); + NickServCollide::ClearTimers(na); /* Old system was unsure since there can be more than one collide * per second. So let use another safer method. @@ -1207,9 +1300,10 @@ void collide(NickAlias * na, int from_timeout) void release(NickAlias * na, int from_timeout) { if (!from_timeout) - del_ns_timeout(na, TO_RELEASE); + NickServRelease::ClearTimers(na); + if (ircd->svshold) - { + { ircdproto->SendSVSHoldDel(na->nick); } else @@ -1220,179 +1314,13 @@ void release(NickAlias * na, int from_timeout) } /*************************************************************************/ -/*************************************************************************/ - -static struct my_timeout -{ - struct my_timeout *next, *prev; - NickAlias *na; - Timeout *to; - int type; -} *my_timeouts; - -/*************************************************************************/ - -/* Remove a collide/release timeout from our private list. */ - -static void rem_ns_timeout(NickAlias * na, int type) -{ - struct my_timeout *t, *t2; - - t = my_timeouts; - while (t) - { - if (t->na == na && t->type == type) - { - t2 = t->next; - if (t->next) - t->next->prev = t->prev; - if (t->prev) - t->prev->next = t->next; - else - my_timeouts = t->next; - delete t; - t = t2; - } - else - { - t = t->next; - } - } -} - -/*************************************************************************/ -/* Collide a nick on timeout. */ - -static void timeout_collide(Timeout * t) -{ - NickAlias *na = static_cast<NickAlias *>(t->data); - - rem_ns_timeout(na, TO_COLLIDE); - /* If they identified or don't exist anymore, don't kill them. */ - if ((na->status & NS_IDENTIFIED) || !finduser(na->nick) - || finduser(na->nick)->my_signon > t->settime) - return; - /* The RELEASE timeout will always add to the beginning of the - * list, so we won't see it. Which is fine because it can't be - * triggered yet anyway. */ - collide(na, 1); -} - -/*************************************************************************/ - -/* Release a nick on timeout. */ - -static void timeout_release(Timeout * t) -{ - NickAlias *na = static_cast<NickAlias *>(t->data); - - rem_ns_timeout(na, TO_RELEASE); - release(na, 1); -} - -/*************************************************************************/ - -/* Add a collide/release timeout. */ - -static void add_ns_timeout(NickAlias * na, int type, time_t delay) +void del_ns_timeout(NickAlias * na, int type) { - Timeout *to; - struct my_timeout *t; - void (*timeout_routine) (Timeout *); - if (type == TO_COLLIDE) - timeout_routine = timeout_collide; + NickServCollide::ClearTimers(na); else if (type == TO_RELEASE) - timeout_routine = timeout_release; - else - { - alog("NickServ: unknown timeout type %d! na=0x%p (%s), delay=%ld", - type, static_cast<void *>(na), na->nick, static_cast<long>(delay)); - return; - } - - to = add_timeout(delay, timeout_routine, 0); - to->data = na; - - t = new my_timeout; - t->na = na; - t->to = to; - t->type = type; - - t->prev = NULL; - t->next = my_timeouts; - my_timeouts = t; - /* Andy Church should stop coding while being drunk. - * Here's the two lines he forgot that produced the timed_update evil bug - * and a *big* memory leak. - */ - if (t->next) - t->next->prev = t; -} - -/*************************************************************************/ - -/* Delete a collide/release timeout. */ - -void del_ns_timeout(NickAlias * na, int type) -{ - struct my_timeout *t, *t2; - - t = my_timeouts; - while (t) - { - if (t->na == na && t->type == type) - { - t2 = t->next; - if (t->next) - t->next->prev = t->prev; - if (t->prev) - t->prev->next = t->next; - else - my_timeouts = t->next; - del_timeout(t->to); - delete t; - t = t2; - } - else - { - t = t->next; - } - } -} - -/*************************************************************************/ - -/* Deletes all timeouts belonging to a given nick. - * This should only be called before nick deletion. - */ - -void clean_ns_timeouts(NickAlias * na) -{ - struct my_timeout *t, *next; - - for (t = my_timeouts; t; t = next) - { - next = t->next; - if (t->na == na) - { - if (debug) - alog("debug: %s deleting timeout type %d from %s", - s_NickServ, t->type, t->na->nick); - /* If the timeout has the TO_RELEASE type, we should release the user */ - if (t->type == TO_RELEASE) - release(na, 1); - if (t->next) - t->next->prev = t->prev; - if (t->prev) - t->prev->next = t->next; - else - my_timeouts = t->next; - del_timeout(t->to); - delete t; - } - } + NickServRelease::ClearTimers(na); } /*************************************************************************/ diff --git a/src/timeout.c b/src/timeout.c index d7544fb9e..e69de29bb 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -1,106 +0,0 @@ -/* Routines for time-delayed actions. - * - * (C) 2003-2009 Anope Team - * Contact us at team@anope.org - * - * Please read COPYING and README for further details. - * - * Based on the original code of Epona by Lara. - * Based on the original code of Services by Andy Church. - * - * $Id$ - * - */ - -#include "services.h" -#include "pseudo.h" - -static Timeout *timeouts = NULL; - -typedef void (*voidF)(); - -/*************************************************************************/ - -/* Check the timeout list for any pending actions. */ - -void check_timeouts() -{ - Timeout *to, *to2; - time_t t = time(NULL); - - if (debug >= 2) - alog("debug: Checking timeouts at %ld", static_cast<long>(t)); - - to = timeouts; - while (to) { - if (t < to->timeout) { - to = to->next; - continue; - } - to->code(to); - if (to->repeat) { - to = to->next; - continue; - } - to2 = to->next; - if (to->next) - to->next->prev = to->prev; - if (to->prev) - to->prev->next = to->next; - else - timeouts = to->next; - delete to; - to = to2; - } - if (debug >= 2) - alog("debug: Finished timeout list"); -} - -/*************************************************************************/ - -/* Add a timeout to the list to be triggered in `delay' seconds. If - * `repeat' is nonzero, do not delete the timeout after it is triggered. - * This must maintain the property that timeouts added from within a - * timeout routine do not get checked during that run of the timeout list. - */ - -Timeout *add_timeout(int delay, void (*code) (Timeout *), int repeat) -{ - Timeout *t = new Timeout; - t->settime = time(NULL); - t->timeout = t->settime + delay; - t->code = code; - t->repeat = repeat; - t->next = timeouts; - t->prev = NULL; - t->data = NULL; - if (timeouts) - timeouts->prev = t; - timeouts = t; - return t; -} - -/*************************************************************************/ - -/* Remove a timeout from the list (if it's there). */ - -void del_timeout(Timeout * t) -{ - Timeout *ptr; - - for (ptr = timeouts; ptr; ptr = ptr->next) { - if (ptr == t) - break; - } - if (!ptr) - return; - if (t->prev) - t->prev->next = t->next; - else - timeouts = t->next; - if (t->next) - t->next->prev = t->prev; - delete t; -} - -/*************************************************************************/ |
