1 |
/* Copyright (C) 2003, 2004 Stephane Thiell |
2 |
* |
3 |
* This file is part of pxyservd (from pxys) |
4 |
* |
5 |
* This program is free software; you can redistribute it and/or |
6 |
* modify it under the terms of the GNU General Public License |
7 |
* as published by the Free Software Foundation; either version 2 |
8 |
* of the License, or (at your option) any later version. |
9 |
* |
10 |
* This program is distributed in the hope that it will be useful, |
11 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 |
* GNU General Public License for more details. |
14 |
* |
15 |
* You should have received a copy of the GNU General Public License |
16 |
* along with this program; if not, write to the Free Software |
17 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
18 |
* |
19 |
*/ |
20 |
#define RCSID "$Id: irc_gline.c,v 1.2 2004/01/10 14:32:29 mbuna Exp $" |
21 |
|
22 |
#ifdef HAVE_CONFIG_H |
23 |
#include "config.h" |
24 |
#endif |
25 |
|
26 |
#ifndef MAX_GLINEQ_ELEMS |
27 |
#define MAX_GLINEQ_ELEMS 500 |
28 |
#endif |
29 |
|
30 |
#define GLINE_PREFIX "AUTO " |
31 |
|
32 |
#include "irc_gline.h" |
33 |
#include "pxyservd_log.h" |
34 |
|
35 |
#include <assert.h> |
36 |
#include <stdlib.h> |
37 |
#include <unistd.h> |
38 |
|
39 |
#include <peak/peak.h> |
40 |
#include <arpa/inet.h> |
41 |
|
42 |
#include "cfgloader.h" |
43 |
#include "glineq.h" |
44 |
#include "irc_send.h" |
45 |
#include "irc_userbase.h" |
46 |
|
47 |
/* This module contains a transparent glines rate limiter to avoid flooding |
48 |
* our hub. It uses glineq to queue the glines, and a libpeak's timer to |
49 |
* delay sendings. |
50 |
*/ |
51 |
|
52 |
static void irc_gline_timer_callback(peak_timer ti, void *context); |
53 |
static peak_timer gti; |
54 |
|
55 |
void |
56 |
irc_gline_init() |
57 |
{ |
58 |
glineq_init(MAX_GLINEQ_ELEMS); |
59 |
|
60 |
gti = peak_timer_create(-1, -1, irc_gline_timer_callback, NULL); |
61 |
peak_task_timer_add(peak_task_self(), gti); |
62 |
peak_release(gti); |
63 |
} |
64 |
|
65 |
void |
66 |
irc_gline_finalize() |
67 |
{ |
68 |
peak_task_timer_remove(peak_task_self(), gti); |
69 |
glineq_finalize(); |
70 |
} |
71 |
|
72 |
static void |
73 |
irc_gline_timer_callback(peak_timer ti, void *context) |
74 |
{ |
75 |
if (glineq_empty()) |
76 |
{ |
77 |
peak_timer_configure(gti, -1, -1); /* Off */ |
78 |
} |
79 |
else |
80 |
{ |
81 |
const struct g_args *ap = glineq_first(); |
82 |
assert(ap != NULL); |
83 |
|
84 |
log_write(LOGID_GLINES, "+*@%s %ld :" GLINE_PREFIX "[%ld] %s", |
85 |
inet_ntoa(ap->addr), gConfig->gline.delay, |
86 |
ap->hitcnt, ap->reason); |
87 |
|
88 |
send_gline(ap->addr, gConfig->gline.delay, GLINE_PREFIX "[%ld] %s", |
89 |
ap->hitcnt, ap->reason); |
90 |
|
91 |
glineq_pop(); |
92 |
} |
93 |
} |
94 |
|
95 |
void |
96 |
irc_gline_send(const struct in_addr *addr, int hitcnt, const char *reason) |
97 |
{ |
98 |
struct g_args args; |
99 |
double ft; |
100 |
|
101 |
args.addr = *addr; |
102 |
args.hitcnt = hitcnt; |
103 |
args.reason = reason; |
104 |
|
105 |
ft = peak_timer_get_firetime(gti); |
106 |
|
107 |
if (glineq_push(&args) == -1) |
108 |
{ |
109 |
/* Ugh !! */ |
110 |
log_system("irc_gline_send: max glineQ exceeded! (delay: %fs -> %fs)", |
111 |
ft, ft / 2.0); |
112 |
peak_timer_configure(gti, 0, ft / 2.0); |
113 |
|
114 |
/* no choice but to call out */ |
115 |
irc_gline_timer_callback(gti, NULL); |
116 |
glineq_push(&args); |
117 |
} |
118 |
|
119 |
if (ft > peak_time() + 10.0) /* not configured ? */ |
120 |
peak_timer_configure(gti, 0, 0.5); /* Fire ASAP with 0.5s repeating */ |
121 |
} |