1 /*
2 * Unreal Internet Relay Chat Daemon, src/modules/m_htm.c
3 * (C) 2000-2001 Carsten V. Munk and the UnrealIRCd Team
4 * Moved to modules by Fish (Justin Hammond)
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 1, or (at your option)
9 * any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "config.h"
22 #include "struct.h"
23 #include "common.h"
24 #include "sys.h"
25 #include "numeric.h"
26 #include "msg.h"
27 #include "channel.h"
28 #include <time.h>
29 #include <sys/stat.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #ifdef _WIN32
34 #include <io.h>
35 #endif
36 #include <fcntl.h>
37 #include "h.h"
38 #include "proto.h"
39 #ifdef STRIPBADWORDS
40 #include "badwords.h"
41 #endif
42 #ifdef _WIN32
43 #include "version.h"
44 #endif
45
46
47 DLLFUNC int m_htm(aClient *cptr, aClient *sptr, int parc, char *parv[]);
48 EVENT(lcf_check);
49 EVENT(htm_calc);
50 Event *e_lcf, *e_htmcalc;
51
52 /* Place includes here */
53 #define MSG_HTM "HTM"
54 #define TOK_HTM "BH"
55
56 DLLFUNC int htm_config_test(ConfigFile *, ConfigEntry *, int, int *);
57 DLLFUNC int htm_config_run(ConfigFile *, ConfigEntry *, int);
58 DLLFUNC int htm_stats(aClient *, char *);
59
60 ModuleInfo *HtmModInfo;
61 static Hook *ConfTest, *ConfRun, *ServerStats;
62
63 ModuleHeader MOD_HEADER(m_htm)
64 = {
65 "htm", /* Name of module */
66 "$Id$", /* Version */
67 "command /htm", /* Short description of module */
68 "3.2-b8-1",
69 NULL
70 };
71
MOD_TEST(m_htm)72 DLLFUNC int MOD_TEST(m_htm)(ModuleInfo *modinfo)
73 {
74 /*
75 * We call our add_Command crap here
76 */
77 HtmModInfo = modinfo;
78 ConfTest = HookAddEx(HtmModInfo->handle, HOOKTYPE_CONFIGTEST, htm_config_test);
79 return MOD_SUCCESS;
80 }
81
82
83 /* This is called on module init, before Server Ready */
MOD_INIT(m_htm)84 DLLFUNC int MOD_INIT(m_htm)(ModuleInfo *modinfo)
85 {
86 /*
87 * We call our add_Command crap here
88 */
89 add_Command(MSG_HTM, TOK_HTM, m_htm, MAXPARA);
90 ConfRun = HookAddEx(HtmModInfo->handle, HOOKTYPE_CONFIGRUN, htm_config_run);
91 ServerStats = HookAddEx(HtmModInfo->handle, HOOKTYPE_STATS, htm_stats);
92 #ifndef NO_FDLIST
93 LockEventSystem();
94 e_lcf = EventAddEx(HtmModInfo->handle, "lcf", LCF, 0, lcf_check, NULL);
95 e_htmcalc = EventAddEx(HtmModInfo->handle, "htmcalc", 1, 0, htm_calc, NULL);
96 UnlockEventSystem();
97 #endif
98 MARK_AS_OFFICIAL_MODULE(modinfo);
99 return MOD_SUCCESS;
100 }
101
102 /* Is first run when server is 100% ready */
MOD_LOAD(m_htm)103 DLLFUNC int MOD_LOAD(m_htm)(int module_load)
104 {
105 return MOD_SUCCESS;
106 }
107
108
109 /* Called when module is unloaded */
MOD_UNLOAD(m_htm)110 DLLFUNC int MOD_UNLOAD(m_htm)(int module_unload)
111 {
112 if (del_Command(MSG_HTM, TOK_HTM, m_htm) < 0)
113 {
114 sendto_realops("Failed to delete commands when unloading %s",
115 MOD_HEADER(m_htm).name);
116 }
117 #ifndef NO_FDLIST
118 LockEventSystem();
119 EventDel(e_lcf);
120 EventDel(e_htmcalc);
121 UnlockEventSystem();
122 #endif
123 return MOD_SUCCESS;
124 }
125
126 /* m_htm recoded by griever
127 parameters
128
129 HTM [server] [command] [param]
130 */
131
m_htm(aClient * cptr,aClient * sptr,int parc,char * parv[])132 DLLFUNC int m_htm(aClient *cptr, aClient *sptr, int parc, char *parv[])
133 {
134 int x = HUNTED_NOSUCH;
135 char *command, *param;
136 if (!IsOper(sptr))
137 {
138 sendto_one(sptr, err_str(ERR_NOPRIVILEGES), me.name, sptr->name);
139 return 0;
140 }
141
142 switch(parc) {
143 case 1:
144 break;
145 case 2:
146 x = hunt_server_token_quiet(cptr, sptr, MSG_HTM, TOK_HTM, "%s", 1, parc, parv);
147 break;
148 case 3:
149 x = hunt_server_token_quiet(cptr, sptr, MSG_HTM, TOK_HTM, "%s %s", 1, parc, parv);
150 break;
151 default:
152 x = hunt_server_token_quiet(cptr, sptr, MSG_HTM, TOK_HTM, "%s %s %s", 1, parc, parv);
153 }
154
155 switch (x) {
156 case HUNTED_NOSUCH:
157 command = (parv[1]);
158 param = (parv[2]);
159 break;
160 case HUNTED_ISME:
161 command = (parv[2]);
162 param = (parv[3]);
163 break;
164 default:
165 return 0;
166 }
167
168 #ifndef NO_FDLIST
169
170 if (!command)
171 {
172 sendto_one(sptr,
173 ":%s NOTICE %s :*** Current incoming rate: %0.2f kb/s",
174 me.name, parv[0], currentrate);
175 sendto_one(sptr,
176 ":%s NOTICE %s :*** Current outgoing rate: %0.2f kb/s",
177 me.name, parv[0], currentrate2);
178 sendto_one(sptr,
179 ":%s NOTICE %s :*** Highest incoming rate: %0.2f kb/s",
180 me.name, parv[0], highest_rate);
181 sendto_one(sptr,
182 ":%s NOTICE %s :*** Highest outgoing rate: %0.2f kb/s",
183 me.name, parv[0], highest_rate2);
184 sendto_one(sptr,
185 ":%s NOTICE %s :*** High traffic mode is currently \2%s\2",
186 me.name, parv[0], (lifesux ? "ON" : "OFF"));
187 sendto_one(sptr,
188 ":%s NOTICE %s :*** High traffic mode is currently in \2%s\2 mode",
189 me.name, parv[0], (noisy_htm ? "NOISY" : "QUIET"));
190 sendto_one(sptr,
191 ":%s NOTICE %s :*** HTM will be activated if incoming > %i kb/s",
192 me.name, parv[0], LRV);
193 }
194
195 else
196 {
197 if (!stricmp(command, "ON"))
198 {
199 EventInfo mod;
200 lifesux = 1;
201 sendto_one(sptr,
202 ":%s NOTICE %s :High traffic mode is now ON.",
203 me.name, parv[0]);
204 sendto_ops
205 ("%s (%s@%s) forced High traffic mode to activate",
206 parv[0], sptr->user->username,
207 GetHost(sptr));
208 LCF = 60; /* 60 seconds */
209 mod.flags = EMOD_EVERY;
210 mod.every = LCF;
211 LockEventSystem();
212 EventMod(e_lcf, &mod);
213 UnlockEventSystem();
214 }
215 else if (!stricmp(command, "OFF"))
216 {
217 EventInfo mod;
218 lifesux = 0;
219 LCF = LOADCFREQ;
220 mod.flags = EMOD_EVERY;
221 mod.every = LCF;
222 LockEventSystem();
223 EventMod(e_lcf, &mod);
224 UnlockEventSystem();
225 sendto_one(sptr,
226 ":%s NOTICE %s :High traffic mode is now OFF.",
227 me.name, parv[0]);
228 sendto_ops
229 ("%s (%s@%s) forced High traffic mode to deactivate",
230 parv[0], sptr->user->username,
231 GetHost(sptr));
232 }
233 else if (!stricmp(command, "TO"))
234 {
235 if (!param)
236 sendto_one(sptr,
237 ":%s NOTICE %s :You must specify an integer value",
238 me.name, parv[0]);
239 else
240 {
241 int new_val = atoi(param);
242 if (new_val < 10)
243 sendto_one(sptr,
244 ":%s NOTICE %s :New value must be > 10",
245 me.name, parv[0]);
246 else
247 {
248 LRV = new_val;
249 sendto_one(sptr,
250 ":%s NOTICE %s :New max rate is %dkb/s",
251 me.name, parv[0], LRV);
252 sendto_ops
253 ("%s (%s@%s) changed the High traffic mode max rate to %dkb/s",
254 parv[0], sptr->user->username,
255 GetHost(sptr), LRV);
256 }
257 }
258 }
259 else if (!stricmp(command, "QUIET"))
260 {
261 noisy_htm = 0;
262 sendto_one(sptr,
263 ":%s NOTICE %s :High traffic mode is now QUIET",
264 me.name, parv[0]);
265 sendto_ops("%s (%s@%s) set High traffic mode to QUIET",
266 parv[0], sptr->user->username,
267 GetHost(sptr));
268 }
269
270 else if (!stricmp(command, "NOISY"))
271 {
272 noisy_htm = 1;
273 sendto_one(sptr,
274 ":%s NOTICE %s :High traffic mode is now NOISY",
275 me.name, parv[0]);
276 sendto_ops("%s (%s@%s) set High traffic mode to NOISY",
277 parv[0], sptr->user->username,
278 GetHost(sptr));
279 }
280 else
281 sendto_one(sptr, ":%s NOTICE %s :Unknown option: %s",
282 me.name, parv[0], command);
283 }
284
285
286 #else
287 sendto_one(sptr,
288 ":%s NOTICE %s :*** High traffic mode and fdlists are not enabled on this server",
289 me.name, sptr->name);
290 #endif
291 return 0;
292 }
293
294 #ifndef NO_FDLIST
295
EVENT(lcf_check)296 EVENT(lcf_check)
297 {
298 static int lrv;
299
300 lrv = LRV * LCF;
301 if ((me.receiveK - lrv >= lastrecvK) || HTMLOCK == 1)
302 {
303 if (!lifesux)
304 {
305
306 lifesux = 1;
307 if (noisy_htm)
308 sendto_realops
309 ("Entering high-traffic mode (incoming = %0.2f kb/s (LRV = %dk/s, outgoing = %0.2f kb/s currently)",
310 currentrate, LRV,
311 currentrate2);}
312 else
313 {
314 EventInfo mod;
315 lifesux++; /* Ok, life really sucks! */
316 LCF += 2; /* wait even longer */
317 mod.flags = EMOD_EVERY;
318 mod.every = LCF;
319 EventMod(e_lcf, &mod);
320 if (noisy_htm)
321 sendto_realops
322 ("Still high-traffic mode %d%s (%d delay): %0.2f kb/s",
323 lifesux,
324 (lifesux >
325 9) ? " (TURBO)" :
326 "", (int)LCF, currentrate);
327 /* Reset htm here, because its been on a little too long.
328 * Bad Things(tm) tend to happen with HTM on too long -epi */
329 if (lifesux > 15)
330 {
331 EventInfo mod;
332 if (noisy_htm)
333 sendto_realops
334 ("Resetting HTM and raising limit to: %dk/s\n",
335 LRV + 5);
336 LCF = LOADCFREQ;
337 mod.flags = EMOD_EVERY;
338 mod.every = LCF;
339 EventMod(e_lcf, &mod);
340 lifesux = 0;
341 LRV += 5;
342 }
343 }
344 }
345 else
346 {
347 EventInfo mod;
348 LCF = LOADCFREQ;
349 mod.flags = EMOD_EVERY;
350 mod.every = LCF;
351 EventMod(e_lcf, &mod);
352 if (lifesux)
353 {
354 lifesux = 0;
355 if (noisy_htm)
356 sendto_realops
357 ("Resuming standard operation (incoming = %0.2f kb/s, outgoing = %0.2f kb/s now)",
358 currentrate, currentrate2);
359 }
360 }
361 }
362
EVENT(htm_calc)363 EVENT(htm_calc)
364 {
365 static time_t last = 0;
366 if (last == 0)
367 last = TStime();
368
369 if (timeofday - last == 0)
370 return;
371
372 currentrate =
373 ((float)(me.receiveK -
374 lastrecvK)) / ((float)(timeofday - last));
375 currentrate2 =
376 ((float)(me.sendK -
377 lastsendK)) / ((float)(timeofday - last));
378 if (currentrate > highest_rate)
379 highest_rate = currentrate;
380 if (currentrate2 > highest_rate2)
381 highest_rate2 = currentrate2;
382 last = TStime();
383 }
384 #endif
385
htm_config_test(ConfigFile * cf,ConfigEntry * ce,int type,int * errs)386 DLLFUNC int htm_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs) {
387 ConfigEntry *cep;
388 int errors = 0;
389
390 if (type != CONFIG_SET)
391 return 0;
392
393 if (!strcmp(ce->ce_varname, "htm"))
394 {
395 for (cep = ce->ce_entries; cep; cep = cep->ce_next)
396 {
397 if (!cep->ce_varname)
398 {
399 config_error("%s:%i: blank set::htm item",
400 cep->ce_fileptr->cf_filename,
401 cep->ce_varlinenum);
402 errors++;
403 continue;
404 }
405 if (!cep->ce_vardata)
406 {
407 config_error("%s:%i: set::htm::%s item without value",
408 cep->ce_fileptr->cf_filename,
409 cep->ce_varlinenum, cep->ce_varname);
410 errors++;
411 continue;
412 }
413 if (!strcmp(cep->ce_varname, "mode"))
414 {
415
416 if (stricmp(cep->ce_vardata, "noisy") && stricmp(cep->ce_vardata, "quiet"))
417 {
418 config_error("%s%i: set::htm::mode: illegal mode",
419 cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
420 errors++;
421 }
422 }
423 else if (!strcmp(cep->ce_varname, "incoming-rate"))
424 {
425 int value = config_checkval(cep->ce_vardata, CFG_SIZE);
426 if (value < 10240)
427 {
428 config_error("%s%i: set::htm::incoming-rate: must be at least 10kb",
429 cep->ce_fileptr->cf_filename, cep->ce_varlinenum);
430 errors++;
431 }
432 }
433 else
434 {
435 config_error("%s:%i: unknown directive set::htm::%s",
436 cep->ce_fileptr->cf_filename, cep->ce_varlinenum,
437 cep->ce_varname);
438 errors++;
439 }
440
441 }
442 *errs = errors;
443 return errors ? -1 : 1;
444 }
445 else
446 return 0;
447 }
448
htm_config_run(ConfigFile * cf,ConfigEntry * ce,int type)449 DLLFUNC int htm_config_run(ConfigFile *cf, ConfigEntry *ce, int type) {
450 ConfigEntry *cep;
451
452 if (type != CONFIG_SET)
453 return 0;
454 if (!strcmp(ce->ce_varname, "htm"))
455 {
456 for (cep = ce->ce_entries; cep; cep = cep->ce_next)
457 {
458 if (!strcmp(cep->ce_varname, "mode"))
459 {
460 if (!stricmp(cep->ce_vardata, "noisy"))
461 noisy_htm = 1;
462 else
463 noisy_htm = 0;
464 }
465 else if (!strcmp(cep->ce_varname, "incoming-rate"))
466 {
467 LRV = config_checkval(cep->ce_vardata, CFG_SIZE);
468 LRV /= 1024;
469 }
470 }
471 return 1;
472 }
473 return 0;
474 }
475
htm_stats(aClient * sptr,char * stats)476 DLLFUNC int htm_stats(aClient *sptr, char *stats) {
477 if (*stats == 'S') {
478 sendto_one(sptr, ":%s %i %s :htm::mode: %s", me.name, RPL_TEXT,
479 sptr->name, noisy_htm ? "noisy" : "quiet");
480 sendto_one(sptr, ":%s %i %s :htm::incoming-rate: %d kb/s", me.name, RPL_TEXT,
481 sptr->name, LRV);
482 }
483 return 0;
484 }
485