--- a/src/error.h Tue Mar 10 01:11:12 2009 +0200
+++ b/src/error.h Tue Mar 10 01:46:09 2009 +0200
@@ -74,6 +74,9 @@
/* irc_line errors */
_ERROR_CODE( ERR_LINE_TOO_LONG, 0x100101, NONE ),
_ERROR_CODE( ERR_LINE_INVALID_TOKEN, 0x100102, NONE ),
+
+ /** irc_conn errors */
+ _ERROR_CODE( ERR_IRC_CONN_REGISTER_STATE, 0x100201, NONE ),
// mask of bits used for the error_code value
_ERROR_CODE_MASK = 0xffffff,
@@ -86,8 +89,8 @@
/* The base error code */
err_t code;
- /* Additional detail info, usually some third-part error code */
- unsigned int extra;
+ /* Additional detail info, usually some third-party error code */
+ int extra;
};
/*
--- a/src/irc_conn.c Tue Mar 10 01:11:12 2009 +0200
+++ b/src/irc_conn.c Tue Mar 10 01:46:09 2009 +0200
@@ -15,9 +15,12 @@
(void) arg;
// update state
+ conn->registering = false;
conn->registered = true;
- log_info("registered");
+ // trigger callback
+ if (conn->callbacks.on_registered)
+ conn->callbacks.on_registered(conn, conn->cb_arg);
}
/*
@@ -78,7 +81,8 @@
}
}
-err_t irc_conn_create (struct irc_conn **conn_ptr, struct sock_stream *sock, const struct irc_conn_config *config, struct error_info *err)
+err_t irc_conn_create (struct irc_conn **conn_ptr, struct sock_stream *sock, const struct irc_conn_callbacks *callbacks,
+ void *cb_arg, struct error_info *err)
{
struct irc_conn *conn;
@@ -86,6 +90,10 @@
if ((conn = calloc(1, sizeof(struct irc_conn))) == NULL)
return SET_ERROR(err, ERR_CALLOC);
+ // init state
+ conn->callbacks = *callbacks;
+ conn->cb_arg = cb_arg;
+
// initialize command handlers
STAILQ_INIT(&conn->handlers);
@@ -97,13 +105,6 @@
if (line_proto_create(&conn->lp, sock, IRC_LINE_MAX * 1.5, &irc_conn_on_line, conn, err))
return ERROR_CODE(err);
- // send the initial messages
- if (
- irc_conn_NICK(conn, config->nickname)
- || irc_conn_USER(conn, config->username, config->realname)
- )
- return ERROR_CODE(err);
-
// ok
*conn_ptr = conn;
@@ -129,6 +130,29 @@
return SUCCESS;
}
+err_t irc_conn_register (struct irc_conn *conn, const struct irc_conn_register_info *info)
+{
+ err_t err;
+
+ // assert state
+ if (conn->registering || conn->registered)
+ // XXX: stupid error code
+ return ERR_IRC_CONN_REGISTER_STATE;
+
+ // send the initial messages
+ if (
+ (err = irc_conn_NICK(conn, info->nickname))
+ || (err = irc_conn_USER(conn, info->username, info->realname))
+ )
+ return err;
+
+ // set state
+ conn->registering = true;
+
+ // ok
+ return SUCCESS;
+}
+
err_t irc_conn_send (struct irc_conn *conn, const struct irc_line *line)
{
char line_buf[IRC_LINE_MAX + 2];
--- a/src/irc_conn.h Tue Mar 10 01:11:12 2009 +0200
+++ b/src/irc_conn.h Tue Mar 10 01:46:09 2009 +0200
@@ -18,28 +18,12 @@
#include "irc_cmd.h"
#include <stdbool.h>
-/*
- * Connection state
- */
-struct irc_conn {
- /* We are a line-based protocol */
- struct line_proto *lp;
-
- /* Registered (as in, we have a working nickname)? */
- bool registered;
-
- /* Command handlers */
- STAILQ_HEAD(irc_conn_handlers, irc_cmd_chain) handlers;
-};
-
-// XXX: this should probably be slightly reworked
-
/**
* The configuration info for an IRC connection.
*
* XXX: this should probably be reworked, maybe as a separate irc_conn_register function?
*/
-struct irc_conn_config {
+struct irc_conn_register_info {
/* Nickname to use on that server */
const char *nickname;
@@ -51,30 +35,74 @@
};
/**
- * Create a new irc_conn using the given sock_stream, which should be connected to an IRC server. The parameters given
- * in \a config will be used to identify with the IRC server.
+ * Connection state callbacks
+ */
+struct irc_conn_callbacks {
+ /**
+ * irc_conn_register has completed.
+ */
+ void (*on_registered) (struct irc_conn *conn, void *arg);
+};
+
+/*
+ * Connection state
+ */
+struct irc_conn {
+ /* We are a line-based protocol */
+ struct line_proto *lp;
+
+ /** Callbacks */
+ struct irc_conn_callbacks callbacks;
+
+ /** Opaque argument for callbacks */
+ void *cb_arg;
+
+ /** Registration request sent */
+ bool registering;
+
+ /* Registered (as in, we have a working nickname)? */
+ bool registered;
+
+ /* Command handlers */
+ STAILQ_HEAD(irc_conn_handlers, irc_cmd_chain) handlers;
+};
+
+/**
+ * Create a new irc_conn using the given sock_stream, which should be connected to an IRC server.
+ *
+ * This does not yet send any requests to the server, it only sets up the core state. Use irc_conn_register to register
+ * with the server.
*
* On success, the resulting irc_conn is returned via *conn with SUCCESS. Otherwise, -ERR_* and error info is returned
* via *err.
*
* @param conn the new irc_conn structure is returned via this pointer
* @param sock the socket connected to the IRC server
- * @param config the basic information used to register
* @param err errors are returned via this pointer
* @return error code
*/
-err_t irc_conn_create (struct irc_conn **conn, struct sock_stream *sock, const struct irc_conn_config *config, struct error_info *err);
+err_t irc_conn_create (struct irc_conn **conn, struct sock_stream *sock, const struct irc_conn_callbacks *callbacks,
+ void *cb_arg, struct error_info *err);
/**
* Add a new chain of command handler callbacks to be used to handle irc_lines from the server. The given arg will be
* passed to the callbacks as the context argument. The chain will be appended to the end of the current list of chains.
*
+ * XXX: rename to not conflict with irc_conn_register()
+ *
* @param chain the array of irc_cmd_handler structs, terminated with a NULL entry
* @param arg the context argument to use for the callbacks
*/
err_t irc_conn_register_handler_chain (struct irc_conn *conn, struct irc_cmd_handler *handlers, void *arg);
/**
+ * Register with the IRC server using the given registration info (initial nickname etc.)
+ *
+ * This sends the NICK/USER command sequence.
+ */
+err_t irc_conn_register (struct irc_conn *conn, const struct irc_conn_register_info *info);
+
+/**
* @group Simple request functions
*
* The error handling of these functions is such that the error return code is can be used or ignored as convenient,
--- a/src/irc_net.c Tue Mar 10 01:11:12 2009 +0200
+++ b/src/irc_net.c Tue Mar 10 01:46:09 2009 +0200
@@ -4,6 +4,29 @@
#include <stdlib.h>
#include <string.h>
+static void irc_net_conn_registered (struct irc_conn *conn, void *arg)
+{
+ struct irc_net *net = arg;
+ struct irc_chan *chan = NULL;
+ err_t err;
+
+ (void) conn;
+
+ // join our channels
+ TAILQ_FOREACH(chan, &net->channels, node) {
+ if ((err = irc_chan_join(chan)))
+ // XXX: fuck...
+ FATAL_ERR(err, "irc_chan_join failed");
+ }
+}
+
+/**
+ * Our irc_conn_callbacks list
+ */
+struct irc_conn_callbacks _conn_callbacks = {
+ .on_registered = &irc_net_conn_registered,
+};
+
err_t irc_net_create (struct irc_net **net_ptr, const struct irc_net_info *info, struct error_info *err)
{
struct irc_net *net;
@@ -34,7 +57,11 @@
log_info("connected, registering");
// create the irc connection state
- if (irc_conn_create(&net->conn, sock, &info->register_info, err))
+ if (irc_conn_create(&net->conn, sock, &_conn_callbacks, net, err))
+ goto error;
+
+ // register
+ if ((ERROR_CODE(err) = irc_conn_register(net->conn, &info->register_info)))
goto error;
// ok
@@ -60,11 +87,14 @@
// add to network list
TAILQ_INSERT_TAIL(&net->channels, chan, node);
-
- // then join
- if ((ERROR_CODE(&err) = irc_chan_join(chan)))
- // XXX
- return NULL;
+
+ // currently connected?
+ if (net->conn && net->conn->registered) {
+ // then join
+ if ((ERROR_CODE(&err) = irc_chan_join(chan)))
+ // XXX
+ return NULL;
+ }
// ok, return
return chan;
--- a/src/irc_net.h Tue Mar 10 01:11:12 2009 +0200
+++ b/src/irc_net.h Tue Mar 10 01:46:09 2009 +0200
@@ -29,7 +29,7 @@
bool use_ssl;
/** Protocol registration info */
- struct irc_conn_config register_info;
+ struct irc_conn_register_info register_info;
};
/**
@@ -55,7 +55,9 @@
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.
+ * Create a new irc_chan and add it to our channel list.
+ *
+ * If we are connected and registered, JOIN the channel right away, otherwise, join it once we register.
*/
struct irc_chan* irc_net_add_chan (struct irc_net *net, const struct irc_chan_info *info);
--- a/src/line_proto.c Tue Mar 10 01:11:12 2009 +0200
+++ b/src/line_proto.c Tue Mar 10 01:46:09 2009 +0200
@@ -47,6 +47,8 @@
struct line_proto *lp = arg;
char *line;
+ (void) sock;
+
// sanity-check
assert(lp->tail_offset < lp->buf_len);
@@ -73,11 +75,13 @@
static void line_proto_on_write (struct sock_stream *sock, void *arg)
{
struct line_proto *lp = arg;
- err_t err;
+ int ret;
+
+ (void) sock;
// just flush
- if ((err = line_proto_flush(lp)) < 0)
- FATAL_ERR(err, "line_proto_flush");
+ if ((ret = line_proto_flush(lp)) < 0)
+ FATAL_ERR(-ret, "line_proto_flush");
}
/*
@@ -151,7 +155,7 @@
*
*/
int _parse_line (char *buf, size_t len, size_t *hint) {
- int i, next = 0;
+ size_t i, next = 0;
// empty buffer -> nothing
if (len == 0)
--- a/src/sock_gnutls.c Tue Mar 10 01:11:12 2009 +0200
+++ b/src/sock_gnutls.c Tue Mar 10 01:46:09 2009 +0200
@@ -67,6 +67,9 @@
static void sock_gnutls_event_handler (int fd, short what, void *arg)
{
struct sock_gnutls *sock = arg;
+
+ (void) fd;
+ (void) what;
// gnutls might be able to proceed now, so ask user to try what didn't work before now, using the mask given to
// event_enable().
@@ -126,10 +129,12 @@
* Our sock_stream_Type
*/
struct sock_stream_type sock_gnutls_type = {
- .methods.read = &sock_gnutls_read,
- .methods.write = &sock_gnutls_write,
- .methods.event_init = &sock_gnutls_event_init,
- .methods.event_enable = &sock_gnutls_event_enable,
+ .methods = {
+ .read = &sock_gnutls_read,
+ .write = &sock_gnutls_write,
+ .event_init = &sock_gnutls_event_init,
+ .event_enable = &sock_gnutls_event_enable,
+ },
};
/*
@@ -153,7 +158,7 @@
// XXX: log func
void _log (int level, const char *msg)
{
- printf("gnutls: %s\n", msg);
+ printf("gnutls: %d: %s", level, msg);
}
err_t sock_gnutls_global_init (struct error_info *err)
@@ -204,7 +209,7 @@
JUMP_SET_ERROR_INFO(err, SOCK_GNUTLS_ERR(sock));
// bind default transport functions (recv/send) to use the TCP fd
- gnutls_transport_set_ptr(sock->session, (gnutls_transport_ptr_t) sock->base_tcp.fd);
+ gnutls_transport_set_ptr(sock->session, (gnutls_transport_ptr_t) (long int) sock->base_tcp.fd);
// perform the handshake
if ((ERROR_EXTRA(err) = gnutls_handshake(sock->session)) < 0)
--- a/src/sock_tcp.c Tue Mar 10 01:11:12 2009 +0200
+++ b/src/sock_tcp.c Tue Mar 10 01:46:09 2009 +0200
@@ -17,6 +17,8 @@
{
struct sock_tcp *sock = arg;
+ (void) fd;
+
// invoke appropriate callback
sock_stream_invoke_callbacks(SOCK_TCP_BASE(sock), what);
}
@@ -111,10 +113,12 @@
* Our sock_stream_type
*/
struct sock_stream_type sock_tcp_type = {
- .methods.read = &sock_tcp_read,
- .methods.write = &sock_tcp_write,
- .methods.event_init = &sock_tcp_event_init,
- .methods.event_enable = &sock_tcp_event_enable,
+ .methods = {
+ .read = &sock_tcp_read,
+ .write = &sock_tcp_write,
+ .event_init = &sock_tcp_event_init,
+ .event_enable = &sock_tcp_event_enable,
+ },
};
err_t sock_tcp_alloc (struct sock_tcp **sock_ptr)