]> jfr.im git - solanum.git/blobdiff - ircd/send.c
global masktrace doesn't need to be an operspy action
[solanum.git] / ircd / send.c
index 4205276c74ae4fdfea369814ecf3fb229a8e7277..9d678a3d0a6337b508dc5994c1cb3a01ee0dcdde 100644 (file)
@@ -70,9 +70,11 @@ _send_linebuf(struct Client *to, buf_head_t *linebuf)
 
        if(rb_linebuf_len(&to->localClient->buf_sendq) > get_sendq(to))
        {
+               dead_link(to, 1);
+
                if(IsServer(to))
                {
-                       sendto_realops_snomask(SNO_GENERAL, L_ALL,
+                       sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
                                             "Max SendQ limit exceeded for %s: %u > %lu",
                                             to->name,
                                             rb_linebuf_len(&to->localClient->buf_sendq),
@@ -84,7 +86,6 @@ _send_linebuf(struct Client *to, buf_head_t *linebuf)
                             get_sendq(to));
                }
 
-               dead_link(to, 1);
                return -1;
        }
        else
@@ -1503,3 +1504,171 @@ kill_client_serv_butone(struct Client *one, struct Client *target_p, const char
 
        rb_linebuf_donebuf(&rb_linebuf_id);
 }
+
+static struct Client *multiline_stashed_target_p;
+static char multiline_prefix[DATALEN+1]; /* allow for null termination */
+static int multiline_prefix_len;
+static char multiline_separator[2];
+static int multiline_separator_len;
+static char *multiline_item_start;
+static char *multiline_cur;
+static int multiline_cur_len;
+static int multiline_remote_pad;
+
+bool
+send_multiline_init(struct Client *target_p, const char *separator, const char *format, ...)
+{
+       va_list args;
+
+       s_assert(multiline_stashed_target_p == NULL && "Multiline: didn't cleanup after last usage!");
+
+       va_start(args, format);
+       multiline_prefix_len = vsnprintf(multiline_prefix, sizeof multiline_prefix, format, args);
+       va_end(args);
+
+       if (multiline_prefix_len <= 0 || multiline_prefix_len >= DATALEN)
+       {
+               s_assert(false && "Multiline: failure preparing prefix!");
+               return false;
+       }
+
+       multiline_separator_len = rb_strlcpy(multiline_separator, separator, sizeof multiline_separator);
+       if (multiline_separator_len >= sizeof multiline_separator)
+       {
+               s_assert(false && "Multiline: separator too long");
+               return false;
+       }
+
+       multiline_stashed_target_p = target_p;
+       multiline_item_start = multiline_prefix + multiline_prefix_len;
+       multiline_cur = multiline_item_start;
+       multiline_cur_len = multiline_prefix_len;
+       multiline_remote_pad = 0;
+       return true;
+}
+
+bool
+send_multiline_remote_pad(struct Client *target_p, struct Client *client_p)
+{
+       ssize_t remote_pad;
+
+       if (target_p != multiline_stashed_target_p)
+       {
+               s_assert(false && "Multiline: missed init call!");
+               multiline_stashed_target_p = NULL;
+               return false;
+       }
+
+       if (MyConnect(target_p))
+               return true;
+
+       remote_pad = strlen(client_p->name) - strlen(client_p->id);
+
+       if (remote_pad > 0)
+       {
+               multiline_remote_pad += remote_pad;
+       }
+
+       return true;
+}
+
+enum multiline_item_result
+send_multiline_item(struct Client *target_p, const char *format, ...)
+{
+       va_list args;
+       char item[DATALEN];
+       int item_len, res;
+       enum multiline_item_result ret = MULTILINE_SUCCESS;
+
+       if (target_p != multiline_stashed_target_p)
+       {
+               s_assert(false && "Multiline: missed init call!");
+               multiline_stashed_target_p = NULL;
+               return MULTILINE_FAILURE;
+       }
+
+       va_start(args, format);
+       item_len = vsnprintf(item, sizeof item, format, args);
+       va_end(args);
+
+       if (item_len < 0 || multiline_prefix_len + multiline_remote_pad + item_len > DATALEN)
+       {
+               s_assert(false && "Multiline: failure preparing item!");
+               multiline_stashed_target_p = NULL;
+               return MULTILINE_FAILURE;
+       }
+
+       if (multiline_cur_len + ((*multiline_item_start != '\0') ? multiline_separator_len : 0) + item_len > DATALEN - multiline_remote_pad)
+       {
+               sendto_one(target_p, "%s", multiline_prefix);
+               *multiline_item_start = '\0';
+               multiline_cur_len = multiline_prefix_len;
+               multiline_cur = multiline_item_start;
+               ret = MULTILINE_WRAPPED;
+       }
+
+       res = snprintf(multiline_cur, sizeof multiline_prefix - multiline_cur_len, "%s%s",
+                       (*multiline_item_start != '\0') ? multiline_separator : "",
+                       item);
+
+       if (res < 0)
+       {
+               s_assert(false && "Multiline: failure appending item!");
+               multiline_stashed_target_p = NULL;
+               return MULTILINE_FAILURE;
+       }
+
+       multiline_cur_len += res;
+       multiline_cur += res;
+       return ret;
+}
+
+bool
+send_multiline_fini(struct Client *target_p, const char *format, ...)
+{
+       va_list args;
+       char final[DATALEN];
+       int final_len;
+
+       if (target_p != multiline_stashed_target_p)
+       {
+               s_assert(false && "Multiline: missed init call!");
+               multiline_stashed_target_p = NULL;
+               return false;
+       }
+
+       if (multiline_cur_len == multiline_prefix_len)
+       {
+               multiline_stashed_target_p = NULL;
+               return true;
+       }
+
+       if (format)
+       {
+               va_start(args, format);
+               final_len = vsnprintf(final, sizeof final, format, args);
+               va_end(args);
+
+               if (final_len <= 0 || final_len > multiline_prefix_len)
+               {
+                       s_assert(false && "Multiline: failure preparing final prefix!");
+                       multiline_stashed_target_p = NULL;
+                       return false;
+               }
+       }
+       else
+       {
+               rb_strlcpy(final, multiline_prefix, multiline_prefix_len + 1);
+       }
+
+       sendto_one(target_p, "%s%s", final, multiline_item_start);
+
+       multiline_stashed_target_p = NULL;
+       return true;
+}
+
+void
+send_multiline_reset(void)
+{
+       multiline_stashed_target_p = NULL;
+}