modules/chanserv/chanserv.c File Reference

#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_tchanserv_probe_chan (const char *chan, int create)
chanserv_member_stats_tchanserv_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_tserver = 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_tchanstats_head = NULL
static bind_table_tBT_chanflood = NULL
static bind_table_tBT_memflood = NULL


Function Documentation

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 }


Variable Documentation

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.

Definition at line 47 of file chanserv.c.

Initial value:

 {
  "chanserv", 0,
  0, 0,
  0
}

Definition at line 32 of file chanserv.c.

Definition at line 82 of file chanserv.c.

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.

Definition at line 29 of file chanserv.c.

int timer_id [static]

Definition at line 31 of file chanserv.c.

Referenced by chanserv_init().


Generated on Sun Nov 30 18:43:35 2008 for eggdrop1.9 by  doxygen 1.5.6