]> jfr.im git - solanum.git/commitdiff
ircd: rework sendq limits a bit.
authorWilliam Pitcock <redacted>
Sun, 10 Jan 2016 05:14:04 +0000 (23:14 -0600)
committerWilliam Pitcock <redacted>
Sun, 10 Jan 2016 05:14:04 +0000 (23:14 -0600)
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.

include/class.h
ircd/class.c
ircd/packet.c
ircd/send.c

index c076c185aa2f02f72f6e5aefda8b93ec3b505a7e..33b99e73f26c09db5f643949632beb02b5b35d82 100644 (file)
@@ -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 *);
index a7eb528ac112bb31abb08afd0968358e707d149a..25a7f53f9f1874df3416ea439c60e99e39ceda6f 100644 (file)
@@ -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;
+}
index fe18b1df8e24c52d2ca5c022037c50082c145981..9ee4f7aaea2f6a76077b9be3101d7b9c4a6b1373 100644 (file)
@@ -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.
index cb2112054a73e6d673a6f7583f263a51ecb3ddb6..a15d9d6427f3a7ce0e7eb112e767e45735fa61b3 100644 (file)
@@ -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);