--- 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
--- /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 <stdlib.h>
+#include <assert.h>
+
+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;
+}
+
--- /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 <sys/queue.h>
+
+/**
+ * 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
--- 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
--- 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 <event2/event.h>
/**
- * 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
--- 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 <stdlib.h>
+#include <string.h>
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;
+
+}
+
--- 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 <sys/queue.h>
/**
* 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
--- 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");
}