# HG changeset patch # User Tero Marttila # Date 1236640272 -7200 # Node ID aec062af155d3e9e354f0776d5f79ea2c9da560b # Parent 56367df4ce5b40f9dcc8a8e677783c89f8debaf5 add irc_chan module diff -r 56367df4ce5b -r aec062af155d Makefile --- a/Makefile Mon Mar 09 16:30:59 2009 +0200 +++ b/Makefile Tue Mar 10 01:11:12 2009 +0200 @@ -38,7 +38,7 @@ SOCK_OBJS = obj/sock.o obj/sock_tcp.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 +IRC_OBJS = obj/irc_line.o obj/irc_conn.o obj/irc_net.o obj/irc_chan.o IRC_LOG_OBJS = obj/irc_log.o # XXX: not yet there diff -r 56367df4ce5b -r aec062af155d src/irc_chan.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/irc_chan.c Tue Mar 10 01:11:12 2009 +0200 @@ -0,0 +1,48 @@ +#include "irc_chan.h" + +#include +#include + +const char* irc_chan_name (struct irc_chan *chan) +{ + return chan->info.channel; +} + +err_t irc_chan_create (struct irc_chan **chan_ptr, struct irc_net *net, const struct irc_chan_info *info, struct error_info *err) +{ + struct irc_chan *chan; + + // allocate + if ((chan = calloc(1, sizeof(*chan))) == NULL) + return SET_ERROR(err, ERR_CALLOC); + + // store + chan->net = net; + chan->info = *info; + chan->state = IRC_CHAN_INIT; + + // ok + *chan_ptr = chan; + + return SUCCESS; +} + +err_t irc_chan_join (struct irc_chan *chan) +{ + err_t err; + + // XXX: error instead? + assert(chan->state == IRC_CHAN_INIT); + + // send JOIN message on the appropriate connection + if ((err = irc_conn_JOIN(chan->net->conn, chan->info.channel))) + // XXX: state? + return err; + + // ok, joining + chan->state = IRC_CHAN_JOINING; + + // done + return SUCCESS; +} + diff -r 56367df4ce5b -r aec062af155d src/irc_chan.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/irc_chan.h Tue Mar 10 01:11:12 2009 +0200 @@ -0,0 +1,82 @@ +#ifndef IRC_CHAN_H +#define IRC_CHAN_H + +/** + * @file + * + * Support for IRC channels, including tracking their state and actions on them. + */ +struct irc_chan_info; +struct irc_chan; + +#include "irc_net.h" +#include "error.h" +#include + +/** + * IRC channel info, as required to create an irc_chan + */ +struct irc_chan_info { + /** Channel name, with the [#&!] prefix */ + const char *channel; + +}; + +/** + * General IRC channel states + */ +enum irc_chan_state { + /** Initialized, but idle */ + IRC_CHAN_INIT, + + /** JOIN request sent */ + IRC_CHAN_JOINING, + + /** Currently joined to the channel */ + IRC_CHAN_JOINED, +}; + +/** + * IRC channel state + */ +struct irc_chan { + /** The irc_net.channels list */ + TAILQ_ENTRY(irc_chan) node; + + /* The network we're on */ + struct irc_net *net; + + /** Our identifying info */ + struct irc_chan_info info; + + /** Current state */ + enum irc_chan_state state; +}; + +/** + * Return the channel's name + */ +const char* irc_chan_name (struct irc_chan *chan); + +/** + * Build/initialize a new irc_chan struct. This does not have any external side-effects. + * + * The channel will be in the IRC_CHAN_INIT state after this. + * + * @param chan_ptr the new irc_chan is returned via this pointer + * @param net the irc_net this channel is on + * @param info the channel's identifying information + * @param err error codes are returned via this + */ +err_t irc_chan_create (struct irc_chan **chan_ptr, struct irc_net *net, const struct irc_chan_info *info, struct error_info *err); + +/** + * Send the initial JOIN message. + * + * The channel must be in the IRC_CHAN_INIT state, and will transition to the IRC_CHAN_JOINING state. + * + * @param chan the channel to JOIN + */ +err_t irc_chan_join (struct irc_chan *chan); + +#endif diff -r 56367df4ce5b -r aec062af155d src/irc_log.c --- a/src/irc_log.c Mon Mar 09 16:30:59 2009 +0200 +++ b/src/irc_log.c Tue Mar 10 01:11:12 2009 +0200 @@ -18,6 +18,9 @@ { struct irc_log_ctx *ctx = arg; + (void) conn; + (void) ctx; + // log it! :P log_debug("%s: %s: %s", line->prefix, line->args[0], line->args[1]); } @@ -27,29 +30,26 @@ { NULL, NULL } }; -err_t irc_log_init (struct event_base *ev_base, const char *db_info, struct irc_conn *irc, const char *channel) +err_t irc_log_init (struct event_base *ev_base, const struct irc_log_info *info) { struct irc_log_ctx *ctx = &_ctx; err_t err; // open the database connection - if (db_info) { - log_info("connect to database: %s", db_info); + if (info->db_info) { + log_info("connect to database: %s", info->db_info); - if ((ctx->db = evsql_new_pq(ev_base, db_info, NULL, NULL)) == NULL) + if ((ctx->db = evsql_new_pq(ev_base, info->db_info, NULL, NULL)) == NULL) return ERR_EVSQL_NEW_PQ; } - if (channel) { - log_info("join channel: %s", channel); - - // join the channel - if ((err = irc_conn_JOIN(irc, channel))) - return err; + if (info->channel) { + log_info("log channel: %s", irc_chan_name(info->channel)); } // register for events - if ((err = irc_conn_register_handler_chain(irc, _cmd_handlers, ctx))) + // XXX: need irc_chan API + if ((err = irc_conn_register_handler_chain(info->channel->net->conn, _cmd_handlers, ctx))) return err; // ok diff -r 56367df4ce5b -r aec062af155d src/irc_log.h --- a/src/irc_log.h Mon Mar 09 16:30:59 2009 +0200 +++ b/src/irc_log.h Tue Mar 10 01:11:12 2009 +0200 @@ -6,16 +6,26 @@ * * Logging IRC events to an SQL database */ - #include "error.h" -#include "irc_conn.h" +#include "irc_chan.h" #include /** - * Initialize the global irc_log state + * Configuration state for irc_log + */ +struct irc_log_info { + /** Database connection string */ + const char *db_info; + + /** The channel to log */ + struct irc_chan *channel; +}; + +/** + * Initialize the global irc_log module to use the given configuration * * XXX: db_info is still unused if not specified */ -err_t irc_log_init (struct event_base *ev_base, const char *db_info, struct irc_conn *irc, const char *channel); +err_t irc_log_init (struct event_base *ev_base, const struct irc_log_info *info); #endif diff -r 56367df4ce5b -r aec062af155d src/irc_net.c --- a/src/irc_net.c Mon Mar 09 16:30:59 2009 +0200 +++ b/src/irc_net.c Tue Mar 10 01:11:12 2009 +0200 @@ -2,6 +2,7 @@ #include "log.h" #include +#include err_t irc_net_create (struct irc_net **net_ptr, const struct irc_net_info *info, struct error_info *err) { @@ -12,6 +13,9 @@ if ((net = calloc(1, sizeof(*net))) == NULL) return SET_ERROR(err, ERR_CALLOC); + // initialize + TAILQ_INIT(&net->channels); + // XXX: over-simplified blocking connect if (info->use_ssl) { log_info("connecting to [%s]:%s using SSL", info->hostname, info->service); @@ -44,3 +48,41 @@ return ERROR_CODE(err); } +struct irc_chan* irc_net_add_chan (struct irc_net *net, const struct irc_chan_info *info) +{ + struct irc_chan *chan; + struct error_info err; + + // create the new irc_chan struct + if (irc_chan_create(&chan, net, info, &err)) + // XXX: we lose error info + return NULL; + + // add to network list + TAILQ_INSERT_TAIL(&net->channels, chan, node); + + // then join + if ((ERROR_CODE(&err) = irc_chan_join(chan))) + // XXX + return NULL; + + // ok, return + return chan; +} + +struct irc_chan* irc_net_get_chan (struct irc_net *net, const char *channel) +{ + struct irc_chan *chan = NULL; + + // look for it... + TAILQ_FOREACH(chan, &net->channels, node) { + if (strcasecmp(chan->info.channel, channel) == 0) + // found it + return chan; + } + + // no such channel + return NULL; + +} + diff -r 56367df4ce5b -r aec062af155d src/irc_net.h --- a/src/irc_net.h Mon Mar 09 16:30:59 2009 +0200 +++ b/src/irc_net.h Tue Mar 10 01:11:12 2009 +0200 @@ -9,6 +9,8 @@ */ #include "error.h" #include "irc_conn.h" +#include "irc_chan.h" +#include /** * Configuration info for an IRC network @@ -37,14 +39,32 @@ /* The current connection */ struct irc_conn *conn; - + /** The list of IRC channel states */ + TAILQ_HEAD(irc_net_chan_list, irc_chan) channels; }; /** * Create a new IRC network state, using the given network info to connect/register. * * Errors are returned via *err, also returning the error code. + * + * @param net the new irc_net struct is returned via this pointer + * @param info network informated, used to connect and register + * @param err used to return extended error information */ err_t irc_net_create (struct irc_net **net, const struct irc_net_info *info, struct error_info *err); +/** + * Create a new irc_chan, add it to our channel list, and send the JOIN request. + */ +struct irc_chan* irc_net_add_chan (struct irc_net *net, const struct irc_chan_info *info); + +/** + * Look up an existing irc_chan by name, returning NULL if not found. + * + * @param net the network state + * @param channel the channel name + */ +struct irc_chan* irc_net_get_chan (struct irc_net *net, const char *channel); + #endif diff -r 56367df4ce5b -r aec062af155d src/nexus.c --- a/src/nexus.c Mon Mar 09 16:30:59 2009 +0200 +++ b/src/nexus.c Tue Mar 10 01:11:12 2009 +0200 @@ -62,7 +62,15 @@ .realname = "SpBot (development version)", } }; - const char *log_database = NULL, *log_channel = NULL; + + struct irc_chan_info log_chan_info = { + .channel = NULL, + }; + + struct irc_log_info log_info = { + .db_info = NULL, + .channel = NULL, + }; bool port_default = true; @@ -91,11 +99,11 @@ break; case OPT_LOG_DATABASE: - log_database = optarg; + log_info.db_info = optarg; break; case OPT_LOG_CHANNEL: - log_channel = optarg; + log_chan_info.channel = optarg; break; case '?': @@ -117,8 +125,13 @@ FATAL_ERROR(&err, "irc_net_create"); // logging? - if (log_database || log_channel) { - if ((ERROR_CODE(&err) = irc_log_init(ev_base, log_database, net->conn, log_channel))) + if (log_info.db_info || log_chan_info.channel) { + // get the channel + if (log_chan_info.channel && (log_info.channel = irc_net_add_chan(net, &log_chan_info)) == NULL) + FATAL("irc_net_add_chan"); + + // init the irc_log module + if ((ERROR_CODE(&err) = irc_log_init(ev_base, &log_info))) FATAL_ERROR(&err, "irc_log_init"); }