--- a/src/irc_chan.c Thu Mar 12 18:11:44 2009 +0200
+++ b/src/irc_chan.c Thu Mar 12 18:35:05 2009 +0200
@@ -24,17 +24,30 @@
chan->state.joined = true;
log_info("joined channel: %s", chan->info.channel);
+
+ // invoke callback
+ IRC_CHAN_INVOKE_CALLBACK(chan, on_self_join);
+ }
+}
- // TODO: callbacks
- }
+/**
+ * :nm PRIVMSG <channel> <message>
+ */
+static void irc_chan_on_PRIVMSG (const struct irc_line *line, void *arg)
+{
+ struct irc_chan *chan = arg;
+
+ // invoke callback (prefix, message)
+ IRC_CHAN_INVOKE_CALLBACK(chan, on_msg, line->prefix, line->args[1]);
}
/**
* Core command handlers
*/
struct irc_cmd_handler _cmd_handlers[] = {
- { "JOIN", &irc_chan_on_JOIN },
- { NULL, NULL }
+ { "JOIN", &irc_chan_on_JOIN },
+ { "PRIVMSG", &irc_chan_on_PRIVMSG },
+ { NULL, NULL }
};
err_t irc_chan_create (struct irc_chan **chan_ptr, struct irc_net *net, const struct irc_chan_info *info, struct error_info *err)
@@ -51,6 +64,7 @@
// init
irc_cmd_init(&chan->handlers);
+ CHAIN_INIT(&chan->callbacks);
// add handlers
if ((ERROR_CODE(err) = irc_cmd_add(&chan->handlers, _cmd_handlers, chan)))
@@ -73,10 +87,18 @@
// free command handlers
irc_cmd_free(&chan->handlers);
+ // free callbacks
+ chain_free(&chan->callbacks);
+
// free chan itself
free(chan);
}
+err_t irc_chan_add_callbacks (struct irc_chan *chan, const struct irc_chan_callbacks *callbacks, void *arg)
+{
+ return chain_add(&chan->callbacks, callbacks, arg);
+}
+
err_t irc_chan_join (struct irc_chan *chan)
{
err_t err;
--- a/src/irc_chan.h Thu Mar 12 18:11:44 2009 +0200
+++ b/src/irc_chan.h Thu Mar 12 18:35:05 2009 +0200
@@ -29,9 +29,27 @@
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);
};
/**
+ * Invoke the given callback with the given args
+ */
+#define IRC_CHAN_INVOKE_CALLBACK(chan, _cb_name_, ...) \
+ do { \
+ struct chain_head *head; \
+ \
+ CHAIN_FOREACH(&(chan)->callbacks, head) { \
+ const struct irc_chan_callbacks *callbacks = head->chain; \
+ \
+ if (callbacks->_cb_name_) \
+ callbacks->_cb_name_((chan), ## __VA_ARGS__, head->arg); \
+ } \
+ } while (0);
+
+/**
* IRC channel state
*/
struct irc_chan {
@@ -56,6 +74,9 @@
/** General command handlers */
irc_cmd_handlers_t handlers;
+
+ /** High-level user callbacks */
+ struct chain_list callbacks;
};
/**
@@ -81,6 +102,11 @@
void irc_chan_destroy (struct irc_chan *chan);
/**
+ * Add high-level irc_chan callbacks
+ */
+err_t irc_chan_add_callbacks (struct irc_chan *chan, const struct irc_chan_callbacks *callbacks, void *arg);
+
+/**
* Send the initial JOIN message.
*
* The channel must be in the IRC_CHAN_INIT state, and will transition to the IRC_CHAN_JOINING state.
--- a/src/irc_log.c Thu Mar 12 18:11:44 2009 +0200
+++ b/src/irc_log.c Thu Mar 12 18:35:05 2009 +0200
@@ -14,19 +14,18 @@
} _ctx;
-static void on_PRIVMSG (const struct irc_line *line, void *arg)
+static void on_chan_msg (struct irc_chan *chan, const char *prefix, const char *message, void *arg)
{
struct irc_log_ctx *ctx = arg;
(void) ctx;
// log it! :P
- log_debug("%s: %s: %s", line->prefix, line->args[0], line->args[1]);
+ log_debug("%s: %s: %s", prefix, irc_chan_name(chan), message);
}
-static struct irc_cmd_handler _cmd_handlers[] = {
- { "PRIVMSG", &on_PRIVMSG },
- { NULL, NULL }
+static struct irc_chan_callbacks _chan_callbacks = {
+ .on_msg = on_chan_msg,
};
err_t irc_log_init (struct event_base *ev_base, const struct irc_log_info *info)
@@ -46,12 +45,16 @@
log_info("log channel: %s", irc_chan_name(info->channel));
}
- // register for events
- // XXX: need irc_chan API for this
- if ((err = irc_conn_add_cmd_handlers(info->channel->net->conn, _cmd_handlers, ctx)))
- return err;
+ // add channel callbacks
+ if ((err = irc_chan_add_callbacks(info->channel, &_chan_callbacks, ctx)))
+ goto error;
// ok
return SUCCESS;
+
+error:
+ // XXX: cleanup
+
+ return err;
}
--- a/src/irc_net.c Thu Mar 12 18:11:44 2009 +0200
+++ b/src/irc_net.c Thu Mar 12 18:35:05 2009 +0200
@@ -28,16 +28,15 @@
};
/**
- * :nm JOIN <channel>
- */
-static void irc_net_on_JOIN (const struct irc_line *line, void *arg)
+ * Propagate the command to the appropriate irc_chan based on the given name
+ */
+static void irc_net_propagate_chan (struct irc_net *net, const struct irc_line *line, const char *channel)
{
- struct irc_net *net = arg;
struct irc_chan *chan;
// look up channel
- if ((chan = irc_net_get_chan(net, line->args[0])) == NULL) {
- log_warn("unkown channel: %s", line->args[0]);
+ if ((chan = irc_net_get_chan(net, channel)) == NULL) {
+ log_warn("unknown channel: %s", channel);
return;
}
@@ -46,10 +45,41 @@
}
/**
+ * Propagate line to irc_chan based on args[0]
+ */
+static void irc_net_on_chan0 (const struct irc_line *line, void *arg)
+{
+ struct irc_net *net = arg;
+
+ irc_net_propagate_chan(net, line, line->args[0]);
+}
+
+/**
+ * :nm PRIVMSG <target> <message>
+ *
+ * Either propagate to channel if found, otherwise handle as a privmsg
+ */
+static void irc_net_on_PRIVMSG (const struct irc_line *line, void *arg)
+{
+ struct irc_net *net = arg;
+
+ // XXX: does two lookups
+ if (irc_net_get_chan(net, line->args[0])) {
+ // short-circuit to on_chan0
+ irc_net_on_chan0(line, arg);
+
+ } else {
+ // XXX: callbacks for privmsgs
+
+ }
+}
+
+/**
* Our irc_cmd handler list
*/
static struct irc_cmd_handler _cmd_handlers[] = {
- { "JOIN", &irc_net_on_JOIN },
+ { "JOIN", &irc_net_on_chan0 },
+ { "PRIVMSG", &irc_net_on_PRIVMSG },
{ NULL, NULL }
};