]>
Commit | Line | Data |
---|---|---|
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 | np->exts[rqnext] = NULL; | |
58 | ||
59 | /* Auth might be null for the newnick hook. */ | |
60 | if(!np->auth) | |
61 | return; | |
62 | ||
63 | /* Try to find an existing fasttrack record for this user. */ | |
64 | for(ft=ftlist;ft;ft=ft->next) { | |
65 | if(np->auth->userid==ft->userid) { | |
66 | np->exts[rqnext] = ft; | |
67 | break; | |
68 | } | |
69 | } | |
70 | } | |
71 | ||
72 | static void rq_cleanup_fasttrack(void *arg) { | |
73 | time_t now; | |
74 | rq_fasttrack **pft, *ft; | |
75 | int j; | |
76 | nick *tnp; | |
77 | ||
78 | now = getnettime(); | |
79 | ||
80 | for(pft=&ftlist;*pft;pft=&((*pft)->next)) { | |
81 | int foundnick = 0; | |
82 | ||
83 | ft = *pft; | |
84 | ||
85 | for(j=0;j<NICKHASHSIZE && !foundnick;j++) { | |
86 | for(tnp=nicktable[j];tnp;tnp=tnp->next) { | |
87 | if(tnp->exts[rqnext]==ft) { | |
88 | foundnick = 1; | |
89 | break; | |
90 | } | |
91 | } | |
92 | } | |
93 | ||
94 | if(!foundnick && ft->refill_time < now) { | |
95 | *pft = ft->next; | |
96 | free(ft); | |
97 | } | |
98 | ||
99 | if (!*pft) | |
100 | break; | |
101 | } | |
102 | } | |
103 | ||
104 | static rq_fasttrack *rq_getfasttrack(nick *np) { | |
105 | rq_fasttrack *ft; | |
106 | ||
107 | /* Use an existing fast-track record if the nick has one. */ | |
108 | if(np->exts[rqnext]) | |
109 | return np->exts[rqnext]; | |
110 | ||
111 | if(!np->auth) | |
112 | return NULL; | |
113 | ||
114 | ft = malloc(sizeof(rq_fasttrack)); | |
115 | ||
116 | if(!ft) | |
117 | return NULL; | |
118 | ||
119 | ft->userid = np->auth->userid; | |
120 | ft->targets = 0; | |
121 | ft->refill_time = 0; | |
122 | ||
123 | ft->next = ftlist; | |
124 | ftlist = ft; | |
125 | ||
126 | np->exts[rqnext] = ft; | |
127 | ||
128 | return ft; | |
129 | } | |
130 | ||
131 | int rq_tryfasttrack(nick *np) { | |
132 | rq_fasttrack *ft = rq_getfasttrack(np); | |
133 | ||
134 | /* Don't fast-track if we can't find a fast-track record. */ | |
135 | if(!ft) | |
136 | return 0; | |
137 | ||
138 | /* Refill targets if necessary. */ | |
139 | if(getnettime() > ft->refill_time) { | |
140 | ft->targets = RQ_FASTTRACK_TARGETS; | |
141 | ft->refill_time = getnettime() + RQ_FASTTRACK_TIMEOUT; | |
142 | } | |
143 | ||
144 | /* Check if we have a free target. */ | |
145 | if(ft->targets==0) | |
146 | return 0; | |
147 | ||
148 | ft->targets--; | |
149 | return 1; | |
150 | } | |
151 |