--- a/Makefile Fri Mar 13 15:22:46 2009 +0200
+++ b/Makefile Fri Mar 13 16:10:48 2009 +0200
@@ -39,7 +39,7 @@
SOCK_TEST_OBJS = obj/sock_test.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 obj/irc_chan.o obj/irc_cmd.o obj/irc_proto.o
+IRC_OBJS = obj/irc_line.o obj/irc_conn.o obj/irc_net.o obj/irc_chan.o obj/irc_cmd.o obj/irc_proto.o obj/irc_client.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_client.c Fri Mar 13 16:10:48 2009 +0200
@@ -0,0 +1,92 @@
+#include "irc_client.h"
+#include "log.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+err_t irc_client_create (struct irc_client **client_ptr, struct error_info *err)
+{
+ struct irc_client *client;
+
+ // allocate
+ if ((client = calloc(1, sizeof(*client))) == NULL)
+ return SET_ERROR(err, ERR_CALLOC);
+
+ // init
+ TAILQ_INIT(&client->networks);
+
+ // ok
+ *client_ptr = client;
+
+ return SUCCESS;
+}
+
+void irc_client_destroy (struct irc_client *client)
+{
+ struct irc_net *next = TAILQ_FIRST(&client->networks), *net;
+
+ // our networks
+ while (next) {
+ net = next;
+ next = TAILQ_NEXT(net, client_networks);
+
+ irc_net_destroy(net);
+ }
+
+ // ourselves
+ free(client);
+}
+
+err_t irc_client_add_net (struct irc_client *client, struct irc_net **net_ptr, struct irc_net_info *net_info)
+{
+ struct irc_net *net;
+ struct error_info err;
+
+ // create the new irc_chan struct
+ if (irc_net_create(&net, net_info, &err))
+ return ERROR_CODE(&err);
+
+ // add to network list
+ TAILQ_INSERT_TAIL(&client->networks, net, client_networks);
+
+ // ok
+ *net_ptr = net;
+
+ return SUCCESS;
+}
+
+struct irc_net* irc_client_get_net (struct irc_client *client, const char *network)
+{
+ struct irc_net *net = NULL;
+
+ // look for it...
+ TAILQ_FOREACH(net, &client->networks, client_networks) {
+ if (strcasecmp(net->info.network, network) == 0)
+ // found it
+ return net;
+ }
+
+ // no such network
+ return NULL;
+}
+
+err_t irc_client_quit (struct irc_client *client, const char *message)
+{
+ struct irc_net *net;
+ err_t err;
+
+ // quit each network
+ TAILQ_FOREACH(net, &client->networks, client_networks) {
+ if ((err = irc_net_quit(net, message))) {
+ log_err(err, "irc_net_quit: %s [%s]", net->info.network, message);
+
+ // XXX: destroy it?
+ }
+ }
+
+ // state
+ client->quitting = true;
+
+ // ok
+ return SUCCESS;
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/irc_client.h Fri Mar 13 16:10:48 2009 +0200
@@ -0,0 +1,53 @@
+#ifndef IRC_CLIENT_H
+#define IRC_CLIENT_H
+
+/**
+ * @file
+ *
+ * Defines the high-level, full-featured IRC 'client' state, which essentially manipulates a set of irc_net's
+ */
+#include "irc_net.h"
+#include <sys/queue.h>
+
+/**
+ * The IRC client
+ */
+struct irc_client {
+ /** Our set of configured IRC networks */
+ TAILQ_HEAD(irc_client_networks, irc_net) networks;
+
+ /** Are we in the process of quitting all networks? */
+ bool quitting;
+
+ /** Have we quit all networks? */
+ bool quit;
+};
+
+/**
+ * Construct a new irc_client
+ */
+err_t irc_client_create (struct irc_client **client_ptr, struct error_info *err);
+
+/**
+ * Destroy the irc_client, also destroying all networks
+ */
+void irc_client_destroy (struct irc_client *client);
+
+/**
+ * Add a new IRC network
+ */
+err_t irc_client_add_net (struct irc_client *client, struct irc_net **net_ptr, struct irc_net_info *net_info);
+
+/**
+ * Get a pre-existing IRC network by name
+ */
+struct irc_net* irc_client_get_net (struct irc_client *client, const char *network);
+
+/**
+ * Quit cleanly from all our IRC networks.
+ *
+ * XXX: currently no way to indicate once we've quit all of them
+ */
+err_t irc_client_quit (struct irc_client *client, const char *message);
+
+#endif
--- a/src/irc_net.c Fri Mar 13 15:22:46 2009 +0200
+++ b/src/irc_net.c Fri Mar 13 16:10:48 2009 +0200
@@ -146,6 +146,7 @@
return SET_ERROR(err, ERR_CALLOC);
// initialize
+ net->info = *info;
TAILQ_INIT(&net->channels);
if (info->raw_sock) {
--- a/src/irc_net.h Fri Mar 13 15:22:46 2009 +0200
+++ b/src/irc_net.h Fri Mar 13 16:10:48 2009 +0200
@@ -42,8 +42,14 @@
/* The current connection */
struct irc_conn *conn;
+ /** Our connection info */
+ struct irc_net_info info;
+
/** The list of IRC channel states */
TAILQ_HEAD(irc_net_chan_list, irc_chan) channels;
+
+ /** The irc_client list */
+ TAILQ_ENTRY(irc_net) client_networks;
};
/**
--- a/src/nexus.c Fri Mar 13 15:22:46 2009 +0200
+++ b/src/nexus.c Fri Mar 13 16:10:48 2009 +0200
@@ -1,5 +1,4 @@
-
-#include "irc_net.h"
+#include "nexus.h"
#include "irc_log.h"
#include "signals.h"
#include "log.h"
@@ -10,9 +9,6 @@
#include <getopt.h>
#include <signal.h>
-#include <event2/event.h>
-
-
#define DEFAULT_HOST "irc.fixme.fi"
#define DEFAULT_PORT "6667"
#define DEFAULT_PORT_SSL "6697"
@@ -46,17 +42,6 @@
printf(" --log-channel channel to log\n");
}
-/**
- * Context for async nexus operation
- */
-struct nexus_ctx {
- /** The libevent base */
- struct event_base *ev_base;
-
- /** The one IRC network */
- struct irc_net *net;
-};
-
void on_sigint (evutil_socket_t sig, short what, void *arg)
{
struct nexus_ctx *ctx = arg;
@@ -64,19 +49,19 @@
(void) sig;
(void) what;
- if (ctx->net && ctx->net->conn && !ctx->net->conn->quitting) {
+ if (ctx->client && !ctx->client->quitting) {
log_info("Quitting...");
// quit it
- irc_net_quit(ctx->net, "Goodbye, cruel world ;(");
+ irc_client_quit(ctx->client, "Goodbye, cruel world ;(");
} else {
log_error("Aborting");
// die
- if (ctx->net) {
- irc_net_destroy(ctx->net);
- ctx->net = NULL;
+ if (ctx->client) {
+ irc_client_destroy(ctx->client);
+ ctx->client = NULL;
}
// exit
@@ -87,8 +72,9 @@
int main (int argc, char **argv)
{
int opt, option_index;
+ struct signals *signals;
struct nexus_ctx ctx;
- struct signals *signals;
+ struct irc_net *net;
struct error_info err;
struct irc_net_info net_info = {
@@ -164,9 +150,13 @@
if (sock_init(ctx.ev_base, &err))
FATAL_ERROR(&err, "sock_init");
+ // the IRC client
+ if (irc_client_create(&ctx.client, &err))
+ FATAL_ERROR(&err, "irc_client_create");
+
// the IRC network
- if (irc_net_create(&ctx.net, &net_info, &err))
- FATAL_ERROR(&err, "irc_net_create");
+ if (irc_client_add_net(ctx.client, &net, &net_info))
+ FATAL_ERR(ERROR_CODE(&err), "irc_client_add_net");
// add our signal handlers
if (
@@ -178,7 +168,7 @@
// logging?
if (log_info.db_info || log_chan_info.channel) {
// get the channel
- if (log_chan_info.channel && (log_info.channel = irc_net_add_chan(ctx.net, &log_chan_info)) == NULL)
+ 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
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/nexus.h Fri Mar 13 16:10:48 2009 +0200
@@ -0,0 +1,26 @@
+#ifndef NEXUS_H
+#define NEXUS_H
+
+/**
+ * A nexus is the central brain of the application; the place where the main() method is implemented
+ */
+#include <event2/event.h>
+#include "irc_client.h"
+
+/**
+ * Context for async nexus operation
+ */
+struct nexus_ctx {
+ /** The libevent base */
+ struct event_base *ev_base;
+
+ /** The IRC client state */
+ struct irc_client *client;
+};
+
+/**
+ * The nexus main function, application entry point, etc.
+ */
+int main (int argc, char **argv);
+
+#endif /* NEXUS_H */