kike: stubplement CAP
This commit is contained in:
parent
55fde4803c
commit
20fc6c17d1
|
@ -48,6 +48,7 @@
|
||||||
403 IRC_ERR_NOSUCHCHANNEL "%s :No such channel"
|
403 IRC_ERR_NOSUCHCHANNEL "%s :No such channel"
|
||||||
404 IRC_ERR_CANNOTSENDTOCHAN "%s :Cannot send to channel"
|
404 IRC_ERR_CANNOTSENDTOCHAN "%s :Cannot send to channel"
|
||||||
409 IRC_ERR_NOORIGIN ":No origin specified"
|
409 IRC_ERR_NOORIGIN ":No origin specified"
|
||||||
|
410 IRC_ERR_INVALIDCAPCMD "%s :%s"
|
||||||
411 IRC_ERR_NORECIPIENT ":No recipient given (%s)"
|
411 IRC_ERR_NORECIPIENT ":No recipient given (%s)"
|
||||||
412 IRC_ERR_NOTEXTTOSEND ":No text to send"
|
412 IRC_ERR_NOTEXTTOSEND ":No text to send"
|
||||||
421 IRC_ERR_UNKNOWNCOMMAND "%s: Unknown command"
|
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
|
struct poller_timer kill_timer; ///< Hard kill timeout
|
||||||
|
|
||||||
bool initialized; ///< Has any data been received yet?
|
bool initialized; ///< Has any data been received yet?
|
||||||
|
bool cap_negotiating; ///< Negotiating capabilities
|
||||||
bool registered; ///< The user has registered
|
bool registered; ///< The user has registered
|
||||||
bool closing_link; ///< Closing link
|
bool closing_link; ///< Closing link
|
||||||
bool half_closed; ///< Closing link: conn. is half-closed
|
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_rx_want_tx; ///< SSL_read() wants to write
|
||||||
bool ssl_tx_want_rx; ///< SSL_write() wants to read
|
bool ssl_tx_want_rx; ///< SSL_write() wants to read
|
||||||
SSL *ssl; ///< SSL connection
|
SSL *ssl; ///< SSL connection
|
||||||
|
@ -339,6 +342,7 @@ client_init (struct client *self)
|
||||||
self->socket_fd = -1;
|
self->socket_fd = -1;
|
||||||
str_init (&self->read_buffer);
|
str_init (&self->read_buffer);
|
||||||
str_init (&self->write_buffer);
|
str_init (&self->write_buffer);
|
||||||
|
self->cap_version = 301;
|
||||||
// TODO: make this configurable and more fine-grained
|
// TODO: make this configurable and more fine-grained
|
||||||
flood_detector_init (&self->antiflood, 10, 20);
|
flood_detector_init (&self->antiflood, 10, 20);
|
||||||
str_map_init (&self->invites);
|
str_map_init (&self->invites);
|
||||||
|
@ -1078,6 +1082,8 @@ irc_try_finish_registration (struct client *c)
|
||||||
struct server_context *ctx = c->ctx;
|
struct server_context *ctx = c->ctx;
|
||||||
if (!c->nickname || !c->username || !c->realname)
|
if (!c->nickname || !c->username || !c->realname)
|
||||||
return;
|
return;
|
||||||
|
if (c->registered || c->cap_negotiating)
|
||||||
|
return;
|
||||||
|
|
||||||
c->registered = true;
|
c->registered = true;
|
||||||
irc_send_reply (c, IRC_RPL_WELCOME, c->nickname, c->username, c->hostname);
|
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);
|
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
|
static void
|
||||||
irc_handle_pass (const struct irc_message *msg, struct client *c)
|
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?
|
// TODO: add a field for oper-only commands?
|
||||||
static const struct irc_command message_handlers[] =
|
static const struct irc_command message_handlers[] =
|
||||||
{
|
{
|
||||||
|
{ "CAP", false, irc_handle_cap },
|
||||||
{ "PASS", false, irc_handle_pass },
|
{ "PASS", false, irc_handle_pass },
|
||||||
{ "NICK", false, irc_handle_nick },
|
{ "NICK", false, irc_handle_nick },
|
||||||
{ "USER", false, irc_handle_user },
|
{ "USER", false, irc_handle_user },
|
||||||
|
|
Loading…
Reference in New Issue