remove irc_chan.state, modify irc_chan_callbacks.on_msg to take a irc_nm, improve error handling a bit further (up to irc_net now)
--- a/Makefile Thu Mar 12 22:06:01 2009 +0200
+++ b/Makefile Thu Mar 12 22:50:08 2009 +0200
@@ -39,7 +39,7 @@
SOCK_TEST_OBJS = obj/sock_test.o
SOCK_GNUTLS_OBJS = obj/sock_gnutls.o
LINEPROTO_OBJS = obj/line_proto.o
-IRC_OBJS = obj/irc_line.o obj/irc_conn.o obj/irc_net.o obj/irc_chan.o obj/irc_cmd.o obj/irc_nm.o
+IRC_OBJS = obj/irc_line.o obj/irc_conn.o obj/irc_net.o obj/irc_chan.o obj/irc_cmd.o obj/irc_proto.o
IRC_LOG_OBJS = obj/irc_log.o
# XXX: not yet there
--- a/src/irc_chan.c Thu Mar 12 22:06:01 2009 +0200
+++ b/src/irc_chan.c Thu Mar 12 22:50:08 2009 +0200
@@ -20,13 +20,17 @@
// us?
if (irc_prefix_cmp_nick(line->prefix, chan->net->conn->nickname) == 0) {
// twiddle state
- chan->state.joining = false;
- chan->state.joined = true;
+ chan->joining = false;
+ chan->joined = true;
log_info("joined channel: %s", chan->info.channel);
// invoke callback
IRC_CHAN_INVOKE_CALLBACK(chan, on_self_join);
+
+ } else {
+ // XXX: who cares
+
}
}
@@ -36,9 +40,23 @@
static void irc_chan_on_PRIVMSG (const struct irc_line *line, void *arg)
{
struct irc_chan *chan = arg;
+ char prefix_buf[IRC_PREFIX_MAX];
+ struct irc_nm *nm;
+ err_t err;
- // invoke callback (prefix, message)
- IRC_CHAN_INVOKE_CALLBACK(chan, on_msg, line->prefix, line->args[1]);
+ const char *msg = line->args[1];
+
+ // parse nickmask
+ if ((err = irc_nm_parse(nm, prefix_buf, line->prefix))) {
+ log_warn("invalid prefix: %s", line->prefix);
+
+ // invoke callback with NULL prefix
+ IRC_CHAN_INVOKE_CALLBACK(chan, on_msg, NULL, msg);
+
+ } else {
+ // invoke callback (prefix, message)
+ IRC_CHAN_INVOKE_CALLBACK(chan, on_msg, nm, msg);
+ }
}
/**
@@ -104,7 +122,8 @@
err_t err;
// XXX: error instead?
- assert(!chan->state.joining && !chan->state.joined);
+ assert(!chan->joining && !chan->joined);
+ assert(chan->net->conn);
// send JOIN message on the appropriate connection
if ((err = irc_conn_JOIN(chan->net->conn, chan->info.channel)))
@@ -112,7 +131,7 @@
return err;
// ok
- chan->state.joining = true;
+ chan->joining = true;
return SUCCESS;
}
--- a/src/irc_chan.h Thu Mar 12 22:06:01 2009 +0200
+++ b/src/irc_chan.h Thu Mar 12 22:50:08 2009 +0200
@@ -11,6 +11,7 @@
#include "irc_net.h"
#include "irc_cmd.h"
+#include "irc_proto.h"
#include "error.h"
#include <sys/queue.h>
@@ -24,14 +25,16 @@
};
/**
- * Semantic IRC channel callbacks
+ * Semantic IRC channel callbacks.
+ *
+ * Where callbacks have irc_nm arguments, these are MAY be given as NULL if the prefix could not be parsed.
*/
struct irc_chan_callbacks {
/** Joined the channel */
void (*on_self_join) (struct irc_chan *chan, void *arg);
/** Someone sent a message to the channel */
- void (*on_msg) (struct irc_chan *chan, const char *prefix, const char *msg, void *arg);
+ void (*on_msg) (struct irc_chan *chan, const struct irc_nm *source, const char *msg, void *arg);
};
/**
@@ -62,16 +65,15 @@
/** Our identifying info */
struct irc_chan_info info;
- /** State flags */
- struct {
+ /** State flags @{ */
/** JOIN request sent, waiting for reply */
bool joining;
/** Currently joined to channel */
bool joined;
- } state;
-
+ // @}
+
/** General command handlers */
irc_cmd_handlers_t handlers;
--- a/src/irc_conn.c Thu Mar 12 22:06:01 2009 +0200
+++ b/src/irc_conn.c Thu Mar 12 22:50:08 2009 +0200
@@ -7,14 +7,19 @@
#include <string.h>
/**
- * @group Forward-declerations
- * @{
+ * Handle an async error on this IRC connection that we could not recover from any other way, the protocol is now dead,
+ * and should be considered as destroyed after this returns.
+ *
+ * For conveniance, this returns the ERROR_CODE
*/
+static err_t irc_conn_set_error (struct irc_conn *conn, struct error_info *err)
+{
+ // notify user callback
+ conn->callbacks.on_error(conn, err, conn->cb_arg);
-/**
- * Handle an event-based error on this IRC connection.
- */
-static void irc_conn_handle_error (struct irc_conn *conn, struct error_info *err);
+ return ERROR_CODE(err);
+}
+
/**
* Update irc_conn.nickname
@@ -28,17 +33,13 @@
SET_ERROR(&err, ERR_STRDUP);
// notify
- irc_conn_handle_error(conn, &err);
-
- return ERROR_CODE(&err);
+ return irc_conn_set_error(conn, &err);
}
// ok
return SUCCESS;
}
-// @}
-
/**
* 001 <nick> :Welcome to the Internet Relay Network <nick>!<user>@<host>
*/
@@ -138,8 +139,8 @@
// log
log_err_info(err, "line_proto error");
- // 'handle'
- irc_conn_handle_error(conn, err);
+ // trash ourselves
+ irc_conn_set_error(conn, err);
}
static struct line_proto_callbacks _lp_callbacks = {
@@ -147,11 +148,6 @@
.on_error = &irc_conn_on_error,
};
-static void irc_conn_handle_error (struct irc_conn *conn, struct error_info *err)
-{
- // XXX: notify user callback
-}
-
err_t irc_conn_create (struct irc_conn **conn_ptr, struct sock_stream *sock, const struct irc_conn_callbacks *callbacks,
void *cb_arg, struct error_info *err)
{
--- a/src/irc_conn.h Thu Mar 12 22:06:01 2009 +0200
+++ b/src/irc_conn.h Thu Mar 12 22:50:08 2009 +0200
@@ -40,6 +40,12 @@
* irc_conn_register has completed.
*/
void (*on_registered) (struct irc_conn *conn, void *arg);
+
+ /**
+ * The connection has failed in some way, and can not be considered useable anymore. Sending messages won't work,
+ * and no more messages will be received. The connection should be destroyed, probably from this callback.
+ */
+ void (*on_error) (struct irc_conn *conn, struct error_info *err, void *arg);
};
/*
--- a/src/irc_log.c Thu Mar 12 22:06:01 2009 +0200
+++ b/src/irc_log.c Thu Mar 12 22:50:08 2009 +0200
@@ -14,14 +14,14 @@
} _ctx;
-static void on_chan_msg (struct irc_chan *chan, const char *prefix, const char *message, void *arg)
+static void on_chan_msg (struct irc_chan *chan, const struct irc_nm *source, const char *message, void *arg)
{
struct irc_log_ctx *ctx = arg;
(void) ctx;
// log it! :P
- log_debug("%s: %s: %s", prefix, irc_chan_name(chan), message);
+ log_debug("%s: %s: %s", source ? source->nickname : "???", irc_chan_name(chan), message);
}
static struct irc_chan_callbacks _chan_callbacks = {
--- a/src/irc_net.c Thu Mar 12 22:06:01 2009 +0200
+++ b/src/irc_net.c Thu Mar 12 22:50:08 2009 +0200
@@ -20,11 +20,26 @@
}
}
+static void irc_net_conn_error (struct irc_conn *conn, struct error_info *err, void *arg)
+{
+ struct irc_net *net = arg;
+
+ // log an error
+ log_err_info(err, "irc_conn failed");
+
+ // destroy and set NULL
+ irc_conn_destroy(conn);
+ net->conn = NULL;
+
+ // XXX: reconnect?
+}
+
/**
* Our irc_conn_callbacks list
*/
struct irc_conn_callbacks _conn_callbacks = {
.on_registered = &irc_net_conn_registered,
+ .on_error = &irc_net_conn_error,
};
/**
--- a/src/irc_proto.c Thu Mar 12 22:06:01 2009 +0200
+++ b/src/irc_proto.c Thu Mar 12 22:50:08 2009 +0200
@@ -2,6 +2,31 @@
#include <string.h>
+err_t irc_nm_parse (struct irc_nm *nm, char *buf, const char *prefix)
+{
+ // too long?
+ if (strlen(prefix) >= IRC_PREFIX_MAX)
+ return ERR_INVALID_NM;
+
+ // copy to mutable buffer
+ strcpy(buf, prefix);
+
+ // mangle tokens
+ nm->nickname = strsep(&buf, "!");
+ nm->username = strsep(&buf, "@");
+
+ // did we find the ! and @ tokens?
+ if (!buf)
+ // probably a server name instead
+ return ERR_INVALID_NM;
+
+ // the hostname is then the rest of the prefix
+ nm->hostname = buf;
+
+ // ok
+ return SUCCESS;
+}
+
/**
* Compare two nicknames
*/
--- a/src/irc_proto.h Thu Mar 12 22:06:01 2009 +0200
+++ b/src/irc_proto.h Thu Mar 12 22:50:08 2009 +0200
@@ -10,11 +10,18 @@
#include <stddef.h>
/**
- * Maximum length of an IRC nickname including terminating NUL
+ * Maximum length of an IRC nickname including terminating NUL.
*/
#define IRC_NICK_MAX 31
/**
+ * Maximum length of an IRC prefix/nickmask string, including any termianting NULs.
+ *
+ * XXX: currently this is pretty large, but does it really matter? We have more than 4k stack...
+ */
+#define IRC_PREFIX_MAX 510
+
+/**
* Parsed nickmask
*/
struct irc_nm {
@@ -31,9 +38,10 @@
/**
* Parse a full nickmask from a prefix. This fails if the prefix is a server name.
*
- * XXX: not implemented, and memory-management issues
+ * Since we cannot modify the prefix string, the user must provide a buffer of at least IRC_PREFIX_MAX bytes to store
+ * the procesed prefix. The returned nm's fields will point into this buffer.
*/
-err_t irc_nm_parse (struct irc_nm *nm, char *prefix);
+err_t irc_nm_parse (struct irc_nm *nm, char *buf, const char *prefix);
/**
* Compare two nicknames for equality, with standard strcmp() semantics.
--- a/src/line_proto.c Thu Mar 12 22:06:01 2009 +0200
+++ b/src/line_proto.c Thu Mar 12 22:50:08 2009 +0200
@@ -40,16 +40,14 @@
static err_t line_proto_schedule_events (struct line_proto *lp, short what);
/**
- * Trigger the on_error callback
+ * An error occured which we could not recover from; the line_proto should now be considered corrupt.
*
- * XXX: take error_info as an arg?
+ * Notify the user callback, which will probably call line_proto_release().
*/
-static void line_proto_handle_error (struct line_proto *lp)
+static void line_proto_set_error (struct line_proto *lp)
{
// trigger callback
lp->callbacks.on_error(&lp->err, lp->cb_arg);
-
- // XXX: do we handle release()? no
}
/**
@@ -69,9 +67,7 @@
// attempt to read a line
if (line_proto_recv(lp, &line)) {
// faaail
- line_proto_handle_error(lp);
-
- return;
+ return line_proto_set_error(lp);
}
// got a line?
@@ -82,7 +78,7 @@
// reschedule
if (line_proto_schedule_events(lp, EV_READ))
- line_proto_handle_error(lp);
+ line_proto_set_error(lp);
}
/*
@@ -100,7 +96,7 @@
// faaaail
SET_ERROR(&lp->err, -ret);
- line_proto_handle_error(lp);
+ return line_proto_set_error(lp);
}
}
--- a/src/line_proto.h Thu Mar 12 22:06:01 2009 +0200
+++ b/src/line_proto.h Thu Mar 12 22:50:08 2009 +0200
@@ -21,7 +21,7 @@
/** Handle received line */
void (*on_line) (char *line, void *arg);
- /** Event-based action failed */
+ /** Transport failed, the line_proto is corrupt, you should call line_proto_release next. */
void (*on_error) (struct error_info *err, void *arg);
};
--- a/src/test.c Thu Mar 12 22:06:01 2009 +0200
+++ b/src/test.c Thu Mar 12 22:50:08 2009 +0200
@@ -379,7 +379,7 @@
// add a channel
assert((chan = irc_net_add_chan(net, &chan_info)));
- assert(!chan->state.joining && !chan->state.joined);
+ assert(!chan->joining && !chan->joined);
assert_success(irc_chan_add_callbacks(chan, &_chan_callbacks, &ctx));
ctx.chan = chan;
@@ -392,12 +392,12 @@
assert_strcmp(net->conn->nickname, "mynick");
// JOIN request
- assert(chan->state.joining);
+ assert(chan->joining);
assert_sock_data(sock, "JOIN #test\r\n");
// JOIN reply
sock_test_add_recv_str(sock, ":mynick!user@host JOIN #test\r\n");
- assert(!chan->state.joining && chan->state.joined);
+ assert(!chan->joining && chan->joined);
assert(ctx.on_chan_self_join);
}