--- a/src/irc_chan.c Thu Mar 26 22:54:25 2009 +0200
+++ b/src/irc_chan.c Thu Mar 26 23:15:55 2009 +0200
@@ -71,7 +71,7 @@
err_t err;
// us?
- if (irc_prefix_cmp_nick(line->prefix, chan->net->conn->nickname) == 0) {
+ if (irc_cmp_nick(line->source->nickname, chan->net->conn->nickname) == 0) {
// twiddle state
chan->joining = false;
chan->joined = true;
@@ -80,19 +80,12 @@
IRC_CHAN_INVOKE_CALLBACK(chan, on_self_join);
} else {
- char prefix_buf[IRC_PREFIX_MAX];
- struct irc_nm nm;
-
- // parse the nickname
- if ((err = irc_nm_parse(&nm, prefix_buf, line->prefix)))
- return log_warn("invalid prefix: %s", line->prefix);
-
// add them
- if ((err = irc_chan_add_user(chan, nm.nickname)))
- return log_warn("irc_chan_add_user(%s, %s): %s", irc_chan_name(chan), nm.nickname, error_name(err));
+ if ((err = irc_chan_add_user(chan, line->source->nickname)))
+ return log_warn("irc_chan_add_user(%s, %s): %s", irc_chan_name(chan), line->source->nickname, error_name(err));
// invoke callback (source)
- IRC_CHAN_INVOKE_CALLBACK(chan, on_join, &nm);
+ IRC_CHAN_INVOKE_CALLBACK(chan, on_join, line->source);
}
}
@@ -104,12 +97,11 @@
static void irc_chan_on_PART (const struct irc_line *line, void *arg)
{
struct irc_chan *chan = arg;
- err_t err;
const char *msg = line->args[1];
// us?
- if (irc_prefix_cmp_nick(line->prefix, chan->net->conn->nickname) == 0) {
+ if (irc_cmp_nick(line->source->nickname, chan->net->conn->nickname) == 0) {
// twiddle state
chan->joined = false;
chan->parted = true;
@@ -119,20 +111,14 @@
} else {
// someone else
- char prefix_buf[IRC_PREFIX_MAX];
- struct irc_nm nm;
struct irc_chan_user *chan_user;
- // parse the nickname
- if ((err = irc_nm_parse(&nm, prefix_buf, line->prefix)))
- return log_warn("invalid prefix: %s", line->prefix);
-
// invoke callback (source, msg)
- IRC_CHAN_INVOKE_CALLBACK(chan, on_part, &nm, msg);
+ IRC_CHAN_INVOKE_CALLBACK(chan, on_part, line->source, msg);
// look up the irc_chan_user
- if ((chan_user = irc_chan_get_user(chan, nm.nickname)) == NULL)
- return log_warn("PART'd user not on channel: %s, %s", irc_chan_name(chan), nm.nickname);
+ if ((chan_user = irc_chan_get_user(chan, line->source->nickname)) == NULL)
+ return log_warn("PART'd user not on channel: %s, %s", irc_chan_name(chan), line->source->nickname);
// remove them
irc_chan_remove_user(chan, chan_user);
@@ -145,23 +131,11 @@
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;
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 source
- IRC_CHAN_INVOKE_CALLBACK(chan, on_msg, NULL, msg);
-
- } else {
- // invoke callback (source, message)
- IRC_CHAN_INVOKE_CALLBACK(chan, on_msg, &nm, msg);
- }
+ // invoke callback (source, message)
+ IRC_CHAN_INVOKE_CALLBACK(chan, on_msg, line->source, msg);
}
/**
--- a/src/irc_conn.c Thu Mar 26 22:54:25 2009 +0200
+++ b/src/irc_conn.c Thu Mar 26 23:15:55 2009 +0200
@@ -81,20 +81,13 @@
static void on_NICK (const struct irc_line *line, void *arg)
{
struct irc_conn *conn = arg;
- char nickname[IRC_NICK_MAX];
-
- // parse nickname, ignoring errors
- if (irc_prefix_parse_nick(line->prefix, nickname)) {
- log_warn("invalid prefix: %s", line->prefix);
- return;
- }
// ignore if it's not us
- if (irc_cmp_nick(nickname, conn->nickname))
+ if (!line->source || irc_cmp_nick(line->source->nickname, conn->nickname))
return;
// update our nickname
- irc_conn_set_nickname(conn, nickname);
+ irc_conn_set_nickname(conn, line->args[0]);
}
/**
@@ -114,13 +107,14 @@
{
struct irc_conn *conn = arg;
struct irc_line line;
+ struct irc_nm nm;
int err;
// log
log_debug("%s", line_buf);
// parse
- if ((err = irc_line_parse(&line, line_buf))) {
+ if ((err = irc_line_parse(&line, &nm, line_buf))) {
log_warn("invalid line: %s: %s\n", line_buf, error_name(err));
return;
}
--- a/src/irc_line.c Thu Mar 26 22:54:25 2009 +0200
+++ b/src/irc_line.c Thu Mar 26 23:15:55 2009 +0200
@@ -1,17 +1,28 @@
-
#include "irc_line.h"
+#include "log.h"
#include <string.h>
#include <assert.h>
-err_t irc_line_parse (struct irc_line *line, char *data)
+err_t irc_line_parse (struct irc_line *line, struct irc_nm *nm, char *data)
{
int i;
+ err_t err;
// prefix?
if (data && *data == ':') {
// consume as token
- line->prefix = strsep(&data, " ") + 1;
+ char *prefix = strsep(&data, " ") + 1;
+
+ // parse as a nickmask
+ if ((err = irc_nm_parse_buf(nm, prefix))) {
+ line->source = NULL;
+ log_warn("invalid prefix: '%s': %s", prefix, error_name(err));
+
+ } else {
+ // valid, store
+ line->source = nm;
+ }
}
// command
@@ -87,7 +98,7 @@
err_t err;
// XXX: no need for prefix on client
- assert(line->prefix == NULL);
+ assert(line->source == NULL);
// command
if ((err = output_token(buf, &off, line->command, TOK_NOSPACE)))
--- a/src/irc_line.h Thu Mar 26 22:54:25 2009 +0200
+++ b/src/irc_line.h Thu Mar 26 23:15:55 2009 +0200
@@ -6,6 +6,7 @@
*
* The low-level IRC protocol unit is a line, with prefix, command and arguments
*/
+#include "irc_proto.h"
#include "error.h"
/**
@@ -28,8 +29,8 @@
* Low-level IRC protocol unit
*/
struct irc_line {
- /** The message source, either a server name or a nickmask */
- const char *prefix;
+ /** The message source as a nickmask, for those messages that have a valid prefix. May be NULL otherwise */
+ const struct irc_nm *source;
/** The command, either a numeric or a primary command */
const char *command;
@@ -42,9 +43,11 @@
* Parse an IRC message to fill in an irc_line. This mutates the value of data (to insert NULs between tokens), and
* stores pointers into this data into the irc_line.
*
+ * If the prefix is a valid nickmask, it will be stored in the given given irc_nm, and irc_line.nm set to this.
+ *
* The irc_line will have the first N args values set to valid values, and all the rest set to NULL.
*/
-err_t irc_line_parse (struct irc_line *line, char *data);
+err_t irc_line_parse (struct irc_line *line, struct irc_nm *nm, char *data);
/**
* Formats an irc_line as a protocol line into the given buffer (which should hold at least IRC_LINE_MAX bytes).
--- a/src/irc_log.c Thu Mar 26 22:54:25 2009 +0200
+++ b/src/irc_log.c Thu Mar 26 23:15:55 2009 +0200
@@ -162,24 +162,6 @@
}
/**
- * Parse the prefix into a nickmask and pass on to irc_log_event
- */
-static err_t irc_log_event_prefix (struct irc_log_ctx *ctx, struct irc_log_chan *chan_ctx, const char *prefix,
- const char *type, const char *target, const char *message)
-{
- char prefix_buf[IRC_PREFIX_MAX];
- struct irc_nm nm;
- err_t err;
-
- // parse nickmask
- if ((err = irc_nm_parse(&nm, prefix_buf, prefix)))
- return err;
-
- // log
- return irc_log_event(ctx, chan_ctx, &nm, type, target, message);
-}
-
-/**
* Log a simple channel event of the form:
*
* :nm <type> <channel> [<msg>]
@@ -190,7 +172,7 @@
const char *msg = line->args[1];
- irc_log_event_prefix(chan_ctx->ctx, chan_ctx, line->prefix, line->command, NULL, msg);
+ irc_log_event(chan_ctx->ctx, chan_ctx, line->source, line->command, NULL, msg);
}
/**
@@ -221,7 +203,7 @@
}
// log
- irc_log_event_prefix(chan_ctx->ctx, chan_ctx, line->prefix, line->command, NULL, message);
+ irc_log_event(chan_ctx->ctx, chan_ctx, line->source, line->command, NULL, message);
}
/**
@@ -236,7 +218,7 @@
const char *target = line->args[1];
const char *msg = line->args[2];
- irc_log_event_prefix(chan_ctx->ctx, chan_ctx, line->prefix, line->command, target, msg);
+ irc_log_event(chan_ctx->ctx, chan_ctx, line->source, line->command, target, msg);
}
/**
--- a/src/irc_proto.c Thu Mar 26 22:54:25 2009 +0200
+++ b/src/irc_proto.c Thu Mar 26 23:15:55 2009 +0200
@@ -2,6 +2,27 @@
#include <string.h>
+err_t irc_nm_parse_buf (struct irc_nm *nm, char *prefix)
+{
+ // XXX: handle server name prefixes
+
+ // mangle tokens
+ nm->nickname = strsep(&prefix, "!");
+ nm->username = strsep(&prefix, "@");
+
+ // did we find the ! and @ tokens?
+ if (!prefix)
+ // probably a server name instead
+ return ERR_INVALID_NM;
+
+ // the hostname is then the rest of the prefix
+ nm->hostname = prefix;
+
+ // ok
+ return SUCCESS;
+
+}
+
err_t irc_nm_parse (struct irc_nm *nm, char *buf, const char *prefix)
{
// too long?
@@ -10,21 +31,9 @@
// 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;
+ // parse from buf
+ return irc_nm_parse_buf(nm, buf);
}
/**
--- a/src/irc_proto.h Thu Mar 26 22:54:25 2009 +0200
+++ b/src/irc_proto.h Thu Mar 26 23:15:55 2009 +0200
@@ -32,7 +32,8 @@
#define IRC_CHANFLAGS "@+"
/**
- * Parsed nickmask
+ * Parsed nickmask. For normal user prefixes, all fields will be non-NULL. For server prefixes, nickname and username
+ * will be NULL, and hostname will be the server name.
*/
struct irc_nm {
/** Nickname, not normalized */
@@ -46,10 +47,14 @@
};
/**
- * Parse a full nickmask from a prefix. This fails if the prefix is a server name.
- *
- * 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.
+ * Parse a full nickmask from a prefix, mutating the value of the given buffer, and returning pointers into the buffer
+ * inside \a nm.
+ */
+err_t irc_nm_parse_buf (struct irc_nm *nm, char *prefix);
+
+/**
+ * Same as irc_nm_parse_buf(), but copies the prefix into the given mutable buffer of at least IRC_PREFIX_MAX bytes and
+ * returns pointers into that instead.
*/
err_t irc_nm_parse (struct irc_nm *nm, char *buf, const char *prefix);
--- a/src/test.c Thu Mar 26 22:54:25 2009 +0200
+++ b/src/test.c Thu Mar 26 23:15:55 2009 +0200
@@ -123,6 +123,12 @@
return dump_strn(str, -1);
}
+void assert_null (const void *ptr)
+{
+ if (ptr)
+ FATAL("%p != NULL", ptr);
+}
+
void assert_strcmp (const char *is, const char *should_be)
{
if (!is || strcmp(is, should_be))
@@ -423,7 +429,7 @@
{
struct _test_irc_conn_ctx *ctx = arg;
- assert_strcmp(line->prefix, "foobar-prefix");
+ assert_null(line->source);
assert_strcmp(line->command, "TEST");
assert_strcmp(line->args[0], "arg0");
assert_strnull(line->args[1]);
@@ -486,6 +492,7 @@
assert_success(irc_conn_add_cmd_handlers(conn, _conn_handlers, &ctx));
// test on_TEST handler
+ // XXX: come up with a better prefix
log_info("test irc_conn.handlers");
test_sock_push(sock, ":foobar-prefix TEST arg0\r\n");
assert(ctx.on_TEST);
@@ -836,7 +843,9 @@
{ "dump_str", &test_dump_str },
{ "sock_test", &test_sock_test },
{ "line_proto", &test_line_proto },
+ // XXX: irc_line_parse_invalid_prefix
{ "irc_conn", &test_irc_conn },
+ // XXX: irc_conn_self_nick
{ "irc_net", &test_irc_net },
{ "irc_chan_add_offline", &test_irc_chan_add_offline },
{ "irc_chan_namreply", &test_irc_chan_namreply },