From 30191c76c8e32c87e6debc269765ad613ef64a12 Mon Sep 17 00:00:00 2001
From: Přemysl Janouch
Date: Fri, 15 May 2015 05:54:03 +0200
Subject: degesch: rework registration
Also fixed the annoying reconnect bug.
---
degesch.c | 110 +++++++++++++++++++++++++++++++++++---------------------------
1 file changed, 63 insertions(+), 47 deletions(-)
diff --git a/degesch.c b/degesch.c
index 6e30bbf..916ecbb 100644
--- a/degesch.c
+++ b/degesch.c
@@ -3057,8 +3057,11 @@ on_irc_disconnected (struct server *s)
while ((channel = str_map_iter_next (&iter)))
irc_left_channel (channel);
- user_unref (s->irc_user);
- s->irc_user = NULL;
+ if (s->irc_user)
+ {
+ user_unref (s->irc_user);
+ s->irc_user = NULL;
+ }
free (s->irc_user_mode);
s->irc_user_mode = NULL;
@@ -3251,14 +3254,6 @@ irc_register (struct server *s)
irc_send (s, "NICK %s", nickname);
// IRC servers may ignore the last argument if it's empty
irc_send (s, "USER %s 8 * :%s", username, *realname ? realname : " ");
-
- // XXX: maybe we should wait for the first message from the server
- // FIXME: the user may exist already after we've reconnected. Either
- // make sure that there's no reference of this nick upon disconnection,
- // or search in "irc_users" first... or something.
- s->irc_user = irc_make_user (s, xstrdup (nickname));
- s->irc_user_mode = xstrdup ("");
- s->irc_user_host = NULL;
}
static void
@@ -3507,6 +3502,8 @@ make_prompt (struct app_context *ctx, struct str *output)
str_append_c (output, ' ');
if (!irc_is_connected (s))
str_append (output, "(disconnected)");
+ else if (s->state != IRC_REGISTERED)
+ str_append (output, "(unregistered)");
else
{
str_append (output, s->irc_user->nickname);
@@ -3561,6 +3558,11 @@ irc_find_userhost (const char *prefix)
static bool
irc_is_this_us (struct server *s, const char *prefix)
{
+ // This shouldn't be called before successfully registering.
+ // Better safe than sorry, though.
+ if (!s->irc_user)
+ return false;
+
char *nick = irc_cut_nickname (prefix);
bool result = !irc_strcmp (nick, s->irc_user->nickname);
free (nick);
@@ -3610,6 +3612,10 @@ irc_get_buffer_for_message (struct server *s,
static bool
irc_is_highlight (struct server *s, const char *message)
{
+ // This may be called by notices before even successfully registering
+ if (!s->irc_user)
+ return false;
+
// Well, this is rather crude but it should make most users happy.
// Ideally we could do this at least in proper Unicode.
char *copy = xstrdup (message);
@@ -4204,6 +4210,28 @@ irc_try_parse_welcome_for_userhost (struct server *s, const char *m)
str_vector_free (&v);
}
+static void
+irc_on_registered (struct server *s, const char *nickname)
+{
+ s->irc_user = irc_get_or_make_user (s, nickname);
+ s->irc_user_mode = xstrdup ("");
+ s->irc_user_host = NULL;
+
+ s->state = IRC_REGISTERED;
+ refresh_prompt (s->ctx);
+
+ // TODO: parse any response and store the result for us in app_context;
+ // this enables proper message splitting on output;
+ // we can also use WHOIS if it's not supported (optional by RFC 2812)
+ irc_send (s, "USERHOST %s", s->irc_user->nickname);
+
+ const char *autojoin = get_config_string (s->ctx, "server.autojoin");
+ if (autojoin)
+ irc_send (s, "JOIN :%s", autojoin);
+
+ // TODO: rejoin all current channels (mark those we've left manually?)
+}
+
static void
irc_process_numeric (struct server *s,
const struct irc_message *msg, unsigned long numeric)
@@ -4211,6 +4239,8 @@ irc_process_numeric (struct server *s,
// Numerics typically have human-readable information
// TODO: try to output certain replies in more specific buffers
+ // TODO: fail the connection if there's no first parameter
+
// Get rid of the first parameter, if there's any at all,
// as it contains our nickname and is of no practical use to the user
struct str_vector copy;
@@ -4228,6 +4258,8 @@ irc_process_numeric (struct server *s,
switch (numeric)
{
case IRC_RPL_WELCOME:
+ irc_on_registered (s, msg->params.vector[0]);
+
// We still issue a USERHOST anyway as this is in general unreliable
if (msg->params.len == 2)
irc_try_parse_welcome_for_userhost (s, msg->params.vector[1]);
@@ -4270,28 +4302,6 @@ irc_process_message (const struct irc_message *msg,
input_show (&s->ctx->input);
}
- // XXX: or is the 001 numeric enough? For what?
- if (s->state == IRC_CONNECTED && (!strcasecmp (msg->command, "MODE")
- || !strcasecmp (msg->command, "376") // RPL_ENDOFMOTD
- || !strcasecmp (msg->command, "422"))) // ERR_NOMOTD
- {
- // XXX: should we really print this?
- buffer_send_status (s->ctx, s->buffer, "Successfully connected");
- s->state = IRC_REGISTERED;
- refresh_prompt (s->ctx);
-
- // TODO: parse any response and store the result for us in app_context;
- // this enables proper message splitting on output;
- // we can also use WHOIS if it's not supported (optional by RFC 2812)
- irc_send (s, "USERHOST %s", s->irc_user->nickname);
-
- const char *autojoin = get_config_string (s->ctx, "server.autojoin");
- if (autojoin)
- irc_send (s, "JOIN :%s", autojoin);
-
- // TODO: rejoin all current channels (mark those we've left manually?)
- }
-
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);
@@ -4402,7 +4412,7 @@ irc_autosplit_message (struct server *s, const char *message,
{
// :!@
int space_in_one_message = 0;
- if (s->irc_user_host)
+ if (s->irc_user && s->irc_user_host)
space_in_one_message = 510
- 1 - (int) strlen (s->irc_user->nickname)
- 1 - (int) strlen (s->irc_user_host)
@@ -4468,7 +4478,7 @@ log_outcoming_action (struct server *s,
{
(void) a;
- if (buffer)
+ if (buffer && soft_assert (s->irc_user))
buffer_send (s->ctx, buffer, BUFFER_LINE_ACTION, 0,
.who = irc_to_utf8 (s->ctx, s->irc_user->nickname),
.text = irc_to_utf8 (s->ctx, line));
@@ -4485,7 +4495,7 @@ static void
log_outcoming_privmsg (struct server *s,
struct send_autosplit_args *a, struct buffer *buffer, const char *line)
{
- if (buffer)
+ if (buffer && soft_assert (s->irc_user))
buffer_send (s->ctx, buffer, BUFFER_LINE_PRIVMSG, 0,
.who = irc_to_utf8 (s->ctx, s->irc_user->nickname),
.text = irc_to_utf8 (s->ctx, line));
@@ -4503,7 +4513,7 @@ static void
log_outcoming_notice (struct server *s,
struct send_autosplit_args *a, struct buffer *buffer, const char *line)
{
- if (buffer)
+ if (buffer && soft_assert (s->irc_user))
buffer_send (s->ctx, buffer, BUFFER_LINE_NOTICE, 0,
.who = irc_to_utf8 (s->ctx, s->irc_user->nickname),
.text = irc_to_utf8 (s->ctx, line));
@@ -4693,8 +4703,12 @@ try_decode_buffer (struct app_context *ctx, const char *word)
}
static bool
-server_command_check (struct app_context *ctx, const char *action)
+server_command_check (struct app_context *ctx, const char *action,
+ bool need_registration)
{
+ // "need_registration" is primarily for message sending commands,
+ // as they may want to log buffer lines and use our current nickname
+
if (ctx->current_buffer->type == BUFFER_GLOBAL)
buffer_send_error (ctx, ctx->current_buffer,
"Can't do this from a global buffer (%s)", action);
@@ -4703,6 +4717,8 @@ server_command_check (struct app_context *ctx, const char *action)
struct server *s = ctx->current_buffer->server;
if (!irc_is_connected (s))
buffer_send_error (ctx, s->buffer, "Not connected");
+ else if (s->state != IRC_REGISTERED && need_registration)
+ buffer_send_error (ctx, s->buffer, "Not registered");
else
return true;
}
@@ -4973,7 +4989,7 @@ handle_command_save (struct app_context *ctx, char *arguments)
static bool
handle_command_msg (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "send messages"))
+ if (!server_command_check (ctx, "send messages", true))
return true;
if (!*arguments)
return false;
@@ -4990,7 +5006,7 @@ handle_command_msg (struct app_context *ctx, char *arguments)
static bool
handle_command_query (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "send messages"))
+ if (!server_command_check (ctx, "send messages", true))
return true;
if (!*arguments)
return false;
@@ -5012,7 +5028,7 @@ handle_command_query (struct app_context *ctx, char *arguments)
static bool
handle_command_notice (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "send messages"))
+ if (!server_command_check (ctx, "send messages", true))
return true;
if (!*arguments)
return false;
@@ -5029,7 +5045,7 @@ handle_command_notice (struct app_context *ctx, char *arguments)
static bool
handle_command_ctcp (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "send messages"))
+ if (!server_command_check (ctx, "send messages", true))
return true;
if (!*arguments)
return false;
@@ -5056,7 +5072,7 @@ handle_command_ctcp (struct app_context *ctx, char *arguments)
static bool
handle_command_me (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "send messages"))
+ if (!server_command_check (ctx, "send messages", true))
return true;
struct server *s = ctx->current_buffer->server;
@@ -5087,7 +5103,7 @@ handle_command_quit (struct app_context *ctx, char *arguments)
static bool
handle_command_join (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "join"))
+ if (!server_command_check (ctx, "join", true))
return true;
struct server *s = ctx->current_buffer->server;
@@ -5116,7 +5132,7 @@ handle_command_join (struct app_context *ctx, char *arguments)
static bool
handle_command_part (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "part"))
+ if (!server_command_check (ctx, "part", true))
return true;
struct server *s = ctx->current_buffer->server;
@@ -5178,7 +5194,7 @@ handle_command_disconnect (struct app_context *ctx, char *arguments)
static bool
handle_command_list (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "list channels"))
+ if (!server_command_check (ctx, "list channels", true))
return true;
struct server *s = ctx->current_buffer->server;
@@ -5192,7 +5208,7 @@ handle_command_list (struct app_context *ctx, char *arguments)
static bool
handle_command_nick (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "change nickname"))
+ if (!server_command_check (ctx, "change nickname", false))
return true;
if (!*arguments)
return false;
@@ -5205,7 +5221,7 @@ handle_command_nick (struct app_context *ctx, char *arguments)
static bool
handle_command_quote (struct app_context *ctx, char *arguments)
{
- if (!server_command_check (ctx, "quote"))
+ if (!server_command_check (ctx, "quote", true))
return true;
struct server *s = ctx->current_buffer->server;
--
cgit v1.2.3-70-g09d2