]> jfr.im git - irc/quakenet/newserv.git/blob - request/request_fasttrack.c
Fix another crash in request_fasttrack.
[irc/quakenet/newserv.git] / request / request_fasttrack.c
1 #include <stdio.h>
2 #include <string.h>
3 #include "../core/schedule.h"
4 #include "../irc/irc.h"
5 #include "../lib/irc_string.h"
6 #include "request_fasttrack.h"
7
8 typedef struct rq_fasttrack {
9 unsigned long userid;
10
11 unsigned int targets;
12 time_t refill_time;
13
14 struct rq_fasttrack *next;
15 } rq_fasttrack;
16
17 static rq_fasttrack *ftlist;
18
19 /* our fast-track extension */
20 int rqnext;
21
22 static void rq_cleanup_fasttrack(void *arg);
23 static void rqhook_account(int hook, void *arg);
24
25 int rq_initfasttrack(void) {
26 rqnext = registernickext("request_fasttrack");
27 if(rqnext < 0)
28 return 0;
29
30 registerhook(HOOK_NICK_NEWNICK, &rqhook_account);
31 registerhook(HOOK_NICK_ACCOUNT, &rqhook_account);
32
33 schedulerecurring(time(NULL)+1, 0, 3600, rq_cleanup_fasttrack, NULL);
34
35 return 1;
36 }
37
38 void rq_finifasttrack(void) {
39 rq_fasttrack *ft, *next;
40
41 deregisterhook(HOOK_NICK_NEWNICK, &rqhook_account);
42 deregisterhook(HOOK_NICK_ACCOUNT, &rqhook_account);
43
44 for(ft=ftlist;ft;) {
45 next = ft->next;
46 free(ft);
47 ft = next;
48 }
49
50 releasenickext(rqnext);
51 }
52
53 static void rqhook_account(int hook, void *arg) {
54 nick *np = (nick *)arg;
55 rq_fasttrack *ft;
56
57 /* Auth might be null for the newnick hook. */
58 if(!np->auth)
59 return;
60
61 /* Try to find an existing fasttrack record for this user. */
62 for(ft=ftlist;ft;ft=ft->next) {
63 if(np->auth->userid==ft->userid) {
64 np->exts[rqnext] = ft;
65 break;
66 }
67 }
68 }
69
70 static void rq_cleanup_fasttrack(void *arg) {
71 time_t now;
72 rq_fasttrack **pft, *ft;
73 int j;
74 nick *tnp;
75
76 now = getnettime();
77
78 for(pft=&ftlist;*pft;pft=&((*pft)->next)) {
79 int foundnick = 0;
80
81 ft = *pft;
82
83 for(j=0;j<NICKHASHSIZE && !foundnick;j++) {
84 for(tnp=nicktable[j];tnp;tnp=tnp->next) {
85 if(tnp->exts[rqnext]==ft) {
86 foundnick = 1;
87 break;
88 }
89 }
90 }
91
92 if(!foundnick && ft->refill_time < now) {
93 *pft = ft->next;
94 free(ft);
95 }
96
97 if (!*pft)
98 break;
99 }
100 }
101
102 static rq_fasttrack *rq_getfasttrack(nick *np) {
103 rq_fasttrack *ft;
104
105 /* Use an existing fast-track record if the nick has one. */
106 if(np->exts[rqnext])
107 return np->exts[rqnext];
108
109 if(!np->auth)
110 return NULL;
111
112 ft = malloc(sizeof(rq_fasttrack));
113
114 if(!ft)
115 return NULL;
116
117 ft->userid = np->auth->userid;
118 ft->targets = 0;
119 ft->refill_time = 0;
120
121 ft->next = ftlist;
122 ftlist = ft;
123
124 np->exts[rqnext] = ft;
125
126 return ft;
127 }
128
129 int rq_tryfasttrack(nick *np) {
130 rq_fasttrack *ft = rq_getfasttrack(np);
131
132 /* Don't fast-track if we can't find a fast-track record. */
133 if(!ft)
134 return 0;
135
136 /* Refill targets if necessary. */
137 if(getnettime() > ft->refill_time) {
138 ft->targets = RQ_FASTTRACK_TARGETS;
139 ft->refill_time = getnettime() + RQ_FASTTRACK_TIMEOUT;
140 }
141
142 /* Check if we have a free target. */
143 if(ft->targets==0)
144 return 0;
145
146 ft->targets--;
147 return 1;
148 }
149