degesch: IRCv3.2 capability negotiation
We can receive and display capability values now.
This commit is contained in:
parent
735096d76d
commit
17f430043a
2
NEWS
2
NEWS
|
@ -2,6 +2,8 @@
|
||||||
|
|
||||||
* degesch: added a /squery command for IRCnet
|
* degesch: added a /squery command for IRCnet
|
||||||
|
|
||||||
|
* degesch: now supporting IRCv3.2 capability negotiation
|
||||||
|
|
||||||
|
|
||||||
1.1.0 (2020-10-31) "What Do You Mean By 'This Isn't Germany'?"
|
1.1.0 (2020-10-31) "What Do You Mean By 'This Isn't Germany'?"
|
||||||
|
|
||||||
|
|
67
degesch.c
67
degesch.c
|
@ -1718,6 +1718,7 @@ struct server
|
||||||
char *irc_user_host; ///< Our current user@host
|
char *irc_user_host; ///< Our current user@host
|
||||||
bool autoaway_active; ///< Autoaway is currently active
|
bool autoaway_active; ///< Autoaway is currently active
|
||||||
|
|
||||||
|
struct strv cap_ls_buf; ///< Buffer for IRCv3.2 CAP LS
|
||||||
bool cap_echo_message; ///< Whether the server echoes messages
|
bool cap_echo_message; ///< Whether the server echoes messages
|
||||||
bool cap_away_notify; ///< Whether we get AWAY notifications
|
bool cap_away_notify; ///< Whether we get AWAY notifications
|
||||||
|
|
||||||
|
@ -1841,6 +1842,7 @@ server_new (struct poller *poller)
|
||||||
|
|
||||||
self->irc_user_mode = str_make ();
|
self->irc_user_mode = str_make ();
|
||||||
|
|
||||||
|
self->cap_ls_buf = strv_make ();
|
||||||
server_init_specifics (self);
|
server_init_specifics (self);
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
@ -1887,6 +1889,7 @@ server_destroy (struct server *self)
|
||||||
str_free (&self->irc_user_mode);
|
str_free (&self->irc_user_mode);
|
||||||
free (self->irc_user_host);
|
free (self->irc_user_host);
|
||||||
|
|
||||||
|
strv_free (&self->cap_ls_buf);
|
||||||
server_free_specifics (self);
|
server_free_specifics (self);
|
||||||
free (self);
|
free (self);
|
||||||
}
|
}
|
||||||
|
@ -4956,6 +4959,7 @@ irc_destroy_state (struct server *s)
|
||||||
str_reset (&s->irc_user_mode);
|
str_reset (&s->irc_user_mode);
|
||||||
cstr_set (&s->irc_user_host, NULL);
|
cstr_set (&s->irc_user_host, NULL);
|
||||||
|
|
||||||
|
strv_reset (&s->cap_ls_buf);
|
||||||
s->cap_away_notify = false;
|
s->cap_away_notify = false;
|
||||||
s->cap_echo_message = false;
|
s->cap_echo_message = false;
|
||||||
|
|
||||||
|
@ -5692,9 +5696,9 @@ irc_register (struct server *s)
|
||||||
const char *realname = get_config_string (s->config, "realname");
|
const char *realname = get_config_string (s->config, "realname");
|
||||||
hard_assert (username && realname);
|
hard_assert (username && realname);
|
||||||
|
|
||||||
// Start IRCv3.1 capability negotiation;
|
// Start IRCv3 capability negotiation, with up to 3.2 features;
|
||||||
// at worst the server will ignore this or send a harmless error message
|
// at worst the server will ignore this or send a harmless error message
|
||||||
irc_send (s, "CAP LS");
|
irc_send (s, "CAP LS 302");
|
||||||
|
|
||||||
const char *password = get_config_string (s->config, "password");
|
const char *password = get_config_string (s->config, "password");
|
||||||
if (password)
|
if (password)
|
||||||
|
@ -6537,6 +6541,39 @@ irc_handle_away (struct server *s, const struct irc_message *msg)
|
||||||
user->away = !!msg->params.len;
|
user->away = !!msg->params.len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
irc_process_cap_ls (struct server *s)
|
||||||
|
{
|
||||||
|
log_server_status (s, s->buffer,
|
||||||
|
"#s: #&S", "Capabilities supported", strv_join (&s->cap_ls_buf, " "));
|
||||||
|
|
||||||
|
struct strv chosen = strv_make ();
|
||||||
|
struct strv use = strv_make ();
|
||||||
|
|
||||||
|
cstr_split (get_config_string (s->config, "capabilities"), ",", true, &use);
|
||||||
|
|
||||||
|
// Filter server capabilities for ones we can make use of
|
||||||
|
for (size_t i = 0; i < s->cap_ls_buf.len; i++)
|
||||||
|
{
|
||||||
|
const char *cap = s->cap_ls_buf.vector[i];
|
||||||
|
size_t cap_name_len = strcspn (cap, "=");
|
||||||
|
for (size_t k = 0; k < use.len; k++)
|
||||||
|
if (!strncasecmp_ascii (use.vector[k], cap, cap_name_len))
|
||||||
|
strv_append_owned (&chosen, xstrndup (cap, cap_name_len));
|
||||||
|
}
|
||||||
|
strv_reset (&s->cap_ls_buf);
|
||||||
|
|
||||||
|
char *chosen_str = strv_join (&chosen, " ");
|
||||||
|
strv_free (&chosen);
|
||||||
|
strv_free (&use);
|
||||||
|
|
||||||
|
// XXX: with IRCv3.2, this may end up being too long for one message,
|
||||||
|
// and we need to be careful with CAP END. One probably has to count
|
||||||
|
// the number of sent CAP REQ vs the number of received CAP ACK/NAK.
|
||||||
|
irc_send (s, "CAP REQ :%s", chosen_str);
|
||||||
|
free (chosen_str);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
irc_handle_cap (struct server *s, const struct irc_message *msg)
|
irc_handle_cap (struct server *s, const struct irc_message *msg)
|
||||||
{
|
{
|
||||||
|
@ -6577,30 +6614,14 @@ irc_handle_cap (struct server *s, const struct irc_message *msg)
|
||||||
}
|
}
|
||||||
else if (!strcasecmp_ascii (subcommand, "LS"))
|
else if (!strcasecmp_ascii (subcommand, "LS"))
|
||||||
{
|
{
|
||||||
log_server_status (s, s->buffer,
|
|
||||||
"#s: #S", "Capabilities supported", args);
|
|
||||||
|
|
||||||
struct strv chosen = strv_make ();
|
if (msg->params.len > 3 && !strcmp (args, "*"))
|
||||||
struct strv use = strv_make ();
|
cstr_split (msg->params.vector[3], " ", true, &s->cap_ls_buf);
|
||||||
|
else
|
||||||
cstr_split (get_config_string (s->config, "capabilities"),
|
|
||||||
",", true, &use);
|
|
||||||
|
|
||||||
// Filter server capabilities for ones we can make use of
|
|
||||||
for (size_t i = 0; i < v.len; i++)
|
|
||||||
{
|
{
|
||||||
const char *cap = v.vector[i];
|
strv_append_vector (&s->cap_ls_buf, v.vector);
|
||||||
for (size_t k = 0; k < use.len; k++)
|
irc_process_cap_ls (s);
|
||||||
if (!strcasecmp_ascii (use.vector[k], cap))
|
|
||||||
strv_append (&chosen, cap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char *chosen_str = strv_join (&chosen, " ");
|
|
||||||
strv_free (&chosen);
|
|
||||||
strv_free (&use);
|
|
||||||
|
|
||||||
irc_send (s, "CAP REQ :%s", chosen_str);
|
|
||||||
free (chosen_str);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strv_free (&v);
|
strv_free (&v);
|
||||||
|
|
Loading…
Reference in New Issue