From: Gunnar Beutner Date: Fri, 28 Jun 2013 14:48:03 +0000 (+0200) Subject: Remove the anti-flood functionality and implement fast-tracking requests. X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/commitdiff_plain/6fec18180502061378b36df7966cb881bf99d281 Remove the anti-flood functionality and implement fast-tracking requests. --HG-- branch : shroudrequest --- diff --git a/request/Makefile.in b/request/Makefile.in index 2e1b6aa8..11b767f3 100644 --- a/request/Makefile.in +++ b/request/Makefile.in @@ -6,4 +6,4 @@ LDFLAGS+=$(LIBPGSQL) .PHONY: all all: request.so -request.so: lrequest.o request.o request_block.o sqrequest.o user.o +request.so: lrequest.o request.o request_block.o request_fasttrack.o sqrequest.o user.o diff --git a/request/lrequest.c b/request/lrequest.c index f8da1b2a..77a383f2 100644 --- a/request/lrequest.c +++ b/request/lrequest.c @@ -5,6 +5,7 @@ #include "request.h" #include "lrequest.h" #include "request_block.h" +#include "request_fasttrack.h" #include "../localuser/localuser.h" /* stats counters */ @@ -30,55 +31,49 @@ int lr_requestl(nick *svc, nick *np, channel *cp, nick *qnick) { cf = cf_findchanfix(cp->index); - if (cf == NULL) { - sendnoticetouser(svc, np, "Sorry, your channel '%s' was created recently. " - "Please try again in an hour.", cp->index->name->content); + if(cf) { + rocount = cf_getsortedregops(cf, LR_TOPX, rolist); - lr_noregops++; + ro = NULL; - return RQ_ERROR; - } - - rocount = cf_getsortedregops(cf, LR_TOPX, rolist); - - ro = NULL; - - for (i = 0; i < min(LR_TOPX, rocount); i++) { - if (cf_cmpregopnick(rolist[i], np)) { - ro = rolist[i]; - break; + for (i = 0; i < min(LR_TOPX, rocount); i++) { + if (cf_cmpregopnick(rolist[i], np)) { + ro = rolist[i]; + break; + } } - } - if (ro == NULL) { - sendnoticetouser(svc, np, "Sorry, you must be one of the top %d ops " - "for the channel '%s'.", LR_TOPX, cp->index->name->content); + if (ro == NULL) { + sendnoticetouser(svc, np, "Sorry, you must be one of the top %d ops " + "for the channel '%s'.", LR_TOPX, cp->index->name->content); - lr_top5++; + lr_top5++; - return RQ_ERROR; + return RQ_ERROR; + } } - /* treat blocked users as if their score is too low */ - if (ro->score < LR_CFSCORE || rq_findblock(np->authname)) { - if (rq_isspam(np)) { - sendnoticetouser(svc, np, "Do not flood the request system. " - "Try again in %s.", rq_longtoduration(rq_blocktime(np))); + if(!rq_tryfasttrack(np)) { + if (cf == NULL) { + sendnoticetouser(svc, np, "Sorry, your channel '%s' was created recently. " + "Please try again in an hour.", cp->index->name->content); - lr_floodattempts++; + lr_noregops++; return RQ_ERROR; } - sendnoticetouser(svc, np, "Sorry, you do not meet the " - "%s request requirements; please try again in an hour, " - "see http://www.quakenet.org/faq/faq.php?c=1&f=6#6", RQ_QNICK); + /* treat blocked users as if their score is too low */ + if (ro->score < LR_CFSCORE || rq_findblock(np->authname)) { + sendnoticetouser(svc, np, "Sorry, you do not meet the " + "%s request requirements; please try again in an hour, " + "see http://www.quakenet.org/faq/faq.php?c=1&f=6#6", RQ_QNICK); - lr_scoretoolow++; + lr_scoretoolow++; - return RQ_ERROR; + return RQ_ERROR; + } } - sendmessagetouser(svc, qnick, "addchan %s #%s +jp upgrade %s", cp->index->name->content, np->authname, np->nick); diff --git a/request/request.c b/request/request.c index 7b9fc104..6d604ac5 100644 --- a/request/request.c +++ b/request/request.c @@ -12,6 +12,7 @@ #include "../splitlist/splitlist.h" #include "request.h" #include "request_block.h" +#include "request_fasttrack.h" #include "lrequest.h" #include "sqrequest.h" #include "user.h" @@ -55,6 +56,9 @@ void _init(void) { if(!rq_initblocks()) return; + if(!rq_initfasttrack()) + return; + extloaded = 1; rqcommands = newcommandtree(); @@ -106,6 +110,7 @@ void _fini(void) { destroycommandtree(rqcommands); rq_finiblocks(); + rq_finifasttrack(); qr_finirequest(); ru_persist(); diff --git a/request/request_block.c b/request/request_block.c index fa7f59de..779c87f3 100644 --- a/request/request_block.c +++ b/request/request_block.c @@ -7,19 +7,10 @@ /* array of blocks */ array rqblocks; -/* our anti-flood nick extension */ -int rqnext; - /* are we currently loading blocks? */ int rq_loading; -void rqhook_lostnick(int hook, void *arg); - int rq_initblocks(void) { - rqnext = registernickext("request"); - if(rqnext < 0) - return 0; - array_init(&rqblocks, sizeof(rq_block)); array_setlim1(&rqblocks, 5); array_setlim2(&rqblocks, 20); @@ -31,15 +22,12 @@ int rq_initblocks(void) { rq_addblock("#qnet*", "Reserved for QuakeNet use only.", "request", 0, 0); rq_addblock("#help*", "Reserved for QuakeNet use only.", "request", 0, 0); - registerhook(HOOK_NICK_LOSTNICK, &rqhook_lostnick); - return 1; } void rq_finiblocks(void) { int i; rq_block block; - nick *nip; for (i = 0; i < rqblocks.cursi; i++) { block = ((rq_block*)rqblocks.content)[i]; @@ -50,64 +38,6 @@ void rq_finiblocks(void) { } array_free(&rqblocks); - - for (i=0; inext) - free(nip->exts[rqnext]); - - deregisterhook(HOOK_NICK_LOSTNICK, &rqhook_lostnick); - - releasenickext(rqnext); -} - -void rqhook_lostnick(int hook, void *arg) { - nick *np = (nick*)arg; - - free(np->exts[rqnext]); -} - -int rq_isspam(nick *np) { - rq_flood *lf; - - if (np->exts[rqnext] == NULL) { - np->exts[rqnext] = lf = (rq_flood*)malloc(sizeof(rq_flood)); - - lf->count = 1; - lf->created = getnettime(); - lf->expire = 0; - - return 0; - } else { - lf = np->exts[rqnext]; - - lf->count -= (getnettime() - lf->created) / (RQ_SPAMBLOCK / RQ_SPAMCOUNT); - - if (lf->count < 0) - lf->count = 0; - - if (lf->count > RQ_SPAMCOUNT && lf->expire > getnettime()) { - return 1; - } else { - lf->count++; - - if (lf->count > RQ_SPAMCOUNT) { - lf->expire = getnettime() + RQ_SPAMBLOCK; - - rq_addblock(np->authname, "Flooding the request system.", "request", 0, getnettime() + 3600); - - return 1; - } - - return 0; - } - } -} - -time_t rq_blocktime(nick *np) { - if (np->exts[rqnext] == NULL) - return 0; - else - return ((rq_flood*)np->exts[rqnext])->expire - getnettime(); } rq_block *rq_findblock(const char *pattern) { diff --git a/request/request_block.h b/request/request_block.h index 8a73f898..afca63fb 100644 --- a/request/request_block.h +++ b/request/request_block.h @@ -1,12 +1,6 @@ #include "../nick/nick.h" #include "../channel/channel.h" -typedef struct { - int count; - time_t created; - time_t expire; -} rq_flood; - typedef struct { sstring *pattern; sstring *reason; @@ -21,9 +15,6 @@ extern array rqblocks; #define RQ_BLOCKFILE "data/rqblocks" #define RQ_BLOCKLEN 256 -#define RQ_SPAMCOUNT 5 -#define RQ_SPAMBLOCK 3600 - int rq_initblocks(void); void rq_finiblocks(void); @@ -34,7 +25,3 @@ int rq_saveblocks(void); rq_block *rq_findblock(const char *pattern); void rq_addblock(const char *pattern, const char *reason, const char *creator, time_t created, time_t expires); int rq_removeblock(const char *pattern); - -/* anti-spam blocks */ -int rq_isspam(nick *np); -time_t rq_blocktime(nick *np); diff --git a/request/request_fasttrack.c b/request/request_fasttrack.c new file mode 100644 index 00000000..2378b066 --- /dev/null +++ b/request/request_fasttrack.c @@ -0,0 +1,115 @@ +#include +#include +#include "../core/schedule.h" +#include "../irc/irc.h" +#include "../lib/irc_string.h" +#include "request_fasttrack.h" + +typedef struct rq_fasttrack { + unsigned long userid; + + unsigned int targets; + time_t refill_time; + + struct rq_fasttrack *next; +} rq_fasttrack; + +static rq_fasttrack *ftlist; + +/* our fast-track extension */ +int rqnext; + +static void rq_cleanup_fasttrack(void *arg); +static void rqhook_account(int hook, void *arg); + +int rq_initfasttrack(void) { + rqnext = registernickext("request_fasttrack"); + if(rqnext < 0) + return 0; + + registerhook(HOOK_NICK_NEWNICK, &rqhook_account); + registerhook(HOOK_NICK_ACCOUNT, &rqhook_account); + + schedulerecurring(time(NULL)+1, 0, 3600, rq_cleanup_fasttrack, NULL); + + return 1; +} + +void rq_finifasttrack(void) { + rq_fasttrack *ft; + + deregisterhook(HOOK_NICK_NEWNICK, &rqhook_account); + deregisterhook(HOOK_NICK_ACCOUNT, &rqhook_account); + + for(ft=ftlist;ft;ft=ft->next) + free(ft); + + releasenickext(rqnext); +} + +static void rqhook_account(int hook, void *arg) { + nick *np = (nick *)arg; + rq_fasttrack *ft; + + /* Auth might be null for the newnick hook. */ + if(!np->auth) + return; + + /* Try to find an existing fasttrack record for this user. */ + for(ft=ftlist;ft;ft=ft->next) { + if(np->auth->userid==ft->userid) { + np->exts[rqnext] = ft; + break; + } + } +} + +static void rq_cleanup_fasttrack(void *arg) { + +} + +static rq_fasttrack *rq_getfasttrack(nick *np) { + rq_fasttrack *ft; + + /* Use an existing fast-track record if the nick has one. */ + if(np->exts[rqnext]) + return np->exts[rqnext]; + + if(!np->auth) + return NULL; + + ft = malloc(sizeof(rq_fasttrack)); + + if(!ft) + return NULL; + + ft->userid = np->auth->userid; + ft->targets = 0; + ft->refill_time = 0; + + np->exts[rqnext] = ft; + + return ft; +} + +int rq_tryfasttrack(nick *np) { + rq_fasttrack *ft = rq_getfasttrack(np); + + /* Don't fast-track if we can't find a fast-track record. */ + if(!ft) + return 0; + + /* Refill targets if necessary. */ + if(getnettime() > ft->refill_time) { + ft->targets = RQ_FASTTRACK_TARGETS; + ft->refill_time = getnettime() + RQ_FASTTRACK_TIMEOUT; + } + + /* Check if we have a free target. */ + if(ft->targets==0) + return 0; + + ft->targets--; + return 1; +} + diff --git a/request/request_fasttrack.h b/request/request_fasttrack.h new file mode 100644 index 00000000..77c6d7ec --- /dev/null +++ b/request/request_fasttrack.h @@ -0,0 +1,10 @@ +#include "../nick/nick.h" +#include "../channel/channel.h" + +#define RQ_FASTTRACK_TARGETS 2 +#define RQ_FASTTRACK_TIMEOUT 60 + +int rq_initfasttrack(void); +void rq_finifasttrack(void); + +int rq_tryfasttrack(nick *np); diff --git a/request/sqrequest.c b/request/sqrequest.c index 025be5cc..7ba73f73 100644 --- a/request/sqrequest.c +++ b/request/sqrequest.c @@ -730,21 +730,10 @@ int qr_instantrequestq(nick *sender, channel *cp) { int qr_requests(nick *rqnick, nick *sender, channel *cp, nick *qnick) { chanindex *cip = cp->index; - int who = 0; requestrec *nextreq, *lastreq; - if (rq_isspam(sender)) { - sendnoticetouser(rqnick, sender, "Do not flood the request system." - " Try again in %s.", rq_longtoduration(rq_blocktime(sender))); - - return RQ_ERROR; - } - /* check which service is on the channel */ if (getnumerichandlefromchanhash(cp->users, qnick->numeric) != NULL) { - /* we've found Q */ - who = QR_Q; - /* Request stats from Q */ sendmessagetouser(rqnick, qnick, "CHANLEV %s", cip->name->content);