summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorrburchell <rburchell@5417fbe8-f217-4b02-8779-1006273d7864>2009-06-10 22:29:59 +0000
committerrburchell <rburchell@5417fbe8-f217-4b02-8779-1006273d7864>2009-06-10 22:29:59 +0000
commit695644d0c479228feb92e2cd9501d15819778c24 (patch)
treeec3389db1a9fa7a957618d1a02765a4df3c79aa0 /src
parentc8c89c7af098ad8825309dea4e118413b368a1d6 (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/Makefile8
-rw-r--r--src/chanserv.c43
-rw-r--r--src/main.c5
-rw-r--r--src/nickserv.c286
-rw-r--r--src/timeout.c106
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;
-}
-
-/*************************************************************************/