kike: stubplement CAP
This commit is contained in:
parent
55fde4803c
commit
20fc6c17d1
@ -48,6 +48,7 @@
|
||||
403 IRC_ERR_NOSUCHCHANNEL "%s :No such channel"
|
||||
404 IRC_ERR_CANNOTSENDTOCHAN "%s :Cannot send to channel"
|
||||
409 IRC_ERR_NOORIGIN ":No origin specified"
|
||||
410 IRC_ERR_INVALIDCAPCMD "%s :%s"
|
||||
411 IRC_ERR_NORECIPIENT ":No recipient given (%s)"
|
||||
412 IRC_ERR_NOTEXTTOSEND ":No text to send"
|
||||
421 IRC_ERR_UNKNOWNCOMMAND "%s: Unknown command"
|
||||
|
67
kike.c
67
kike.c
@ -308,10 +308,13 @@ struct client
|
||||
struct poller_timer kill_timer; ///< Hard kill timeout
|
||||
|
||||
bool initialized; ///< Has any data been received yet?
|
||||
bool cap_negotiating; ///< Negotiating capabilities
|
||||
bool registered; ///< The user has registered
|
||||
bool closing_link; ///< Closing link
|
||||
bool half_closed; ///< Closing link: conn. is half-closed
|
||||
|
||||
unsigned long cap_version; ///< CAP protocol version
|
||||
|
||||
bool ssl_rx_want_tx; ///< SSL_read() wants to write
|
||||
bool ssl_tx_want_rx; ///< SSL_write() wants to read
|
||||
SSL *ssl; ///< SSL connection
|
||||
@ -339,6 +342,7 @@ client_init (struct client *self)
|
||||
self->socket_fd = -1;
|
||||
str_init (&self->read_buffer);
|
||||
str_init (&self->write_buffer);
|
||||
self->cap_version = 301;
|
||||
// TODO: make this configurable and more fine-grained
|
||||
flood_detector_init (&self->antiflood, 10, 20);
|
||||
str_map_init (&self->invites);
|
||||
@ -1078,6 +1082,8 @@ irc_try_finish_registration (struct client *c)
|
||||
struct server_context *ctx = c->ctx;
|
||||
if (!c->nickname || !c->username || !c->realname)
|
||||
return;
|
||||
if (c->registered || c->cap_negotiating)
|
||||
return;
|
||||
|
||||
c->registered = true;
|
||||
irc_send_reply (c, IRC_RPL_WELCOME, c->nickname, c->username, c->hostname);
|
||||
@ -1109,6 +1115,66 @@ irc_try_finish_registration (struct client *c)
|
||||
ctx->server_name, c->nickname, c->ssl_cert_fingerprint);
|
||||
}
|
||||
|
||||
static void
|
||||
irc_handle_cap (const struct irc_message *msg, struct client *c)
|
||||
{
|
||||
if (msg->params.len < 1)
|
||||
RETURN_WITH_REPLY (c, IRC_ERR_NEEDMOREPARAMS, msg->command);
|
||||
|
||||
struct str_vector v;
|
||||
str_vector_init (&v);
|
||||
|
||||
const char *subcommand = msg->params.vector[0];
|
||||
const char *params = "";
|
||||
if (msg->params.len > 1)
|
||||
{
|
||||
params = msg->params.vector[1];
|
||||
split_str_ignore_empty (params, ' ', &v);
|
||||
}
|
||||
|
||||
const char *target = c->nickname ? c->nickname : "*";
|
||||
if (!irc_strcmp (subcommand, "LS"))
|
||||
{
|
||||
if (v.len == 1 && !xstrtoul (&c->cap_version, v.vector[0], 10))
|
||||
irc_send_reply (c, IRC_ERR_INVALIDCAPCMD,
|
||||
subcommand, "Ignoring invalid protocol version number");
|
||||
|
||||
c->cap_negotiating = true;
|
||||
// TODO: actually implement a few capabilities
|
||||
client_send (c, "CAP %s LS :", target);
|
||||
}
|
||||
else if (!irc_strcmp (subcommand, "LIST"))
|
||||
{
|
||||
// TODO: list currently enabled capabilities
|
||||
client_send (c, "CAP %s LIST :", target);
|
||||
}
|
||||
else if (!irc_strcmp (subcommand, "REQ"))
|
||||
{
|
||||
c->cap_negotiating = true;
|
||||
// TODO: process the capability change request, "-" disables
|
||||
if (v.len)
|
||||
client_send (c, "CAP %s NAK :%s", target, params);
|
||||
else
|
||||
client_send (c, "CAP %s ACK :%s", target, params);
|
||||
}
|
||||
else if (!irc_strcmp (subcommand, "ACK"))
|
||||
{
|
||||
if (v.len)
|
||||
irc_send_reply (c, IRC_ERR_INVALIDCAPCMD,
|
||||
subcommand, "No acknowledgable capabilities supported");
|
||||
}
|
||||
else if (!irc_strcmp (subcommand, "END"))
|
||||
{
|
||||
c->cap_negotiating = false;
|
||||
irc_try_finish_registration (c);
|
||||
}
|
||||
else
|
||||
irc_send_reply (c, IRC_ERR_INVALIDCAPCMD,
|
||||
subcommand, "Invalid CAP subcommand");
|
||||
|
||||
str_vector_free (&v);
|
||||
}
|
||||
|
||||
static void
|
||||
irc_handle_pass (const struct irc_message *msg, struct client *c)
|
||||
{
|
||||
@ -2516,6 +2582,7 @@ irc_register_handlers (struct server_context *ctx)
|
||||
// TODO: add a field for oper-only commands?
|
||||
static const struct irc_command message_handlers[] =
|
||||
{
|
||||
{ "CAP", false, irc_handle_cap },
|
||||
{ "PASS", false, irc_handle_pass },
|
||||
{ "NICK", false, irc_handle_nick },
|
||||
{ "USER", false, irc_handle_user },
|
||||
|
Loading…
Reference in New Issue
Block a user