From 0814442111c4b0bebe2e8ac2ba552df7c68a7620 Mon Sep 17 00:00:00 2001 From: Sam Dodrill Date: Fri, 4 Oct 2013 21:32:00 -0700 Subject: [PATCH] away-notify and away rate limiting added Referenced: atheme/charybdis@c5bbc6037579a3c4b72b2a9910138950c628a8d8 : Add away-notify client capability. atheme/charybdis@d42e6915cf1002f5d5df2677d8f2a9225a0857c0 : Pace aways. atheme/charybdis@725403fd7f78716db000b0847f81ac346d4e98b6 : Don't end the flood grace period with the first AWAY. atheme/charybdis@dc0fd46236fe65a18ce082707c3fade81a689f68 : Ensure AWAY pacing only affects local clients. --- doc/example.conf | 1 + doc/reference.conf | 6 ++++++ include/client.h | 3 ++- include/s_conf.h | 1 + modules/m_away.c | 31 +++++++++++++++++++++++++++++-- modules/m_cap.c | 3 ++- modules/m_info.c | 6 ++++++ src/channel.c | 6 ++++++ src/newconf.c | 1 + src/s_conf.c | 1 + 10 files changed, 55 insertions(+), 4 deletions(-) diff --git a/doc/example.conf b/doc/example.conf index 1e2dc2a..77e11c5 100755 --- a/doc/example.conf +++ b/doc/example.conf @@ -608,6 +608,7 @@ general { throttle_duration = 60; throttle_count = 4; expire_override_time = 5 minutes; + away_interval = 30; }; modules { diff --git a/doc/reference.conf b/doc/reference.conf index 69417a2..94152c8 100755 --- a/doc/reference.conf +++ b/doc/reference.conf @@ -1479,6 +1479,12 @@ general { * this long after it is set. 0 disables this. Default is 5 minutes. */ expire_override_time = 5 minutes; + + /* away_interval: the minimum interval between AWAY commands. One + * additional AWAY command is allowed, and only marking as away + * counts. + */ + away_interval = 30; }; modules { diff --git a/include/client.h b/include/client.h index 17e5a52..0e9ae53 100644 --- a/include/client.h +++ b/include/client.h @@ -238,7 +238,7 @@ struct LocalUser struct DNSQuery *dnsquery; /* for outgoing server's name lookup */ - time_t last_away; /* Away since... */ + time_t next_away; /* Don't allow next away before... */ time_t last; /* clients allowed to talk through +g */ @@ -453,6 +453,7 @@ struct ListClient #define CLICAP_SASL 0x0002 #define CLICAP_ACCOUNT_NOTIFY 0x0004 #define CLICAP_EXTENDED_JOIN 0x0008 +#define CLICAP_AWAY_NOTIFY 0x0010 /* * flags macros. diff --git a/include/s_conf.h b/include/s_conf.h index 0a52c7a..36858aa 100644 --- a/include/s_conf.h +++ b/include/s_conf.h @@ -233,6 +233,7 @@ struct config_file_entry int use_propagated_bans; int secret_channels_in_whois; int expire_override_time; + int away_interval; }; struct config_channel_entry diff --git a/modules/m_away.c b/modules/m_away.c index 557371e..e8e26be 100644 --- a/modules/m_away.c +++ b/modules/m_away.c @@ -68,7 +68,8 @@ DECLARE_MODULE_AV1(away, NULL, NULL, away_clist, NULL, NULL, "$Revision: 3370 $" static int m_away(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) { - if(MyClient(source_p) && !IsFloodDone(source_p)) + if(MyClient(source_p) && source_p->localClient->next_away && + !IsFloodDone(source_p)) flood_endgrace(source_p); if(!IsClient(source_p)) @@ -83,12 +84,34 @@ m_away(struct Client *client_p, struct Client *source_p, int parc, const char *p sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s AWAY", use_id(source_p)); free_away(source_p); + + sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, ":%s!%s@%s AWAY", + source_p->name, source_p->username, source_p->host); } if(MyConnect(source_p)) sendto_one_numeric(source_p, RPL_UNAWAY, form_str(RPL_UNAWAY)); return 0; } + /* Rate limit this because it is sent to common channels. */ + if (MyClient(source_p)) + { + if(!IsOper(source_p) && + source_p->localClient->next_away > rb_current_time()) + { + sendto_one(source_p, form_str(RPL_LOAD2HI), + me.name, source_p->name, "AWAY"); + return; + } + if(source_p->localClient->next_away < rb_current_time() - + ConfigFileEntry.away_interval) + source_p->localClient->next_away = rb_current_time(); + else + source_p->localClient->next_away = rb_current_time() + + ConfigFileEntry.away_interval; + } + + if(source_p->user->away == NULL) allocate_away(source_p); if(strncmp(source_p->user->away, parv[1], AWAYLEN - 1)) @@ -97,9 +120,13 @@ m_away(struct Client *client_p, struct Client *source_p, int parc, const char *p sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s AWAY :%s", use_id(source_p), source_p->user->away); } - + if(MyConnect(source_p)) sendto_one_numeric(source_p, RPL_NOWAWAY, form_str(RPL_NOWAWAY)); + sendto_common_channels_local_butone(source_p, CLICAP_AWAY_NOTIFY, ":%s!%s@%s AWAY :%s", + source_p->name, source_p->username, source_p->host, + source_p->user->away); + return 0; } diff --git a/modules/m_cap.c b/modules/m_cap.c index 7bff1a6..d5fec5d 100644 --- a/modules/m_cap.c +++ b/modules/m_cap.c @@ -70,7 +70,8 @@ static struct clicap _CLICAP("multi-prefix", CLICAP_MULTI_PREFIX, 0, 0), _CLICAP("sasl", CLICAP_SASL, 0, 0), _CLICAP("account-notify", CLICAP_ACCOUNT_NOTIFY, 0, 0), - _CLICAP("extended-join", CLICAP_EXTENDED_JOIN, 0, 0) + _CLICAP("extended-join", CLICAP_EXTENDED_JOIN, 0, 0), + _CLICAP("away-notify", CLICAP_AWAY_NOTIFY, 0, 0), }; #define CLICAP_LIST_LEN (sizeof(clicap_list) / sizeof(struct clicap)) diff --git a/modules/m_info.c b/modules/m_info.c index 4ec27f3..40533fc 100644 --- a/modules/m_info.c +++ b/modules/m_info.c @@ -547,6 +547,12 @@ static struct InfoStruct info_table[] = { &ConfigFileEntry.use_propagated_bans, "KLINE sets fully propagated bans" }, + { + "away_interval", + OUTPUT_DECIMAL, + &ConfigFileEntry.away_interval, + "The minimum time between aways", + }, { "default_split_server_count", OUTPUT_DECIMAL, diff --git a/src/channel.c b/src/channel.c index 1aea425..6002a09 100644 --- a/src/channel.c +++ b/src/channel.c @@ -2008,6 +2008,12 @@ void user_join(struct Client * client_p, struct Client * source_p, const char * EmptyString(source_p->user->suser) ? "*" : source_p->user->suser, source_p->tsinfo, source_p->info); + /* Send away message to away-notify enabled clients. */ + if (client_p->user->away) + sendto_channel_local_with_capability_butone(client_p, ALL_MEMBERS, CLICAP_AWAY_NOTIFY, NOCAPS, chptr, + ":%s!%s@%s AWAY :%s", client_p->name, client_p->username, + client_p->host, client_p->user->away); + /* its a new channel, set +nt and burst. */ if(flags & CHFL_CHANOP) { diff --git a/src/newconf.c b/src/newconf.c index b4ccf2d..7f8d6f7 100644 --- a/src/newconf.c +++ b/src/newconf.c @@ -2282,6 +2282,7 @@ static struct ConfEntry conf_general_table[] = { "warn_no_nline", CF_YESNO, NULL, 0, &ConfigFileEntry.warn_no_nline }, { "use_propagated_bans",CF_YESNO, NULL, 0, &ConfigFileEntry.use_propagated_bans }, { "expire_override_time", CF_TIME, NULL, 0, &ConfigFileEntry.expire_override_time}, + { "away_interval", CF_INT, NULL, 0, &ConfigFileEntry.away_interval }, { "\0", 0, NULL, 0, NULL } }; diff --git a/src/s_conf.c b/src/s_conf.c index 73f5cd0..8ac6977 100644 --- a/src/s_conf.c +++ b/src/s_conf.c @@ -755,6 +755,7 @@ set_default_conf(void) ConfigFileEntry.operspy_dont_care_user_info = NO; ConfigFileEntry.use_propagated_bans = YES; ConfigFileEntry.secret_channels_in_whois = NO; + ConfigFileEntry.away_interval = 30; #ifdef HAVE_LIBZ ConfigFileEntry.compression_level = 4;