From da9adec47fc3a11f27f0221232c46f9f6b0d0b11 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Mon, 12 Aug 2019 23:41:18 +0200 Subject: [PATCH 1/3] sending of tag messages and customisable maximum irc message length --- src/irc/core/irc-channels.c | 2 +- src/irc/core/irc-servers.c | 17 +++++++-- src/irc/core/irc-servers.h | 4 +++ src/irc/core/irc.c | 60 ++++++++++++++++++++++++-------- src/irc/notifylist/notify-ison.c | 2 +- src/perl/irc/Irc.xs | 2 ++ 6 files changed, 69 insertions(+), 18 deletions(-) diff --git a/src/irc/core/irc-channels.c b/src/irc/core/irc-channels.c index 27f8f4b2..6d38c560 100644 --- a/src/irc/core/irc-channels.c +++ b/src/irc/core/irc-channels.c @@ -142,7 +142,7 @@ static void irc_channels_join(IRC_SERVER_REC *server, const char *data, /* don't try to send too long lines make sure it's not longer than 510 so 510 - strlen("JOIN ") = 505 */ - if (cmdlen < MAX_IRC_MESSAGE_LEN - 5 /* strlen("JOIN ") */) + if (cmdlen < server->max_message_len - 5 /* strlen("JOIN ") */) continue; } if (outchans->len > 0) { diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 5e98e724..38afb749 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -202,7 +202,7 @@ static char **split_message(SERVER_REC *server, const char *target, /* length calculation shamelessly stolen from splitlong_safe.pl */ return split_line(SERVER(server), msg, target, - MAX_IRC_MESSAGE_LEN - strlen(":! PRIVMSG :") - + ircserver->max_message_len - strlen(":! PRIVMSG :") - strlen(ircserver->nick) - MAX_USERHOST_LEN - strlen(target)); } @@ -233,6 +233,7 @@ static void server_init(IRC_SERVER_REC *server) irc_cap_toggle(server, CAP_SASL, TRUE); } + irc_cap_toggle(server, CAP_MAXLINE, TRUE); irc_cap_toggle(server, CAP_MULTI_PREFIX, TRUE); irc_cap_toggle(server, CAP_EXTENDED_JOIN, TRUE); irc_cap_toggle(server, CAP_SETNAME, TRUE); @@ -314,6 +315,8 @@ SERVER_REC *irc_server_init_connect(SERVER_CONNECT_REC *conn) server->connrec->use_tls ? 6697 : 6667; } + server->max_message_len = MAX_IRC_MESSAGE_LEN; + server->cmd_queue_speed = ircconn->cmd_queue_speed > 0 ? ircconn->cmd_queue_speed : settings_get_time("cmd_queue_speed"); server->max_cmds_at_once = ircconn->max_cmds_at_once > 0 ? @@ -479,6 +482,14 @@ static void sig_server_quit(IRC_SERVER_REC *server, const char *msg) g_free(recoded); } +static void cap_maxline(IRC_SERVER_REC *server) +{ + int maxline = atoi(g_hash_table_lookup(server->cap_supported, CAP_MAXLINE)); + if (maxline >= MAX_IRC_MESSAGE_LEN + 2 /* 2 bytes for CR+LF */) { + server->max_message_len = maxline - 2; + } +} + void irc_server_send_action(IRC_SERVER_REC *server, const char *target, const char *data) { char *recoded; @@ -496,7 +507,7 @@ char **irc_server_split_action(IRC_SERVER_REC *server, const char *target, g_return_val_if_fail(data != NULL, NULL); return split_line(SERVER(server), data, target, - MAX_IRC_MESSAGE_LEN - strlen(":! PRIVMSG :\001ACTION \001") - + server->max_message_len - strlen(":! PRIVMSG :\001ACTION \001") - strlen(server->nick) - MAX_USERHOST_LEN - strlen(target)); } @@ -1033,6 +1044,7 @@ void irc_servers_init(void) signal_add_first("server connected", (SIGNAL_FUNC) sig_connected); signal_add_last("server destroyed", (SIGNAL_FUNC) sig_destroyed); signal_add_last("server quit", (SIGNAL_FUNC) sig_server_quit); + signal_add("server cap ack " CAP_MAXLINE, (SIGNAL_FUNC) cap_maxline); signal_add("event 001", (SIGNAL_FUNC) event_connected); signal_add("event 004", (SIGNAL_FUNC) event_server_info); signal_add("event 005", (SIGNAL_FUNC) event_isupport); @@ -1060,6 +1072,7 @@ void irc_servers_deinit(void) signal_remove("server connected", (SIGNAL_FUNC) sig_connected); signal_remove("server destroyed", (SIGNAL_FUNC) sig_destroyed); signal_remove("server quit", (SIGNAL_FUNC) sig_server_quit); + signal_remove("server cap ack " CAP_MAXLINE, (SIGNAL_FUNC) cap_maxline); signal_remove("event 001", (SIGNAL_FUNC) event_connected); signal_remove("event 004", (SIGNAL_FUNC) event_server_info); signal_remove("event 005", (SIGNAL_FUNC) event_isupport); diff --git a/src/irc/core/irc-servers.h b/src/irc/core/irc-servers.h index 5313c1d0..09936e91 100644 --- a/src/irc/core/irc-servers.h +++ b/src/irc/core/irc-servers.h @@ -15,6 +15,8 @@ #define MAX_IRC_USER_TAGS_LEN 4094 #define CAP_LS_VERSION "302" +#define CAP_MAXLINE "oragono.io/maxline-2" +#define CAP_MESSAGE_TAGS "message-tags" #define CAP_SASL "sasl" #define CAP_MULTI_PREFIX "multi-prefix" #define CAP_EXTENDED_JOIN "extended-join" @@ -58,6 +60,8 @@ struct _IRC_SERVER_CONNECT_REC { struct _IRC_SERVER_REC { #include + int max_message_len; /* Maximum message length, default = 510 = 512 - 2 (for CR+LF) */ + /* For deciding if event should be redirected */ GSList *redirects; GSList *redirect_queue; /* should be updated from redirect_next each time cmdqueue is updated */ diff --git a/src/irc/core/irc.c b/src/irc/core/irc.c index 2f520328..51770aaf 100644 --- a/src/irc/core/irc.c +++ b/src/irc/core/irc.c @@ -49,8 +49,9 @@ static void strip_params_colon(char *const); void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd, int send_now, int immediate, int raw) { - char str[513]; + GString *str; int len; + gboolean server_supports_tag; g_return_if_fail(server != NULL); g_return_if_fail(cmd != NULL); @@ -58,35 +59,66 @@ void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd, if (server->connection_lost) return; - len = strlen(cmd); + str = g_string_sized_new(MAX_IRC_USER_TAGS_LEN + 2 /* `@'+SPACE */ + + server->max_message_len + 2 /* CR+LF */ + 1 /* `\0' */); + if (server->cmdcount == 0) irc_servers_start_cmd_timeout(); server->cmdcount++; if (!raw) { + const char *tmp = cmd; + + server_supports_tag = server->cap_supported != NULL && + g_hash_table_lookup_extended(server->cap_supported, CAP_MESSAGE_TAGS, NULL, NULL); + + if (*cmd == '@' && server_supports_tag) { + const char *end; + + while (*tmp != ' ' && *tmp != '\0') + tmp++; + + end = tmp; + + if (tmp - cmd > MAX_IRC_USER_TAGS_LEN) { + g_warning("irc_send_cmd_full(); tags too long(%ld)", tmp - cmd); + while (tmp - cmd > MAX_IRC_USER_TAGS_LEN && cmd != tmp - 1) tmp--; + while (*tmp != ',' && cmd != tmp - 1) tmp--; + } + if (cmd != tmp) + g_string_append_len(str, cmd, tmp - cmd); + + tmp = end; + while (*tmp == ' ') tmp++; + + if (*tmp != '\0' && str->len > 0) + g_string_append_c(str, ' '); + } + len = strlen(tmp); + /* check that we don't send any longer commands than 510 bytes (2 bytes for CR+LF) */ - strncpy(str, cmd, 510); - if (len > 510) len = 510; - str[len] = '\0'; - cmd = str; + g_string_append_len(str, tmp, len > server->max_message_len ? + server->max_message_len : len); + } else { + g_string_append(str, cmd); } if (send_now) { - rawlog_output(server->rawlog, cmd); - server_redirect_command(server, cmd, server->redirect_next); + rawlog_output(server->rawlog, str->str); + server_redirect_command(server, str->str, server->redirect_next); server->redirect_next = NULL; } if (!raw) { /* Add CR+LF to command */ - str[len++] = 13; - str[len++] = 10; - str[len] = '\0'; + g_string_append_c(str, 13); + g_string_append_c(str, 10); } if (send_now) { - irc_server_send_data(server, cmd, len); + irc_server_send_data(server, str->str, str->len); + g_string_free(str, TRUE); } else { /* add to queue */ @@ -94,10 +126,10 @@ void irc_send_cmd_full(IRC_SERVER_REC *server, const char *cmd, server->cmdqueue = g_slist_prepend(server->cmdqueue, server->redirect_next); server->cmdqueue = g_slist_prepend(server->cmdqueue, - g_strdup(cmd)); + g_string_free(str, FALSE)); } else { server->cmdqueue = g_slist_append(server->cmdqueue, - g_strdup(cmd)); + g_string_free(str, FALSE)); server->cmdqueue = g_slist_append(server->cmdqueue, server->redirect_next); } diff --git a/src/irc/notifylist/notify-ison.c b/src/irc/notifylist/notify-ison.c index 4fb9315a..910c0b73 100644 --- a/src/irc/notifylist/notify-ison.c +++ b/src/irc/notifylist/notify-ison.c @@ -131,7 +131,7 @@ static void notifylist_timeout_server(IRC_SERVER_REC *server) len = strlen(nick); - if (cmd->len+len+1 > MAX_IRC_MESSAGE_LEN) + if (cmd->len+len+1 > server->max_message_len) ison_send(server, cmd); g_string_append_printf(cmd, "%s ", nick); diff --git a/src/perl/irc/Irc.xs b/src/perl/irc/Irc.xs index 3bf81f9a..f64d9728 100644 --- a/src/perl/irc/Irc.xs +++ b/src/perl/irc/Irc.xs @@ -24,6 +24,8 @@ static void perl_irc_server_fill_hash(HV *hv, IRC_SERVER_REC *server) (void) hv_store(hv, "usermode", 8, new_pv(server->usermode), 0); (void) hv_store(hv, "userhost", 8, new_pv(server->userhost), 0); + (void) hv_store(hv, "max_message_len", 15, newSViv(server->max_message_len), 0); + (void) hv_store(hv, "max_cmds_at_once", 16, newSViv(server->max_cmds_at_once), 0); (void) hv_store(hv, "cmd_queue_speed", 15, newSViv(server->cmd_queue_speed), 0); (void) hv_store(hv, "max_query_chans", 15, newSViv(server->max_query_chans), 0); From 200020da93830dc9cfd254b7984a84d25687e008 Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Wed, 14 Aug 2019 21:17:53 +0200 Subject: [PATCH 2/3] use better number parsing --- src/irc/core/irc-servers.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 38afb749..044d676e 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -484,8 +484,10 @@ static void sig_server_quit(IRC_SERVER_REC *server, const char *msg) static void cap_maxline(IRC_SERVER_REC *server) { - int maxline = atoi(g_hash_table_lookup(server->cap_supported, CAP_MAXLINE)); - if (maxline >= MAX_IRC_MESSAGE_LEN + 2 /* 2 bytes for CR+LF */) { + unsigned int maxline = 0; + if (parse_uint(g_hash_table_lookup(server->cap_supported, CAP_MAXLINE), + NULL, 10, &maxline) && + maxline >= MAX_IRC_MESSAGE_LEN + 2 /* 2 bytes for CR+LF */) { server->max_message_len = maxline - 2; } } From 6c370994078969225185bc38e1075b999b9f6bbc Mon Sep 17 00:00:00 2001 From: ailin-nemui Date: Thu, 15 Aug 2019 16:39:26 +0200 Subject: [PATCH 3/3] more variables --- src/irc/core/irc-servers.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/irc/core/irc-servers.c b/src/irc/core/irc-servers.c index 044d676e..2d26c271 100644 --- a/src/irc/core/irc-servers.c +++ b/src/irc/core/irc-servers.c @@ -485,8 +485,16 @@ static void sig_server_quit(IRC_SERVER_REC *server, const char *msg) static void cap_maxline(IRC_SERVER_REC *server) { unsigned int maxline = 0; - if (parse_uint(g_hash_table_lookup(server->cap_supported, CAP_MAXLINE), - NULL, 10, &maxline) && + gboolean parse_successful = FALSE; + const char *maxline_str; + + maxline_str = g_hash_table_lookup(server->cap_supported, CAP_MAXLINE); + if (maxline_str != NULL) { + parse_successful = parse_uint(maxline_str, NULL, 10, &maxline); + + } + + if (parse_successful && maxline >= MAX_IRC_MESSAGE_LEN + 2 /* 2 bytes for CR+LF */) { server->max_message_len = maxline - 2; }