From 10a264ec3d189ba0fc00e4c6f7b0e7e4a8043aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Janouch?= Date: Sun, 31 Jan 2016 20:06:45 +0100 Subject: [PATCH] kike: add support for IRCv3.2 server-time --- NEWS | 2 ++ common.c | 15 +++++++++++++++ degesch.c | 5 +++++ kike.c | 21 ++++++++++++++++++--- 4 files changed, 40 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 9f9eca0..f19388c 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ * degesch: backlog limit was made configurable + * kike: add support for IRCv3.2 server-time + * Remote addresses are now resolved asynchronously * Various bugfixes diff --git a/common.c b/common.c index a92bae4..7880dee 100644 --- a/common.c +++ b/common.c @@ -52,6 +52,21 @@ str_vector_find (const struct str_vector *v, const char *s) return -1; } +static time_t +unixtime_msec (long *msec) +{ +#ifdef _POSIX_TIMERS + struct timespec tp; + hard_assert (clock_gettime (CLOCK_REALTIME, &tp) != -1); + *msec = tp.tv_nsec / 1000000; +#else // ! _POSIX_TIMERS + struct timeval tp; + hard_assert (gettimeofday (&tp, NULL) != -1); + *msec = tp.tv_usec / 1000; +#endif // ! _POSIX_TIMERS + return tp.tv_sec; +} + /// This differs from the non-unique version in that we expect the filename /// to be something like a pattern for mkstemp(), so the resulting path can /// reside in a system-wide directory with no risk of a conflict. diff --git a/degesch.c b/degesch.c index 59a5675..26f0065 100644 --- a/degesch.c +++ b/degesch.c @@ -3144,6 +3144,7 @@ log_formatter (struct app_context *ctx, // Move the formatter inside struct buffer_line *line = buffer_line_new (f); line->flags = flags; + // TODO: allow providing custom time (IRCv3.2 server-time) line->when = time (NULL); buffer_pop_excess_lines (ctx, buffer); @@ -5474,6 +5475,7 @@ irc_handle_cap (struct server *s, const struct irc_message *msg) const char *cap = v.vector[i]; if (!strcasecmp_ascii (cap, "multi-prefix") || !strcasecmp_ascii (cap, "invite-notify") + || !strcasecmp_ascii (cap, "server-time") || !strcasecmp_ascii (cap, "echo-message")) str_vector_add (&chosen, cap); } @@ -6827,6 +6829,9 @@ irc_process_numeric (struct server *s, static void irc_process_message (const struct irc_message *msg, struct server *s) { + // TODO: make use of IRCv3.2 server-time (with fallback to unixtime_msec()) + // -> change all calls to log_{server,nick,outcoming,ctcp}*() to take + // an extra argument specifying time struct irc_handler key = { .name = msg->command }; struct irc_handler *handler = bsearch (&key, g_irc_handlers, N_ELEMENTS (g_irc_handlers), sizeof key, irc_handler_cmp_by_name); diff --git a/kike.c b/kike.c index 1e65318..3aeb2b8 100644 --- a/kike.c +++ b/kike.c @@ -307,7 +307,8 @@ enum IRC_CAP_MULTI_PREFIX = (1 << 0), IRC_CAP_INVITE_NOTIFY = (1 << 1), IRC_CAP_ECHO_MESSAGE = (1 << 2), - IRC_CAP_USERHOST_IN_NAMES = (1 << 3) + IRC_CAP_USERHOST_IN_NAMES = (1 << 3), + IRC_CAP_SERVER_TIME = (1 << 4) }; struct client @@ -832,9 +833,22 @@ client_send_str (struct client *c, const struct str *s) hard_assert (!c->closing_link); size_t old_sendq = c->write_buffer.len; + + // So far there's only one message tag we use, so we can do it simple; + // note that a 512-character limit applies to messages with tags on + if (c->caps_enabled & IRC_CAP_SERVER_TIME) + { + long milliseconds; char buf[32]; struct tm tm; + time_t now = unixtime_msec (&milliseconds); + if (soft_assert (strftime (buf, sizeof buf, + "%Y-%m-%dT%T", gmtime_r (&now, &tm)))) + str_append_printf (&c->write_buffer, + "@time=%s.%03ldZ ", buf, milliseconds); + } + // TODO: kill the connection above some "SendQ" threshold (careful!) str_append_data (&c->write_buffer, s->str, - s->len > IRC_MAX_MESSAGE_LENGTH ? IRC_MAX_MESSAGE_LENGTH : s->len); + MIN (s->len, IRC_MAX_MESSAGE_LENGTH)); str_append (&c->write_buffer, "\r\n"); // XXX: we might want to move this elsewhere, so that it doesn't get called // as often; it's going to cause a lot of syscalls with epoll. @@ -1251,6 +1265,7 @@ irc_cap_table[] = { IRC_CAP_INVITE_NOTIFY, "invite-notify" }, { IRC_CAP_ECHO_MESSAGE, "echo-message" }, { IRC_CAP_USERHOST_IN_NAMES, "userhost-in-names" }, + { IRC_CAP_SERVER_TIME, "server-time" }, }; static void @@ -1263,7 +1278,7 @@ irc_handle_cap_ls (struct client *c, struct irc_cap_args *a) c->cap_negotiating = true; client_send (c, ":%s CAP %s LS :multi-prefix invite-notify echo-message" - " userhost-in-names", c->ctx->server_name, a->target); + " userhost-in-names server-time", c->ctx->server_name, a->target); } static void