#include <eggdrop/eggdrop.h>
#include "chanserv.h"
Go to the source code of this file.
Functions | |
static int | chanserv_timer (void *client_data) |
EXPORT_SCOPE int | chanserv_LTX_start (egg_module_t *modinfo) |
static int | chanserv_close (int why) |
static int | on_chanset (const char *chan, const char *setting, const char *oldvalue, const char *newvalue) |
static int | chanserv_init () |
static int | chanserv_shutdown () |
int | chanserv_refresh_channel_config (void *client_data) |
chanserv_channel_stats_t * | chanserv_probe_chan (const char *chan, int create) |
chanserv_member_stats_t * | chanserv_probe_member (chanserv_channel_stats_t *chan, const char *nick, const char *uhost, int create) |
int | chanserv_lookup_config (const char *chan, int stat, int *limit, int *period) |
int | chanserv_update_stats (int stat, const char *chan, const char *nick, const char *uhost) |
static int | cleanup_old_members (chanserv_channel_stats_t *chan) |
static int | free_channel (chanserv_channel_stats_t *chan) |
Variables | |
static const char | rcsid [] = "$Id: chanserv.c,v 1.6 2005-12-28 17:27:31 sven Exp $" |
chanserv_config_t | chanserv_config |
egg_server_api_t * | server = NULL |
static chanserv_channel_stats_t | global_chan |
static int | timer_id |
static event_owner_t | chanserv_owner |
static const char * | channel_config_names [] |
static config_var_t | chanserv_config_vars [] |
static chanserv_channel_stats_t * | chanstats_head = NULL |
static bind_table_t * | BT_chanflood = NULL |
static bind_table_t * | BT_memflood = NULL |
static int chanserv_close | ( | int | why | ) | [static] |
Definition at line 344 of file chanserv.c.
References chanserv_shutdown(), config_get_root(), config_root, config_unlink_table(), and NULL.
Referenced by chanserv_LTX_start().
00345 { 00346 void *config_root; 00347 00348 chanserv_shutdown(); 00349 config_root = config_get_root("eggdrop"); 00350 config_unlink_table(chanserv_config_vars, config_root, "chanserv", 0, NULL); 00351 return(0); 00352 }
static int chanserv_init | ( | ) | [static] |
Definition at line 90 of file chanserv.c.
References bind_add_simple(), BIND_STACKABLE, bind_table_add(), CHANSERV_CLEANUP_TIMER, chanserv_timer(), events_init, MATCH_MASK, module_get_api(), NULL, on_chanset(), egg_timeval::sec, timer_create_complex(), timer_id, TIMER_REPEAT, and egg_timeval::usec.
Referenced by chanserv_LTX_start().
00091 { 00092 egg_timeval_t howlong; 00093 00094 memset(&global_chan, 0, sizeof(global_chan)); 00095 BT_chanflood = bind_table_add("chanflood", 5, "ssiii", MATCH_MASK, BIND_STACKABLE); 00096 BT_memflood = bind_table_add("memflood", 7, "ssssiii", MATCH_MASK, BIND_STACKABLE); 00097 server = module_get_api("server", 1, 0); 00098 bind_add_simple("chanset", NULL, "settings.chanserv.*", on_chanset); 00099 events_init(); 00100 howlong.sec = CHANSERV_CLEANUP_TIMER; 00101 howlong.usec = 0; 00102 timer_id = timer_create_complex(&howlong, "chanserv stats cleanup", chanserv_timer, NULL, TIMER_REPEAT, &chanserv_owner); 00103 return(0); 00104 }
int chanserv_lookup_config | ( | const char * | chan, | |
int | stat, | |||
int * | limit, | |||
int * | period | |||
) |
Definition at line 195 of file chanserv.c.
References chanserv_config_t::channel_limits, chanserv_config_t::channel_periods, chanserv_probe_chan, chanserv_channel_stats::limits, and chanserv_channel_stats::periods.
00196 { 00197 chanserv_channel_stats_t *chanstats; 00198 00199 chanstats = chanserv_probe_chan(chan, 1); 00200 if (limit) { 00201 *limit = chanstats->limits[stat]; 00202 if (*limit < 0) *limit = chanserv_config.channel_limits[stat]; 00203 } 00204 if (period) { 00205 *period = chanstats->periods[stat]; 00206 if (*period < 0) *period = chanserv_config.channel_periods[stat]; 00207 } 00208 return(0); 00209 }
int chanserv_LTX_start | ( | egg_module_t * | modinfo | ) |
Definition at line 354 of file chanserv.c.
References egg_module::author, chanserv_close(), chanserv_init(), egg_module::close_func, config_get_root(), config_link_table(), config_root, config_update_table(), egg_module::description, event_owner_b::module, egg_module::name, NULL, and egg_module::version.
00355 { 00356 void *config_root; 00357 00358 chanserv_owner.module = modinfo; 00359 00360 modinfo->name = "chanserv"; 00361 modinfo->author = "eggdev"; 00362 modinfo->version = "1.0.0"; 00363 modinfo->description = "channel services"; 00364 modinfo->close_func = chanserv_close; 00365 00366 /* Set defaults. */ 00367 memset(&chanserv_config, 0, sizeof(chanserv_config)); 00368 00369 /* Link our vars in. */ 00370 config_root = config_get_root("eggdrop"); 00371 config_link_table(chanserv_config_vars, config_root, "chanserv", 0, NULL); 00372 config_update_table(chanserv_config_vars, config_root, "chanserv", 0, NULL); 00373 00374 chanserv_init(); 00375 return(0); 00376 }
chanserv_channel_stats_t* chanserv_probe_chan | ( | const char * | chan, | |
int | create | |||
) |
Definition at line 147 of file chanserv.c.
References chanserv_refresh_channel_config, chanserv_channel_stats::name, chanserv_channel_stats::next, NULL, and chanserv_channel_stats::prev.
00148 { 00149 chanserv_channel_stats_t *chanstats, *prev; 00150 00151 prev = NULL; 00152 for (chanstats = chanstats_head; chanstats; chanstats = chanstats->next) { 00153 if (!strcasecmp(chanstats->name, chan)) return(chanstats); 00154 prev = chanstats; 00155 } 00156 if (!create) return(NULL); 00157 00158 /* Create new channel. */ 00159 chanstats = calloc(1, sizeof(*chanstats)); 00160 chanstats->name = strdup(chan); 00161 chanserv_refresh_channel_config(chanstats); 00162 00163 if (prev) prev->next = chanstats; 00164 else chanstats_head = chanstats; 00165 chanstats->prev = prev; 00166 return(chanstats); 00167 }
chanserv_member_stats_t* chanserv_probe_member | ( | chanserv_channel_stats_t * | chan, | |
const char * | nick, | |||
const char * | uhost, | |||
int | create | |||
) |
Definition at line 169 of file chanserv.c.
References egg_msprintf(), ircmask_create(), chanserv_channel_stats::members, chanserv_channel_stats::nmembers, NULL, chanserv_member_stats_t::who, and wild_match().
00170 { 00171 char *who, buf[256]; 00172 int i; 00173 00174 if (!chan) chan = &global_chan; 00175 00176 who = egg_msprintf(buf, sizeof(buf), NULL, "%s!%s", nick, uhost); 00177 00178 for (i = 0; i < chan->nmembers; i++) { 00179 if (wild_match(chan->members[i].who, who)) { 00180 if (who != buf) free(who); 00181 return(chan->members+i); 00182 } 00183 } 00184 if (who != buf) free(who); 00185 if (!create) return(NULL); 00186 00187 /* Add new member. */ 00188 chan->members = realloc(chan->members, sizeof(*chan->members) * (chan->nmembers+1)); 00189 chan->nmembers++; 00190 memset(chan->members+i, 0, sizeof(*chan->members)); 00191 chan->members[i].who = ircmask_create(5, nick, uhost); 00192 return(chan->members+i); 00193 }
int chanserv_refresh_channel_config | ( | void * | client_data | ) |
Definition at line 114 of file chanserv.c.
References channel_config_names, egg_server_api_t::channel_get_int, egg_server_api_t::channel_lookup, CHANSERV_STAT_LEN, chanserv_channel_stats::limits, chanserv_channel_stats::name, NULL, chanserv_channel_stats::periods, and chanserv_channel_stats::stats.
00115 { 00116 chanserv_channel_stats_t *chanstats = client_data; 00117 channel_t *chan = server->channel_lookup(chanstats->name); 00118 int i, setting; 00119 00120 if (!chan) return(0); 00121 for (i = 0; i < CHANSERV_STAT_LEN; i++) { 00122 /* If the setting isn't found, default to -1, which means 00123 * we use the global default. This happens when a channel 00124 * is created. */ 00125 if (server->channel_get_int(chan, &setting, "chanserv", 0, channel_config_names[i], 0, "period", 0, NULL)) setting = -1; 00126 00127 /* If the period changes, we clear the stats. */ 00128 if (setting != chanstats->periods[i]) { 00129 chanstats->periods[i] = setting; 00130 chanstats->stats[i] = 0; 00131 } 00132 00133 if (server->channel_get_int(chan, &setting, "chanserv", 0, channel_config_names[i], 0, "limit", 0, NULL)) setting = -1; 00134 chanstats->limits[i] = setting; 00135 } 00136 00137 return(0); 00138 }
static int chanserv_shutdown | ( | ) | [static] |
Definition at line 106 of file chanserv.c.
References bind_table_del(), and events_shutdown.
Referenced by chanserv_close().
00107 { 00108 bind_table_del(BT_chanflood); 00109 bind_table_del(BT_memflood); 00110 events_shutdown(); 00111 return(0); 00112 }
static int chanserv_timer | ( | void * | client_data | ) | [static] |
Definition at line 331 of file chanserv.c.
References egg_server_api_t::channel_lookup, cleanup_old_members(), free_channel(), chanserv_channel_stats::name, and chanserv_channel_stats::next.
Referenced by chanserv_init().
00332 { 00333 chanserv_channel_stats_t *chan, *next; 00334 00335 for (chan = chanstats_head; chan; chan = next) { 00336 next = chan->next; 00337 if (!server->channel_lookup(chan->name)) free_channel(chan); 00338 else cleanup_old_members(chan); 00339 } 00340 cleanup_old_members(&global_chan); 00341 return(0); 00342 }
int chanserv_update_stats | ( | int | stat, | |
const char * | chan, | |||
const char * | nick, | |||
const char * | uhost | |||
) |
Definition at line 211 of file chanserv.c.
References bind_check(), channel_config_names, chanserv_config_t::channel_limits, chanserv_config_t::channel_periods, chanserv_probe_chan, chanserv_probe_member, CHANSERV_STAT_CYCLE, CHANSERV_STAT_JOIN, CHANSERV_STAT_LEAVE, CHANSERV_STAT_LEN, chanserv_update_stats, chanserv_config_t::cycle_time, chanserv_member_stats_t::last_event, chanserv_member_stats_t::last_event_time, chanserv_channel_stats::last_event_time, chanserv_channel_stats::limits, now, NULL, chanserv_channel_stats::periods, chanserv_member_stats_t::stats, chanserv_channel_stats::stats, and timer_get_now_sec().
00212 { 00213 chanserv_channel_stats_t *chanstats = NULL; 00214 chanserv_member_stats_t *m = NULL; 00215 int period, limit; 00216 time_t now; 00217 int diff; 00218 00219 if (stat < 0 || stat >= CHANSERV_STAT_LEN) return(-1); 00220 if (!nick || !uhost) return(-1); 00221 00222 if (chan) chanstats = chanserv_probe_chan(chan, 1); 00223 m = chanserv_probe_member(chanstats, nick, uhost, 1); 00224 if (!m) return(-1); 00225 00226 /* Take care of channel stats first. */ 00227 00228 now = timer_get_now_sec(NULL); 00229 00230 if (chanstats) { 00231 /* Figure out the period and limit for this stat. */ 00232 period = chanstats->periods[stat]; 00233 if (period < 0) period = chanserv_config.channel_periods[stat]; 00234 if (period > 0) { 00235 limit = chanstats->limits[stat]; 00236 if (limit < 0) limit = chanserv_config.channel_limits[stat]; 00237 00238 /* Adjust stats for time difference of this event 00239 * relative to the last one. */ 00240 diff = now - chanstats->last_event_time[stat]; 00241 if (diff > period) { 00242 chanstats->last_event_time[stat] = now; 00243 chanstats->stats[stat] = 0; 00244 diff = 0; 00245 } 00246 chanstats->stats[stat]++; 00247 00248 if (chanstats->stats[stat] > limit) { 00249 bind_check(BT_chanflood, NULL, channel_config_names[stat], channel_config_names[stat], chan, limit, period, diff); 00250 chanstats->last_event_time[stat] = now; 00251 chanstats->stats[stat] = 0; 00252 } 00253 } 00254 } 00255 00256 /* Now update member stats. */ 00257 if (m) { 00258 m->last_event = now; 00259 /* Figure out the period and limit for this stat. */ 00260 period = global_chan.periods[stat]; 00261 if (period > 0) { 00262 limit = global_chan.limits[stat]; 00263 00264 /* Adjust stats for time difference of this event 00265 * relative to the last one. */ 00266 diff = now - m->last_event_time[stat]; 00267 if (diff > period) { 00268 m->last_event_time[stat] = now; 00269 m->stats[stat] = 0; 00270 diff = 0; 00271 } 00272 m->stats[stat]++; 00273 00274 if (m->stats[stat] > limit) { 00275 bind_check(BT_memflood, NULL, channel_config_names[stat], channel_config_names[stat], chan, nick, uhost, limit, period, diff); 00276 m->last_event_time[stat] = now; 00277 m->stats[stat] = 0; 00278 } 00279 } 00280 00281 switch (stat) { 00282 case CHANSERV_STAT_LEAVE: 00283 if (now - m->last_event_time[CHANSERV_STAT_JOIN] < chanserv_config.cycle_time) { 00284 chanserv_update_stats(CHANSERV_STAT_CYCLE, chan, nick, uhost); 00285 } 00286 break; 00287 } 00288 } 00289 return(0); 00290 }
static int cleanup_old_members | ( | chanserv_channel_stats_t * | chan | ) | [static] |
Definition at line 293 of file chanserv.c.
References CHANSERV_CLEANUP_TIME, chanserv_member_stats_t::last_event, chanserv_channel_stats::members, chanserv_channel_stats::nmembers, now, NULL, timer_get_now_sec(), and chanserv_member_stats_t::who.
Referenced by chanserv_timer().
00294 { 00295 chanserv_member_stats_t *m; 00296 time_t now; 00297 int i; 00298 00299 now = timer_get_now_sec(NULL); 00300 00301 for (i = 0; i < chan->nmembers; i++) { 00302 m = chan->members+i; 00303 if (now - m->last_event > CHANSERV_CLEANUP_TIME) { 00304 free(m->who); 00305 memmove(chan->members+i, chan->members+i+1, sizeof(*chan->members)*(chan->nmembers-i-1)); 00306 chan->nmembers--; 00307 i--; 00308 } 00309 } 00310 return(0); 00311 }
static int free_channel | ( | chanserv_channel_stats_t * | chan | ) | [static] |
Definition at line 313 of file chanserv.c.
References LOG_MISC, chanserv_channel_stats::members, chanserv_channel_stats::name, chanserv_channel_stats::next, chanserv_channel_stats::nmembers, chanserv_channel_stats::prev, putlog(), and chanserv_member_stats_t::who.
Referenced by chanserv_timer().
00314 { 00315 int i; 00316 00317 /* ###### test to make sure this gets called properly, remove later */ 00318 putlog(LOG_MISC, "*", "chanserv: freeing channel '%s'", chan->name); 00319 free(chan->name); 00320 for (i = 0; i < chan->nmembers; i++) { 00321 free(chan->members[i].who); 00322 } 00323 free(chan->members); 00324 if (chan->prev) chan->prev->next = chan->next; 00325 else chanstats_head = chan->next; 00326 if (chan->next) chan->next->prev = chan->prev; 00327 free(chan); 00328 return(0); 00329 }
static int on_chanset | ( | const char * | chan, | |
const char * | setting, | |||
const char * | oldvalue, | |||
const char * | newvalue | |||
) | [static] |
Definition at line 140 of file chanserv.c.
References chanserv_probe_chan, chanserv_refresh_channel_config, garbage_add(), and GARBAGE_ONCE.
Referenced by chanserv_init().
00141 { 00142 chanserv_channel_stats_t *chanstats = chanserv_probe_chan(chan, 1); 00143 garbage_add(chanserv_refresh_channel_config, chanstats, GARBAGE_ONCE); 00144 return(0); 00145 }
bind_table_t* BT_chanflood = NULL [static] |
Definition at line 83 of file chanserv.c.
bind_table_t* BT_memflood = NULL [static] |
Definition at line 84 of file chanserv.c.
const char* channel_config_names[] [static] |
Initial value:
{ "join", "part", "quit", "cycle", "leave", "ctcp", "msg", "notice", "line", "nick", "kick", "mode", "modefight", "topic" }
Definition at line 41 of file chanserv.c.
Referenced by chanserv_refresh_channel_config(), and chanserv_update_stats().
Definition at line 28 of file chanserv.c.
config_var_t chanserv_config_vars[] [static] |
Definition at line 47 of file chanserv.c.
event_owner_t chanserv_owner [static] |
chanserv_channel_stats_t* chanstats_head = NULL [static] |
Definition at line 82 of file chanserv.c.
chanserv_channel_stats_t global_chan [static] |
Definition at line 30 of file chanserv.c.
const char rcsid[] = "$Id: chanserv.c,v 1.6 2005-12-28 17:27:31 sven Exp $" [static] |
Definition at line 21 of file chanserv.c.
egg_server_api_t* server = NULL |
Definition at line 29 of file chanserv.c.
int timer_id [static] |