ircd: rework sendq limits a bit.
The sendq limit is now soft, now we halt processing if a sendq is exceeded, until it is sufficiently drained. This allows us to implement SAFELIST and other floody commands without hacks.
This commit is contained in:
parent
8dacf9e917
commit
9a5958119c
4 changed files with 53 additions and 5 deletions
|
@ -40,6 +40,7 @@ struct Class
|
|||
int max_global;
|
||||
int max_ident;
|
||||
int max_sendq;
|
||||
int max_sendq_hard;
|
||||
int con_freq;
|
||||
int ping_freq;
|
||||
int total;
|
||||
|
@ -61,6 +62,7 @@ extern struct Class *default_class;
|
|||
#define MaxUsers(x) ((x)->max_total)
|
||||
#define PingFreq(x) ((x)->ping_freq)
|
||||
#define MaxSendq(x) ((x)->max_sendq)
|
||||
#define MaxSendqHard(x) ((x)->max_sendq_hard)
|
||||
#define CurrUsers(x) ((x)->total)
|
||||
#define IpLimits(x) ((x)->ip_limits)
|
||||
#define CidrIpv4Bitlen(x) ((x)->cidr_ipv4_bitlen)
|
||||
|
@ -81,12 +83,14 @@ extern struct Class *default_class;
|
|||
#define ConfCidrAmount(x) (ClassPtr(x)->cidr_amount)
|
||||
#define ConfCidrIpv4Bitlen(x) (ClassPtr(x)->cidr_ipv4_bitlen)
|
||||
#define ConfCidrIpv6Bitlen(x) (ClassPtr(x)->cidr_ipv6_bitlen)
|
||||
#define ConfMaxSendqHard(x) (ClassPtr(x)->max_sendq_hard)
|
||||
|
||||
void add_class(struct Class *);
|
||||
|
||||
struct Class *make_class(void);
|
||||
|
||||
extern long get_sendq(struct Client *);
|
||||
extern long get_sendq_hard(struct Client *);
|
||||
extern int get_con_freq(struct Class *);
|
||||
extern struct Class *find_class(const char *);
|
||||
extern const char *get_client_class(struct Client *);
|
||||
|
|
32
ircd/class.c
32
ircd/class.c
|
@ -55,6 +55,7 @@ make_class(void)
|
|||
PingFreq(tmp) = DEFAULT_PINGFREQUENCY;
|
||||
MaxUsers(tmp) = 1;
|
||||
MaxSendq(tmp) = DEFAULT_SENDQ;
|
||||
MaxSendqHard(tmp) = DEFAULT_SENDQ * 4;
|
||||
|
||||
tmp->ip_limits = rb_new_patricia(PATRICIA_BITS);
|
||||
return tmp;
|
||||
|
@ -198,6 +199,7 @@ add_class(struct Class *classptr)
|
|||
MaxIdent(tmpptr) = MaxIdent(classptr);
|
||||
PingFreq(tmpptr) = PingFreq(classptr);
|
||||
MaxSendq(tmpptr) = MaxSendq(classptr);
|
||||
MaxSendqHard(tmpptr) = MaxSendq(classptr) * 4;
|
||||
ConFreq(tmpptr) = ConFreq(classptr);
|
||||
CidrIpv4Bitlen(tmpptr) = CidrIpv4Bitlen(classptr);
|
||||
CidrIpv6Bitlen(tmpptr) = CidrIpv6Bitlen(classptr);
|
||||
|
@ -342,3 +344,33 @@ get_sendq(struct Client *client_p)
|
|||
|
||||
return DEFAULT_SENDQ;
|
||||
}
|
||||
|
||||
/*
|
||||
* get_sendq_hard
|
||||
*
|
||||
* inputs - pointer to client
|
||||
* output - hard sendq limit for this client as found from its class
|
||||
* side effects - NONE
|
||||
*/
|
||||
long
|
||||
get_sendq_hard(struct Client *client_p)
|
||||
{
|
||||
if(client_p == NULL || IsMe(client_p))
|
||||
return DEFAULT_SENDQ;
|
||||
|
||||
if(IsServer(client_p))
|
||||
{
|
||||
struct server_conf *server_p;
|
||||
server_p = client_p->localClient->att_sconf;
|
||||
return MaxSendqHard(server_p->class);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct ConfItem *aconf = client_p->localClient->att_conf;
|
||||
|
||||
if(aconf != NULL && aconf->status & CONF_CLIENT)
|
||||
return ConfMaxSendqHard(aconf);
|
||||
}
|
||||
|
||||
return DEFAULT_SENDQ;
|
||||
}
|
||||
|
|
|
@ -108,11 +108,23 @@ parse_client_queued(struct Client *client_p)
|
|||
else
|
||||
allow_read = ConfigFileEntry.client_flood_burst_rate;
|
||||
allow_read *= ConfigFileEntry.client_flood_message_time;
|
||||
|
||||
/* allow opers 4 times the amount of messages as users. why 4?
|
||||
* why not. :) --fl_
|
||||
*/
|
||||
if(IsOper(client_p) && ConfigFileEntry.no_oper_flood)
|
||||
allow_read *= 4;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If a client's sendq is greater than the soft limit, do not allow any
|
||||
* more messages to be read. This allows us to safely handle commands like
|
||||
* LIST without harming the server. --kaniini
|
||||
*/
|
||||
if (rb_linebuf_len(&client_p->localClient->buf_sendq) > (get_sendq(client_p)))
|
||||
allow_read = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle flood protection here - if we exceed our flood limit on
|
||||
* messages in this loop, we simply drop out of the loop prematurely.
|
||||
|
|
10
ircd/send.c
10
ircd/send.c
|
@ -69,20 +69,20 @@ _send_linebuf(struct Client *to, buf_head_t *linebuf)
|
|||
if(!MyConnect(to) || IsIOError(to))
|
||||
return 0;
|
||||
|
||||
if(rb_linebuf_len(&to->localClient->buf_sendq) > get_sendq(to))
|
||||
if(rb_linebuf_len(&to->localClient->buf_sendq) > get_sendq_hard(to))
|
||||
{
|
||||
if(IsServer(to))
|
||||
{
|
||||
sendto_realops_snomask(SNO_GENERAL, L_ALL,
|
||||
"Max SendQ limit exceeded for %s: %u > %lu",
|
||||
"Hard SendQ limit exceeded for %s: %u > %lu",
|
||||
to->name,
|
||||
rb_linebuf_len(&to->localClient->buf_sendq),
|
||||
get_sendq(to));
|
||||
get_sendq_hard(to));
|
||||
|
||||
ilog(L_SERVER, "Max SendQ limit exceeded for %s: %u > %lu",
|
||||
ilog(L_SERVER, "Hard SendQ limit exceeded for %s: %u > %lu",
|
||||
log_client_name(to, SHOW_IP),
|
||||
rb_linebuf_len(&to->localClient->buf_sendq),
|
||||
get_sendq(to));
|
||||
get_sendq_hard(to));
|
||||
}
|
||||
|
||||
dead_link(to, 1);
|
||||
|
|
Loading…
Reference in a new issue