# HG changeset patch # User Tero Marttila # Date 1236875705 -7200 # Node ID 0c2e0cb46c3a6aa15c04bd352a39bde0e35f09ee # Parent 4fe4a3c4496e206ef15982b83b05336f0255463c implement irc_chan_callbacks, and add on_msg diff -r 4fe4a3c4496e -r 0c2e0cb46c3a src/irc_chan.c --- 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 + */ +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; diff -r 4fe4a3c4496e -r 0c2e0cb46c3a src/irc_chan.h --- 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. diff -r 4fe4a3c4496e -r 0c2e0cb46c3a src/irc_log.c --- 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; } diff -r 4fe4a3c4496e -r 0c2e0cb46c3a src/irc_net.c --- 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 - */ -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 + * + * 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 } };