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),
get_sendq(to));
}
- dead_link(to, 1);
return -1;
}
else
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;
+}