some irc_net code to use said async connects
authorTero Marttila <terom@fixme.fi>
Mon, 30 Mar 2009 01:31:13 +0300
changeset 86 5e7e64544cb7
parent 85 75bc8b164ef8
child 87 f0db6ebf18b9
some irc_net code to use said async connects
src/irc_net.c
src/irc_net.h
--- a/src/irc_net.c	Mon Mar 30 01:31:00 2009 +0300
+++ b/src/irc_net.c	Mon Mar 30 01:31:13 2009 +0300
@@ -25,7 +25,7 @@
     net->conn = NULL;
 
     // update channel state
-    TAILQ_FOREACH(chan, &net->channels, node) {
+    TAILQ_FOREACH(chan, &net->channels, net_channels) {
         // XXX: notify channel somehow
     }
 
@@ -64,7 +64,7 @@
     (void) conn;
 
     // join our channels
-    TAILQ_FOREACH(chan, &net->channels, node) {
+    TAILQ_FOREACH(chan, &net->channels, net_channels) {
         if ((ERROR_CODE(&err) = irc_chan_join(chan)))
             // XXX: this should be some kind of irc_chan_error instead
             irc_net_error(net, &err);
@@ -162,7 +162,7 @@
     struct irc_chan *chan;
     
     // scan each channel
-    TAILQ_FOREACH(chan, &net->channels, node) {
+    TAILQ_FOREACH(chan, &net->channels, net_channels) {
         if (irc_chan_get_user(chan, line->source->nickname)) {
             // propagate
             irc_cmd_invoke(&chan->handlers, line);
@@ -240,6 +240,45 @@
     {   NULL,               NULL                    }
 };
 
+/**
+ * The given socket is now connected, so create the irc_conn and bind it in to us
+ */
+static err_t irc_net_connected (struct irc_net *net, struct sock_stream *sock, struct error_info *err)
+{
+    // create the irc connection state
+    if (irc_conn_create(&net->conn, sock, &_conn_callbacks, net, err))
+        return ERROR_CODE(err);
+
+    // add our command handlers
+    if ((ERROR_CODE(err) = irc_conn_add_cmd_handlers (net->conn, _cmd_handlers, net)))
+        return ERROR_CODE(err);
+
+    // register
+    if ((ERROR_CODE(err) = irc_conn_register(net->conn, &net->info.register_info)))
+        return ERROR_CODE(err);
+
+    // ok
+    return SUCCESS;
+}
+
+static void irc_net_on_connect (struct sock_stream *sock, struct error_info *conn_err, void *arg)
+{
+    struct irc_net *net = arg;
+    struct error_info err;
+
+    // XXX: better error handling
+    
+    // trap errors
+    if (conn_err)
+        FATAL_ERROR(conn_err, "async TCP connect failed");
+    
+    // ok, yay
+    if (irc_net_connected(net, sock, &err))
+        FATAL_ERROR(&err, "irc_net_connected failed");
+
+    // XXX: cleanup
+}
+
 err_t irc_net_create (struct irc_net **net_ptr, const struct irc_net_info *info, struct error_info *err)
 {
     struct irc_net *net;
@@ -254,41 +293,35 @@
     TAILQ_INIT(&net->channels);
     LIST_INIT(&net->users);
 
-    if (info->raw_sock) {
-        log_debug("connected using raw socket: %p", info->raw_sock);
-
-        sock = info->raw_sock;
+    // non-async socket connect?
+    if (info->raw_sock || info->use_ssl) {
+        // create the socket
+        if (info->raw_sock) {
+            log_debug("connected using raw socket: %p", info->raw_sock);
 
-    } else if (info->use_ssl) {
-        log_debug("connecting to [%s]:%s using SSL", info->hostname, info->service);
+            sock = info->raw_sock;
 
-        // XXX: over-simplified blocking connect
-        if (sock_ssl_connect(&sock, info->hostname, info->service, err))
+        } else if (info->use_ssl) {
+            log_debug("connecting to [%s]:%s using SSL", info->hostname, info->service);
+
+            // XXX: over-simplified blocking connect
+            if (sock_ssl_connect(&sock, info->hostname, info->service, err))
+                goto error;
+        }
+
+        // then create the conn right away
+        if (irc_net_connected(net, sock, err))
             goto error;
 
     } else {
         log_debug("connecting to [%s]:%s", info->hostname, info->service);
-
-        // XXX: over-simplified blocking connect
-        if (sock_tcp_connect(&sock, info->hostname, info->service, err))
+            
+        // begin async connect
+        if (sock_tcp_connect_async(&sock, info->hostname, info->service, &irc_net_on_connect, net, err))
             goto error;
-
+        
     }
 
-    // create the irc connection state
-    if (irc_conn_create(&net->conn, sock, &_conn_callbacks, net, err))
-        goto error;
-
-    // add our command handlers
-    if ((ERROR_CODE(err) = irc_conn_add_cmd_handlers (net->conn, _cmd_handlers, net)))
-        goto error;
-
-    // register
-    log_debug("connected, registering");
-
-    if ((ERROR_CODE(err) = irc_conn_register(net->conn, &info->register_info)))
-        goto error;
-    
     // ok
     *net_ptr = net;
 
@@ -316,7 +349,7 @@
     // our channels
     while (next) {
         chan = next;
-        next = TAILQ_NEXT(chan, node);
+        next = TAILQ_NEXT(chan, net_channels);
 
         irc_chan_destroy(chan);
     }
@@ -336,7 +369,7 @@
         return ERROR_CODE(err);
     
     // add to network list
-    TAILQ_INSERT_TAIL(&net->channels, chan, node);
+    TAILQ_INSERT_TAIL(&net->channels, chan, net_channels);
     
     // currently connected?
     if (net->conn && net->conn->registered) {
@@ -357,7 +390,7 @@
     struct irc_chan *chan = NULL;
 
     // look for it...
-    TAILQ_FOREACH(chan, &net->channels, node) {
+    TAILQ_FOREACH(chan, &net->channels, net_channels) {
         if (strcasecmp(chan->info.channel, channel) == 0)
             // found it
             return chan;
--- a/src/irc_net.h	Mon Mar 30 01:31:00 2009 +0300
+++ b/src/irc_net.h	Mon Mar 30 01:31:13 2009 +0300
@@ -31,7 +31,7 @@
     /** SSL? */
     bool use_ssl;
 
-    /** Protocol registration info */
+    /** Protocol registration info (nickname etc) */
     struct irc_conn_register_info register_info;
 
     /** Raw socket to use, mainly for testing purposes */
@@ -39,10 +39,18 @@
 };
 
 /**
- * IRC Network state
+ * The persistent IRC network state. This includes the "current" connection (which may change over time), the
+ * identifying info, the list of channels and their state, etc.
+ *
+ * This handles the irc_conn's messages, and propagates relevant messages to the appropriate irc_chan
+ * (using irc_chan::handlers). This includes NICK/QUIT events for users on said channel.
+ *
+ * For NICK events, the event is propagated *before* updating irc_user::nickname.
+ *
+ * XXX: needs some callbacks
  */
 struct irc_net {
-    /* The current connection */
+    /** The current connection */
     struct irc_conn *conn;
 
     /** Our connection info */
@@ -59,7 +67,7 @@
 };
 
 /**
- * Return the networks's name
+ * Return the network's name, as per irc_net_info::network
  */
 const char* irc_net_name (struct irc_net *net);
 
@@ -69,7 +77,7 @@
  * 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 info network information, used to connect and register
  * @param err return error info
  */
 err_t irc_net_create (struct irc_net **net, const struct irc_net_info *info, struct error_info *err);
@@ -83,10 +91,10 @@
 /**
  * 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.
+ * If we are connected and registered, join the channel right away, otherwise, join it once we register.
  *
  * @param net the irc_net the channel is on
- * #param chan_ptr return the new irc_chan via this, if not NULL
+ * @param chan_ptr return the new irc_chan via this, if given
  * @param info the info required to identify and join the channel
  * @param err return error info
  */
@@ -119,6 +127,8 @@
 
 /**
  * Quit from the IRC network, this sends a QUIT message to the server, and waits for the connection to be closed cleanly.
+ *
+ * XXX: nothing to indicate completion
  */
 err_t irc_net_quit (struct irc_net *net, const char *message);