[Goodies-commits] r5237 - xfce4-mailwatch-plugin/trunk/libmailwatch-core

Brian Tarricone kelnos at xfce.org
Sat Aug 16 10:48:32 CEST 2008


Author: kelnos
Date: 2008-08-16 08:48:32 +0000 (Sat, 16 Aug 2008)
New Revision: 5237

Modified:
   xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-gmail.c
   xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c
   xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c
Log:
port imap, pop3, and gmail mailboxes to use new network stack

Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-gmail.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-gmail.c	2008-08-16 08:48:21 UTC (rev 5236)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-gmail.c	2008-08-16 08:48:32 UTC (rev 5237)
@@ -78,18 +78,13 @@
 
 #include "mailwatch-utils.h"
 #include "mailwatch.h"
+#include "mailwatch-net-conn.h"
 
 #define BORDER         8
 #define GMAIL_HOST     "mail.google.com"
 #define GMAIL_ATOMURI  "/mail/feed/atom"
 #define XFCE_MAILWATCH_GMAIL_MAILBOX(ptr)  ((XfceMailwatchGMailMailbox *)ptr)
 
-#define GMAIL_CMD_START    GINT_TO_POINTER(1)
-#define GMAIL_CMD_PAUSE    GINT_TO_POINTER(2)
-#define GMAIL_CMD_TIMEOUT  GINT_TO_POINTER(3)
-#define GMAIL_CMD_QUIT     GINT_TO_POINTER(4)
-#define GMAIL_CMD_UPDATE   GINT_TO_POINTER(5)
-
 typedef struct
 {
     XfceMailwatchMailbox mailbox;
@@ -100,27 +95,33 @@
     gchar *password;
     guint timeout;
     
-    GThread *th;
-    GAsyncQueue *aqueue;
-    
     XfceMailwatch *mailwatch;
     
     /* current connection state */
-    gint sockfd;
-    XfceMailwatchSecurityInfo security_info;
+    gint running;
+    gpointer th;
+    XfceMailwatchNetConn *net_conn;
+    guint check_id;
 } XfceMailwatchGMailMailbox;
 
 
+static gboolean
+gmail_should_continue(XfceMailwatchNetConn *net_conn,
+                      gpointer user_data)
+{
+    XfceMailwatchGMailMailbox *gmailbox = user_data;
+    return g_atomic_int_get(&gmailbox->running);
+}
+
 static gssize
 gmail_send(XfceMailwatchGMailMailbox *gmailbox, const gchar *buf)
 {
     GError *error = NULL;
     gssize sent;
     
-    sent = xfce_mailwatch_net_send(gmailbox->sockfd,
-                                   &gmailbox->security_info,
-                                   buf,
-                                   &error);
+    sent = xfce_mailwatch_net_conn_send_data(gmailbox->net_conn,
+                                             (const guchar *)buf, -1,
+                                             &error);
     if(sent < 0) {
         xfce_mailwatch_log_message(gmailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(gmailbox),
@@ -138,12 +139,8 @@
     GError *error = NULL;
     gssize recvd;
     
-    recvd = xfce_mailwatch_net_recv(gmailbox->sockfd,
-                                    &gmailbox->security_info,
-                                    buf,
-                                    len,
-                                    &error);
-    
+    recvd = xfce_mailwatch_net_conn_recv_data(gmailbox->net_conn,
+                                              (guchar *)buf, len, &error);
     if(recvd < 0) {
         xfce_mailwatch_log_message(gmailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(gmailbox),
@@ -156,164 +153,33 @@
 }
 
 static gboolean
-gmail_get_addrinfo(XfceMailwatchGMailMailbox *gmailbox, const gchar *host,
-                  const gchar *service, struct addrinfo **addresses)
+gmail_connect(XfceMailwatchGMailMailbox *gmailbox, gint *port)
 {
     GError *error = NULL;
+
+    TRACE("entering");
     
-    TRACE("entering (%s, %s, %p)", host, service, addresses);
+    g_return_val_if_fail(port, FALSE);
     
-    g_return_val_if_fail(host && service && addresses, FALSE);
+    gmailbox->net_conn = xfce_mailwatch_net_conn_new(GMAIL_HOST, "https");
+    xfce_mailwatch_net_conn_set_should_continue_func(gmailbox->net_conn,
+                                                     gmail_should_continue,
+                                                     gmailbox);
     
-    if(!xfce_mailwatch_net_get_addrinfo(host, service, addresses, &error)) {
+    if(xfce_mailwatch_net_conn_connect(gmailbox->net_conn, &error)) {
+        *port = xfce_mailwatch_net_conn_get_port(gmailbox->net_conn);
+        return TRUE;
+    } else {
         xfce_mailwatch_log_message(gmailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(gmailbox),
                                    XFCE_MAILWATCH_LOG_ERROR,
-                                   error->message);
+                                   "%s", error->message);
         g_error_free(error);
         return FALSE;
     }
-    
-    return TRUE;
 }
 
-
 static gboolean
-gmail_connect(XfceMailwatchGMailMailbox *gmailbox, gint *port)
-{
-    struct addrinfo *addresses = NULL, *ai;
-    gpointer msg = NULL;
-    
-    if(!gmail_get_addrinfo(gmailbox, GMAIL_HOST, "https", &addresses)) {
-        DBG("failed to get sockaddr");
-        return FALSE;
-    }
-    
-    for(ai = addresses; ai; ai = ai->ai_next) {
-        gchar portstr[16];
-        
-        *port = 0;
-        if(!getnameinfo(ai->ai_addr, ai->ai_addrlen, NULL, 0,
-                        portstr, sizeof(portstr), NI_NUMERICSERV))
-        {
-            *port = atoi(portstr);
-        }
-    
-        gmailbox->sockfd = socket(ai->ai_family, ai->ai_socktype,
-                                  ai->ai_protocol);
-        if(gmailbox->sockfd < 0)
-            continue;
-#if 0
-        if(gmailbox->sockfd < 0) {
-            xfce_mailwatch_log_message(gmailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(gmailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       "socket(): %s",
-                                       strerror(errno));
-            DBG("failed to open socket");
-            return FALSE;
-        }
-#endif
-        /* this next batch of crap is necessary because it seems like a failed
-         * connection (that is, one that isn't ECONNREFUSED) takes over 3 minutes
-         * to fail!  if the panel is trying to quit, that's just unacceptable.
-         */
-        
-        if(fcntl(gmailbox->sockfd, F_SETFL,
-                 fcntl(gmailbox->sockfd, F_GETFL) | O_NONBLOCK))
-        {
-            xfce_mailwatch_log_message(gmailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(gmailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       _("Unable to set socket to non-blocking mode.  If the connect attempt hangs, the panel may hang on close."));
-        }
-        
-        if(connect(gmailbox->sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
-            gboolean failed = TRUE;
-            
-            if(errno == EINPROGRESS) {
-                gint iters_left;
-                for(iters_left = 25; iters_left >= 0; iters_left--) {
-                    fd_set wfd;
-                    struct timeval tv = { 2, 0 };
-                    int sock_err = 0;
-                    socklen_t sock_err_len = sizeof(int);
-                    
-                    FD_ZERO(&wfd);
-                    FD_SET(gmailbox->sockfd, &wfd);
-                    
-                    DBG("checking for a connection...");
-                    
-                    /* wait until the connect attempt finishes */
-                    if(select(FD_SETSIZE, NULL, &wfd, NULL, &tv) < 0)
-                        break;
-                    
-                    /* check to see if it finished, and, if so, if there was an
-                     * error, or if it completed successfully */
-                    if(FD_ISSET(gmailbox->sockfd, &wfd)) {
-                        if(!getsockopt(gmailbox->sockfd, SOL_SOCKET, SO_ERROR,
-                                       &sock_err, &sock_err_len)
-                           && !sock_err)
-                        {
-                            DBG("    connection succeeded");
-                            failed = FALSE;
-                        } else {
-#if 0
-                            xfce_mailwatch_log_message(gmailbox->mailwatch,
-                                                       XFCE_MAILWATCH_MAILBOX(gmailbox),
-                                                       XFCE_MAILWATCH_LOG_ERROR,
-                                                       _("Failed to connect to server: %s"),
-                                                       strerror(sock_err));
-#endif
-                            DBG("    connection failed: sock_err is (%d) %s",
-                                sock_err, strerror(sock_err));
-                        }
-                        break;
-                    }
-                    
-                    /* check the main thread to see if we're supposed to quit */
-                    msg = g_async_queue_try_pop(gmailbox->aqueue);
-                    if(msg) {
-                        /* put it back so pop3_check_mail_th() can read it */
-                        g_async_queue_push(gmailbox->aqueue, msg);
-                        if(msg == GMAIL_CMD_QUIT) {
-                            failed = TRUE;
-                            break;
-                        }
-                        msg = NULL;
-                    }
-                }
-            }
-            
-            if(failed) {
-                DBG("failed to connect");
-                close(gmailbox->sockfd);
-                gmailbox->sockfd = -1;
-                continue;
-            } else
-                break;
-        }
-        
-        if(fcntl(gmailbox->sockfd, F_SETFL,
-                 fcntl(gmailbox->sockfd, F_GETFL) & ~(O_NONBLOCK)))
-        {
-            xfce_mailwatch_log_message(gmailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(gmailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       _("Unable to return socket to blocking mode.  Data may not be retreived correctly."));
-        }
-        
-        if(msg && msg == GMAIL_CMD_QUIT)
-            break;
-    }
-    
-    if(addresses)
-        freeaddrinfo(addresses);
-    
-    return (gmailbox->sockfd >= 0);
-}
-
-static gboolean
 gmail_check_atom_feed(XfceMailwatchGMailMailbox *gmailbox,
                       const gchar *username,
                       const gchar *password,
@@ -330,11 +196,7 @@
         return FALSE;
     }
     
-    gmailbox->security_info.using_tls = TRUE;
-    if(!xfce_mailwatch_net_negotiate_tls(gmailbox->sockfd,
-                                         &gmailbox->security_info, GMAIL_HOST,
-                                         &error))
-    {
+    if(!xfce_mailwatch_net_conn_make_secure(gmailbox->net_conn, &error)) {
         xfce_mailwatch_log_message(gmailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(gmailbox),
                                    XFCE_MAILWATCH_LOG_ERROR,
@@ -365,6 +227,9 @@
     }
     
     for(;;) {
+        if(!gmail_should_continue(gmailbox->net_conn, gmailbox))
+            break;
+
         bin = gmail_recv(gmailbox, buf, BUFSIZE);
         if(bin <= 0) {
             DBG("failed to recv response (%d)", bin);
@@ -451,11 +316,12 @@
         break;
     }
     
-    cleanup:
+cleanup:
     
-    shutdown(gmailbox->sockfd, SHUT_RDWR);
-    close(gmailbox->sockfd);
-    gmailbox->sockfd = -1;
+    if(gmailbox->net_conn) {
+        xfce_mailwatch_net_conn_destroy(gmailbox->net_conn);
+        gmailbox->net_conn = NULL;
+    }
     
     return ret;
 #undef BUFSIZE
@@ -488,8 +354,6 @@
     } else {
         DBG("failed to connect to gmail server");
     }
-    
-    xfce_mailwatch_net_tls_teardown(&gmailbox->security_info);
 #undef BUFSIZE
 }
 
@@ -497,48 +361,45 @@
 gmail_check_mail_th(gpointer data)
 {
     XfceMailwatchGMailMailbox *gmailbox = XFCE_MAILWATCH_GMAIL_MAILBOX(data);
-    gboolean running = FALSE;
-    GTimeVal start, now;
-    guint timeout = 0, delta = 0;
     
-    g_async_queue_ref(gmailbox->aqueue);
-    
-    g_get_current_time(&start);
-    
-    for(;;) {
-        gpointer msg = g_async_queue_try_pop(gmailbox->aqueue);
-        
-        if(msg) {
-            if(msg == GMAIL_CMD_START) {
-                g_get_current_time(&start);
-                running = TRUE;
-            } else if(msg == GMAIL_CMD_PAUSE)
-                running = FALSE;
-            else if(msg == GMAIL_CMD_TIMEOUT)
-                timeout = GPOINTER_TO_UINT(g_async_queue_pop(gmailbox->aqueue));
-            else if(msg == GMAIL_CMD_QUIT) {
-                g_async_queue_unref(gmailbox->aqueue);
-                g_thread_exit(NULL);
-            }
-        }
-        
-        g_get_current_time(&now);
-        
-        if(running && (msg == GMAIL_CMD_UPDATE
-                || now.tv_sec - start.tv_sec >= timeout - delta))
-        {
-            gmail_check_mail(gmailbox);
-            g_get_current_time(&start);
-            delta = (gint)start.tv_sec - now.tv_sec;
-        } else
-            g_usleep(250000);
+    while(!g_atomic_pointer_get(&gmailbox->th)
+          && g_atomic_int_get(&gmailbox->running))
+    {
+        g_thread_yield();
     }
+
+    if(!g_atomic_int_get(&gmailbox->running)) {
+        g_atomic_pointer_set(&gmailbox->th, NULL);
+        return NULL;
+    }
     
-    /* NOTREACHED */
-    g_async_queue_unref(gmailbox->aqueue);
+    gmail_check_mail(gmailbox);
+
+    g_atomic_pointer_set(&gmailbox->th, NULL);
     return NULL;
 }
 
+static gboolean
+gmail_check_mail_timeout(gpointer data)
+{
+    XfceMailwatchGMailMailbox *gmailbox = XFCE_MAILWATCH_GMAIL_MAILBOX(data);
+
+    GThread *th;
+
+    if(g_atomic_pointer_get(&gmailbox->th)) {
+        xfce_mailwatch_log_message(gmailbox->mailwatch,
+                                   XFCE_MAILWATCH_MAILBOX(gmailbox),
+                                   XFCE_MAILWATCH_LOG_WARNING,
+                                   _("Previous thread hasn't exited yet, not checking mail this time."));
+        return TRUE;
+    }
+
+    th = g_thread_create(gmail_check_mail_th, gmailbox, FALSE, NULL);
+    g_atomic_pointer_set(&gmailbox->th, th);
+
+    return TRUE;
+}
+
 static XfceMailwatchMailbox *
 gmail_mailbox_new(XfceMailwatch *mailwatch, XfceMailwatchMailboxType *type)
 {
@@ -547,14 +408,7 @@
     gmailbox->mailwatch = mailwatch;
     gmailbox->timeout = XFCE_MAILWATCH_DEFAULT_TIMEOUT;
     gmailbox->config_mx = g_mutex_new();
-    gmailbox->aqueue = g_async_queue_new();
     
-    g_async_queue_push(gmailbox->aqueue, GMAIL_CMD_TIMEOUT);
-    g_async_queue_push(gmailbox->aqueue,
-                       GUINT_TO_POINTER(XFCE_MAILWATCH_DEFAULT_TIMEOUT));
-    
-    gmailbox->th = g_thread_create(gmail_check_mail_th, gmailbox, TRUE, NULL);
-    
     return (XfceMailwatchMailbox *)gmailbox;
 }
 
@@ -562,15 +416,43 @@
 gmail_set_activated(XfceMailwatchMailbox *mailbox, gboolean activated)
 {
     XfceMailwatchGMailMailbox *gmailbox = XFCE_MAILWATCH_GMAIL_MAILBOX(mailbox);
-    g_async_queue_push(gmailbox->aqueue,
-                       activated ? GMAIL_CMD_START : GMAIL_CMD_PAUSE);
+
+    if(activated == g_atomic_int_get(&gmailbox->running))
+        return;
+
+    if(activated) {
+        g_atomic_int_set(&gmailbox->running, TRUE);
+        gmailbox->check_id = g_timeout_add(gmailbox->timeout * 1000,
+                                           gmail_check_mail_timeout,
+                                           gmailbox);
+    } else {
+        g_atomic_int_set(&gmailbox->running, FALSE);
+        g_source_remove(gmailbox->check_id);
+        gmailbox->check_id = 0;
+    }
 }
 
 static void
 gmail_force_update_cb(XfceMailwatchMailbox *mailbox)
 {
     XfceMailwatchGMailMailbox *gmailbox = XFCE_MAILWATCH_GMAIL_MAILBOX(mailbox);
-    g_async_queue_push(gmailbox->aqueue, GMAIL_CMD_UPDATE);
+
+    if(!g_atomic_pointer_get(&gmailbox->th)) {
+        gboolean restart = FALSE;
+
+        if(gmailbox->check_id) {
+            g_source_remove(gmailbox->check_id);
+            restart = TRUE;
+        }
+
+        gmail_check_mail_timeout(gmailbox);
+
+        if(restart) {
+            gmailbox->check_id = g_timeout_add(gmailbox->timeout * 1000,
+                                               gmail_check_mail_timeout,
+                                               gmailbox);
+        }
+    }
 }
 
 static gboolean
@@ -614,10 +496,20 @@
     XfceMailwatchGMailMailbox *gmailbox = XFCE_MAILWATCH_GMAIL_MAILBOX(user_data);
     gint value = gtk_spin_button_get_value_as_int(sb) * 60;
     
+    if(value == gmailbox->timeout)
+        return FALSE;
+
     gmailbox->timeout = value;
-    g_async_queue_push(gmailbox->aqueue, GMAIL_CMD_TIMEOUT);
-    g_async_queue_push(gmailbox->aqueue, GUINT_TO_POINTER(value));
-    
+
+    if(g_atomic_int_get(&gmailbox->running)) {
+        /* probably shouldn't do this so frequently */
+        if(gmailbox->check_id)
+            g_source_remove(gmailbox->check_id);
+        gmailbox->check_id = g_timeout_add(gmailbox->timeout * 1000,
+                                           gmail_check_mail_timeout,
+                                           gmailbox);
+    }
+
     return FALSE;
 }
 
@@ -715,12 +607,8 @@
             gmailbox->username = g_strdup(param->value);
         else if(!strcmp(param->key, "password"))
             gmailbox->password = g_strdup(param->value);
-        else if(!strcmp(param->key, "timeout")) {
+        else if(!strcmp(param->key, "timeout"))
             gmailbox->timeout = atoi(param->value);
-            g_async_queue_push(gmailbox->aqueue, GMAIL_CMD_TIMEOUT);
-            g_async_queue_push(gmailbox->aqueue,
-                               GUINT_TO_POINTER(gmailbox->timeout));
-        }
     }
     
     g_mutex_unlock(gmailbox->config_mx);
@@ -760,9 +648,14 @@
 {
     XfceMailwatchGMailMailbox *gmailbox = XFCE_MAILWATCH_GMAIL_MAILBOX(mailbox);
     
-    g_async_queue_push(gmailbox->aqueue, GMAIL_CMD_QUIT);
-    g_thread_join(gmailbox->th);
-    g_async_queue_unref(gmailbox->aqueue);
+    if(gmailbox->check_id) {
+        g_source_remove(gmailbox->check_id);
+        gmailbox->check_id = 0;
+    }
+
+    g_atomic_int_set(&gmailbox->running, FALSE);
+    while(g_atomic_pointer_get(&gmailbox->th))
+        g_thread_yield();
     
     g_mutex_free(gmailbox->config_mx);
     

Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c	2008-08-16 08:48:21 UTC (rev 5236)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c	2008-08-16 08:48:32 UTC (rev 5237)
@@ -46,10 +46,6 @@
 #include <netinet/in.h>
 #endif
 
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
 #ifdef HAVE_SYS_SELECT_H
 #include <sys/select.h>
 #endif
@@ -58,24 +54,13 @@
 #include <sys/wait.h>
 #endif
 
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#ifndef MSG_NOSIGNAL
-#define MSG_NOSIGNAL 0
-#endif
-
 #include <glib.h>
 #include <gtk/gtk.h>
 
 #include <libxfce4util/libxfce4util.h>
 #include <libxfcegui4/libxfcegui4.h>
 
+#include "mailwatch-net-conn.h"
 #include "mailwatch-utils.h"
 #include "mailwatch.h"
 
@@ -90,15 +75,10 @@
 #define IMAP_PORT_S              "143"
 #define IMAPS_PORT_S             "993"
 
-#define IMAP_CMD_START           GINT_TO_POINTER(1)
-#define IMAP_CMD_PAUSE           GINT_TO_POINTER(2)
-#define IMAP_CMD_TIMEOUT         GINT_TO_POINTER(3)
-#define IMAP_CMD_QUIT            GINT_TO_POINTER(4)
-#define IMAP_CMD_UPDATE          GINT_TO_POINTER(5)
-
 typedef struct
 {
     XfceMailwatchMailbox mailbox;
+    XfceMailwatch *mailwatch;
     
     GMutex *config_mx;
     
@@ -113,23 +93,18 @@
     gint nonstandard_port;
     XfceMailwatchAuthType auth_type;
     
-    GThread *th;
-    GAsyncQueue *aqueue;
-    
-    XfceMailwatch *mailwatch;
-    
-    /* state related to the current connection (if any) */
-    gint sockfd;
+    /* current connection stuff */
+    gint running;
+    gpointer th;  /* really a GThread *, but avoids casts later */
     guint imap_tag;
-    /* secure this, dude */
-    XfceMailwatchSecurityInfo security_info;
+    guint check_id;
     
     /* config dlg */
+    gint folder_tree_running;
+    gpointer folder_tree_th;  /* (GThread *) */
     GtkWidget *folder_tree_dialog;
     GtkTreeStore *ts;
     GtkCellRenderer *render;
-    GThread *folder_tree_th;
-    GAsyncQueue *folder_tree_aqueue;
     GtkWidget *refresh_btn;
     GNode *folder_tree;
 } XfceMailwatchIMAPMailbox;
@@ -150,16 +125,34 @@
     gboolean holds_messages;
 } IMAPFolderData;
 
+
+static gboolean
+imap_should_continue(XfceMailwatchNetConn *net_conn,
+                     gpointer user_data)
+{
+    XfceMailwatchIMAPMailbox *imailbox = user_data;
+    return (gboolean)g_atomic_int_get(&imailbox->running);
+}
+
+static gboolean
+imap_folder_tree_should_continue(XfceMailwatchNetConn *net_conn,
+                                 gpointer user_data)
+{
+    XfceMailwatchIMAPMailbox *imailbox = user_data;
+    return (gboolean)g_atomic_int_get(&imailbox->folder_tree_running);
+}
+
 static gssize
-imap_send(XfceMailwatchIMAPMailbox *imailbox, const gchar *buf)
+imap_send(XfceMailwatchIMAPMailbox *imailbox,
+          XfceMailwatchNetConn *net_conn,
+          const gchar *buf)
 {
     GError *error = NULL;
     gssize sent;
     
-    sent = xfce_mailwatch_net_send(imailbox->sockfd,
-                                   &imailbox->security_info,
-                                   buf,
-                                   &error);
+    sent = xfce_mailwatch_net_conn_send_data(net_conn,
+                                             (guchar *)buf, strlen(buf),
+                                             &error);
     if(sent < 0) {
         xfce_mailwatch_log_message(imailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(imailbox),
@@ -172,16 +165,16 @@
 }
 
 static gssize
-imap_recv(XfceMailwatchIMAPMailbox *imailbox, gchar *buf, gsize len)
+imap_recv(XfceMailwatchIMAPMailbox *imailbox,
+          XfceMailwatchNetConn *net_conn,
+          gchar *buf,
+          gsize len)
 {
     GError *error = NULL;
     gssize recvd;
     
-    recvd = xfce_mailwatch_net_recv(imailbox->sockfd,
-                                    &imailbox->security_info,
-                                    buf,
-                                    len,
-                                    &error);
+    recvd = xfce_mailwatch_net_conn_recv_line(net_conn,
+                                              buf, len, &error);
     
     if(recvd < 0) {
         xfce_mailwatch_log_message(imailbox->mailwatch,
@@ -194,42 +187,12 @@
     return recvd;
 }
 
-static void
-imap_do_logout(XfceMailwatchIMAPMailbox *imailbox)
-{
-    imap_send(imailbox, "ABCD LOGOUT\r\n");
-    
-    shutdown(imailbox->sockfd, SHUT_RDWR);
-    close(imailbox->sockfd);
-    imailbox->sockfd = -1;
-}
-
 static gboolean
-imap_get_addrinfo(XfceMailwatchIMAPMailbox *imailbox, const gchar *host,
-                  const gchar *service, struct addrinfo **addresses)
+imap_send_login_info(XfceMailwatchIMAPMailbox *imailbox,
+                     XfceMailwatchNetConn *net_conn,
+                     const gchar *username,
+                     const gchar *password)
 {
-    GError *error = NULL;
-        
-    TRACE("entering (%s, %s, %p)", host, service, addresses);
-    
-    g_return_val_if_fail(host && service && addresses, FALSE);
-    
-    if(!xfce_mailwatch_net_get_addrinfo(host, service, addresses, &error)) {
-        xfce_mailwatch_log_message(imailbox->mailwatch,
-                                   XFCE_MAILWATCH_MAILBOX(imailbox),
-                                   XFCE_MAILWATCH_LOG_ERROR,
-                                   error->message);
-        g_error_free(error);
-        return FALSE;
-    }
-    
-    return TRUE;
-}
-
-static gboolean
-imap_send_login_info(XfceMailwatchIMAPMailbox *imailbox, const gchar *username,
-        const gchar *password)
-{
 #define BUFSIZE 8191
     gint bin, bout;
     gchar buf[BUFSIZE+1];
@@ -238,11 +201,11 @@
     
     /* check capabilities */
     g_snprintf(buf, BUFSIZE, "%05d CAPABILITY\r\n", ++imailbox->imap_tag);
-    bout = imap_send(imailbox, buf);
+    bout = imap_send(imailbox, net_conn, buf);
     DBG("sent CAPABILITY (%d)", bout);
     if(bout != strlen(buf))
         goto cleanuperr;
-    bin = imap_recv(imailbox, buf, BUFSIZE);
+    bin = imap_recv(imailbox, net_conn, buf, BUFSIZE);
     DBG("response from CAPABILITY (%d): %s", bin, bin>0?buf:"(nada)");
     if(bin <= 0)
         goto cleanuperr;
@@ -258,11 +221,11 @@
         /* the server supports CRAM-MD5; prefer that over LOGIN */
         g_snprintf(buf, BUFSIZE, "%05d AUTHENTICATE CRAM-MD5\r\n",
                    ++imailbox->imap_tag);
-        bout = imap_send(imailbox, buf);
+        bout = imap_send(imailbox, net_conn, buf);
         if(bout != strlen(buf))
             goto cleanuperr;
         
-        bin = imap_recv(imailbox, buf, BUFSIZE);
+        bin = imap_recv(imailbox, net_conn, buf, BUFSIZE);
         DBG("response from AUTHENTICATE CRAM-MD5 (%d): %s\n", bin, bin>0?buf:"(nada)");
         if(bin <= 0)
             goto cleanuperr;
@@ -286,12 +249,12 @@
                 goto cleanuperr;
             g_snprintf(buf, BUFSIZE, "%s\r\n", response_base64);
             g_free(response_base64);
-            bout = imap_send(imailbox, buf);
+            bout = imap_send(imailbox, net_conn, buf);
             DBG("sent CRAM-MD5 response: %s\n", buf);
             if(bout != strlen(buf))
                 goto cleanuperr;
 
-            bin = imap_recv(imailbox, buf, BUFSIZE);
+            bin = imap_recv(imailbox, net_conn, buf, BUFSIZE);
             DBG("reponse from cram-md5 resp (%d): %s\n", bin, bin>0?buf:"(nada)");
             if(bin <= 0)
                 goto cleanuperr;
@@ -308,13 +271,13 @@
     /* send the creds */
     g_snprintf(buf, BUFSIZE, "%05d LOGIN \"%s\" \"%s\"\r\n",
                ++imailbox->imap_tag, username, password);
-    bout = imap_send(imailbox, buf);
+    bout = imap_send(imailbox, net_conn, buf);
     DBG("sent login (%d)", bout);
     if(bout != strlen(buf))
         goto cleanuperr;
     
     /* and see if we actually got auth-ed */
-    bin = imap_recv(imailbox, buf, BUFSIZE);
+    bin = imap_recv(imailbox, net_conn, buf, BUFSIZE);
     DBG("response from login (%d): %s", bin, bin>0?buf:"(nada)");
     if(bin <= 0)
         goto cleanuperr;
@@ -326,24 +289,21 @@
     
     return TRUE;
     
-    cleanuperr:
-    
-    shutdown(imailbox->sockfd, SHUT_RDWR);
-    close(imailbox->sockfd);
-    imailbox->sockfd = -1;
-    
+cleanuperr:
+
     return FALSE;
 #undef BUFSIZE
 }
 
 static gboolean
-imap_negotiate_ssl(XfceMailwatchIMAPMailbox *imailbox, const gchar *host)
+imap_negotiate_ssl(XfceMailwatchIMAPMailbox *imailbox,
+                   XfceMailwatchNetConn *net_conn,
+                   const gchar *host)
 {
     gboolean ret;
     GError *error = NULL;
     
-    ret = xfce_mailwatch_net_negotiate_tls(imailbox->sockfd,
-            &imailbox->security_info, host, &error);
+    ret = xfce_mailwatch_net_conn_make_secure(net_conn, &error);
     
     if(!ret) {
         xfce_mailwatch_log_message(imailbox->mailwatch,
@@ -352,17 +312,17 @@
                                    _("TLS handshake failed: %s"),
                                    error->message);
         g_error_free(error);
-        shutdown(imailbox->sockfd, SHUT_RDWR);
-        close(imailbox->sockfd);
-        imailbox->sockfd = -1;
     }
     
     return ret;
 }
 
 static gboolean
-imap_do_starttls(XfceMailwatchIMAPMailbox *imailbox, const gchar *host,
-        const gchar *username, const gchar *password)
+imap_do_starttls(XfceMailwatchIMAPMailbox *imailbox,
+                 XfceMailwatchNetConn *net_conn,
+                 const gchar *host,
+                 const gchar *username,
+                 const gchar *password)
 {
 #define BUFSIZE 8191
     gint bin;
@@ -371,236 +331,119 @@
     TRACE("entering");
     
     g_snprintf(buf, BUFSIZE, "%05d CAPABILITY\r\n", ++imailbox->imap_tag);
-    if(imap_send(imailbox, buf) != strlen(buf))
-        goto cleanuperr;
+    if(imap_send(imailbox, net_conn, buf) != strlen(buf))
+        return FALSE;
     
-    bin = imap_recv(imailbox, buf, BUFSIZE);
+    bin = imap_recv(imailbox, net_conn, buf, BUFSIZE);
     DBG("checking for STARTTLS caps (%d): %s", bin, bin>0?buf:"(nada)");
     if(bin <= 0)
-        goto cleanuperr;
+        return FALSE;
     if(!strstr(buf, " STARTTLS")) {
         xfce_mailwatch_log_message(imailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(imailbox),
                                    XFCE_MAILWATCH_LOG_WARNING,
                                    _("STARTTLS security was requested, but this server does not support it."));
-        goto cleanuperr;
+        return FALSE;
     }
     
     g_snprintf(buf, BUFSIZE, "%05d STARTTLS\r\n", ++imailbox->imap_tag);
-    if(imap_send(imailbox, buf) != strlen(buf))
-        goto cleanuperr;
+    if(imap_send(imailbox, net_conn, buf) != strlen(buf))
+        return FALSE;
     
-    if(imap_recv(imailbox, buf, BUFSIZE) < 0)
-        goto cleanuperr;
+    if(imap_recv(imailbox, net_conn, buf, BUFSIZE) < 0)
+        return FALSE;
     if(!strstr(buf, " OK"))
-        goto cleanuperr;
+        return FALSE;
     
-    /* now that we've negotiated SSL, reenable using_tls */
-    imailbox->security_info.using_tls = TRUE;
-    
     return TRUE;
-    
-    cleanuperr:
-    
-    shutdown(imailbox->sockfd, SHUT_RDWR);
-    close(imailbox->sockfd);
-    imailbox->sockfd = -1;
-    
-    return FALSE;
 #undef BUFSIZE
 }
 
 static gboolean
-imap_connect(XfceMailwatchIMAPMailbox *imailbox, const gchar *host,
-        const gchar *service, gint nonstandard_port)
+imap_connect(XfceMailwatchIMAPMailbox *imailbox,
+             XfceMailwatchNetConn *net_conn,
+             const gchar *host,
+             const gchar *service,
+             gint nonstandard_port)
 {
-    struct addrinfo *addresses = NULL, *ai;
-    gchar buf[16] = { 0, };
-    gpointer msg = NULL;
+    GError *error = NULL;
 
     TRACE("entering (%s)", service);
     
+    g_return_val_if_fail(net_conn, FALSE);
+    
+    xfce_mailwatch_net_conn_set_service(net_conn, service);
     if(nonstandard_port > 0)
-        g_snprintf(buf, sizeof(buf), "%d", nonstandard_port);
+        xfce_mailwatch_net_conn_set_port(net_conn, nonstandard_port);
     
-    if(!imap_get_addrinfo(imailbox, host, *buf ? buf : service, &addresses)) {
-        DBG("failed to get sockaddr");
+    if(xfce_mailwatch_net_conn_connect(net_conn, &error))
+        return TRUE;
+    else {
+        xfce_mailwatch_log_message(imailbox->mailwatch,
+                                   XFCE_MAILWATCH_MAILBOX(imailbox),
+                                   XFCE_MAILWATCH_LOG_ERROR,
+                                   "%s", error->message);
+        g_error_free(error);
         return FALSE;
     }
-    
-    for(ai = addresses; ai; ai = ai->ai_next) {
-        imailbox->sockfd = socket(ai->ai_family, ai->ai_socktype,
-                                  ai->ai_protocol);
-        if(imailbox->sockfd < 0)
-            continue;
-#if 0
-        if(imailbox->sockfd < 0) {
-            xfce_mailwatch_log_message(imailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(imailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       "socket(): %s",
-                                       strerror(errno));
-            DBG("failed to open socket");
-            return FALSE;
-        }
-#endif 
-        /* this next batch of crap is necessary because it seems like a failed
-         * connection (that is, one that isn't ECONNREFUSED) takes over 3 minutes
-         * to fail!  if the panel is trying to quit, that's just unacceptable.
-         */
-        
-        if(fcntl(imailbox->sockfd, F_SETFL,
-                 fcntl(imailbox->sockfd, F_GETFL) | O_NONBLOCK))
-        {
-            xfce_mailwatch_log_message(imailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(imailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       _("Unable to set socket to non-blocking mode.  If the connect attempt hangs, the panel may hang on close."));
-        }
-        
-        if(connect(imailbox->sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
-            gboolean failed = TRUE;
-            
-            if(errno == EINPROGRESS) {
-                gint iters_left;
-                for(iters_left = 25; iters_left >= 0; iters_left--) {
-                    fd_set wfd;
-                    struct timeval tv = { 2, 0 };
-                    int sock_err = 0;
-                    socklen_t sock_err_len = sizeof(int);
-                    
-                    FD_ZERO(&wfd);
-                    FD_SET(imailbox->sockfd, &wfd);
-                    
-                    DBG("checking for a connection...");
-                    
-                    /* wait until the connect attempt finishes */
-                    if(select(FD_SETSIZE, NULL, &wfd, NULL, &tv) < 0)
-                        break;
-                    
-                    /* check to see if it finished, and, if so, if there was an
-                     * error, or if it completed successfully */
-                    if(FD_ISSET(imailbox->sockfd, &wfd)) {
-                        if(!getsockopt(imailbox->sockfd, SOL_SOCKET, SO_ERROR,
-                                       &sock_err, &sock_err_len)
-                           && !sock_err)
-                        {
-                            DBG("    connection succeeded");
-                            failed = FALSE;
-                        } else {
-#if 0
-                            xfce_mailwatch_log_message(imailbox->mailwatch,
-                                                       XFCE_MAILWATCH_MAILBOX(imailbox),
-                                                       XFCE_MAILWATCH_LOG_ERROR,
-                                                       _("Failed to connect to server: %s"),
-                                                       strerror(sock_err));
-#endif
-                            DBG("    connection failed: sock_err is (%d) %s",
-                                sock_err, strerror(sock_err));
-                        }
-                        break;
-                    }
-                    
-                    /* check the main thread to see if we're supposed to quit */
-                    msg = g_async_queue_try_pop(imailbox->aqueue);
-                    if(msg) {
-                        /* put it back so imap_check_mail_th() can read it */
-                        g_async_queue_push(imailbox->aqueue, msg);
-                        if(msg == IMAP_CMD_QUIT) {
-                            failed = TRUE;
-                            break;
-                        }
-                        msg = NULL;
-                    }
-                }
-            }
-            
-            if(failed) {
-                DBG("failed to connect");
-                close(imailbox->sockfd);
-                imailbox->sockfd = -1;
-                continue;
-            } else
-                break;
-        }
-        
-        if(fcntl(imailbox->sockfd, F_SETFL,
-                 fcntl(imailbox->sockfd, F_GETFL) & ~(O_NONBLOCK)))
-        {
-            xfce_mailwatch_log_message(imailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(imailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       _("Unable to return socket to blocking mode.  Data may not be retreived correctly."));
-        }
-        
-        if(msg && msg == IMAP_CMD_QUIT)
-            break;
-    }
-    
-    if(addresses)
-        freeaddrinfo(addresses);
-    
-    return (imailbox->sockfd >= 0);
 }
 
 static inline gboolean
-imap_slurp_banner(XfceMailwatchIMAPMailbox *imailbox)
+imap_slurp_banner(XfceMailwatchIMAPMailbox *imailbox,
+                  XfceMailwatchNetConn *net_conn)
 {
     gchar buf[2048];
     gint bin;
     
-    do {
-        bin = imap_recv(imailbox, buf, sizeof(buf)-1);
-        if(bin < 0) {
-            DBG("failed to get banner");
-            shutdown(imailbox->sockfd, SHUT_RDWR);
-            close(imailbox->sockfd);
-            imailbox->sockfd = -1;
-        } else {
-            buf[bin] = 0;
-            DBG("got banner, discarding: %s\n", buf);
-        }
-    } while(bin != -1 && !strchr(buf, '\n'));
+    bin = imap_recv(imailbox, net_conn, buf, sizeof(buf)-1);
+    if(bin < 0) {
+        DBG("failed to get banner");
+    } else {
+        buf[bin] = 0;
+        DBG("got banner, discarding: %s\n", buf);
+    }
     
     return (bin != -1);
 }
 
 static gboolean
-imap_authenticate(XfceMailwatchIMAPMailbox *imailbox, const gchar *host,
-        const gchar *username, const gchar *password,
-        XfceMailwatchAuthType auth_type, gint nonstandard_port)
+imap_authenticate(XfceMailwatchIMAPMailbox *imailbox,
+                  XfceMailwatchNetConn *net_conn,
+                  const gchar *host,
+                  const gchar *username,
+                  const gchar *password,
+                  XfceMailwatchAuthType auth_type,
+                  gint nonstandard_port)
 {
     gboolean ret = FALSE;
+
+    g_return_val_if_fail(net_conn && host && username && password, FALSE);
     
     TRACE("entering, auth_type is %d", auth_type);
     
     switch(auth_type) {
         case AUTH_NONE:
-            imailbox->security_info.using_tls = FALSE;
-            ret = imap_connect(imailbox, host, "imap", nonstandard_port);
+            ret = imap_connect(imailbox, net_conn, host, "imap", nonstandard_port);
             if(ret)
-                ret = imap_slurp_banner(imailbox);
+                ret = imap_slurp_banner(imailbox, net_conn);
             break;
         
         case AUTH_STARTTLS:
-            imailbox->security_info.using_tls = FALSE;
-            ret = imap_connect(imailbox, host, "imap", nonstandard_port);
+            ret = imap_connect(imailbox, net_conn, host, "imap", nonstandard_port);
             if(ret)
-                ret = imap_slurp_banner(imailbox);
+                ret = imap_slurp_banner(imailbox, net_conn);
             if(ret)
-                ret = imap_do_starttls(imailbox, host, username, password);
+                ret = imap_do_starttls(imailbox, net_conn, host, username, password);
             if(ret)
-                ret = imap_negotiate_ssl(imailbox, host);
-            imailbox->security_info.using_tls = TRUE;
+                ret = imap_negotiate_ssl(imailbox, net_conn, host);
             break;
         
         case AUTH_SSL_PORT:
-            imailbox->security_info.using_tls = TRUE;
-            ret = imap_connect(imailbox, host, "imaps", nonstandard_port);
+            ret = imap_connect(imailbox, net_conn, host, "imaps", nonstandard_port);
             if(ret)
-                ret = imap_negotiate_ssl(imailbox, host);
+                ret = imap_negotiate_ssl(imailbox, net_conn, host);
             if(ret)
-                ret = imap_slurp_banner(imailbox);
+                ret = imap_slurp_banner(imailbox, net_conn);
             break;
         
         default:
@@ -608,21 +451,19 @@
             return FALSE;
     }
     
-    DBG("using_tls is %s", imailbox->security_info.using_tls?"TRUE":"FALSE");
-        
     if(ret)
-       ret = imap_send_login_info(imailbox, username, password);
-    
+       ret = imap_send_login_info(imailbox, net_conn, username, password);
+
     return ret;
 }
 
 static guint
 imap_check_mailbox(XfceMailwatchIMAPMailbox *imailbox,
-        const gchar *mailbox_name)
+                   XfceMailwatchNetConn *net_conn,
+                   const gchar *mailbox_name)
 {
-    gint new_messages = 0;
+    gint new_messages = 0, bin;
     gchar buf[4096], *p, *q, tmp[64];
-    gboolean got_OK = FALSE, got_LF = FALSE;
     
     TRACE("entering, folder %s", mailbox_name);
     
@@ -631,26 +472,26 @@
     /* ask the server to look at the mailbox */
     g_snprintf(buf, sizeof(buf), "%05d STATUS %s (UNSEEN)\r\n",
                ++imailbox->imap_tag, mailbox_name);
-    if(imap_send(imailbox, buf) != strlen(buf))
+    if(imap_send(imailbox, net_conn, buf) != strlen(buf))
         return 0;
     DBG("  successfully sent cmd '%s'", buf);
     
     /* grab the response */
     g_snprintf(tmp, sizeof(tmp), "%05d NO", imailbox->imap_tag);
-    do {
-        if(imap_recv(imailbox, buf, sizeof(buf)-1) <= 0) {
-            xfce_mailwatch_log_message(imailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(imailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       _("The IMAP server returned a response we weren't quite expecting.  This might be OK, or this plugin might need to be modified to support your mail server if the new message counts are incorrect."));
-            g_warning("Mailwatch: Odd response to SEARCH UNSEEN");
-            return 0;
-        }
-        
-        if(strstr(buf, tmp))
-            return 0;
-    } while(!(p = strstr(buf, "(UNSEEN ")));
+    if(imap_recv(imailbox, net_conn, buf, sizeof(buf)-1) <= 0) {
+        xfce_mailwatch_log_message(imailbox->mailwatch,
+                                   XFCE_MAILWATCH_MAILBOX(imailbox),
+                                   XFCE_MAILWATCH_LOG_WARNING,
+                                   _("The IMAP server returned a response we weren't quite expecting.  This might be OK, or this plugin might need to be modified to support your mail server if the new message counts are incorrect."));
+        g_warning("Mailwatch: Odd response to SEARCH UNSEEN");
+        return 0;
+    }
     
+    if(strstr(buf, tmp))
+        return 0;
+    p = strstr(buf, "(UNSEEN ");
+    if(!p)
+        return 0;
     q = strchr(p, ')');
     if(!q)
         return 0;
@@ -660,26 +501,11 @@
     
     /* make sure we got the entire command; it should end with "##### OK" in it */
     g_snprintf(tmp, sizeof(tmp), "%05d OK", imailbox->imap_tag);
-    while(!got_OK && !got_LF) {
-        DBG("looking for end, got: %s", buf);
-        
-        if(!got_OK) {
-            gchar *p = strstr(buf, tmp);
-            if(p) {
-                DBG("got OK");
-                got_OK = TRUE;
-                got_LF = !!strchr(p, '\n');
-                DBG("%s LF after getting OK", got_LF?"got":"didn't get");
-            } else
-                DBG("didn't get OK");
-        } else {
-            got_LF = !!strchr(buf, '\n');
-            DBG("%s LF", got_LF?"got":"didn't get");
-        }
-        
-        if(!got_OK && !got_LF && imap_recv(imailbox, buf, sizeof(buf)-1) <= 0)
-            break;
-    }
+    do {
+        bin = imap_recv(imailbox, net_conn, buf, sizeof(buf)-1);
+        if(bin < 0)
+            return (guint)new_messages;
+    } while(!strstr(buf, tmp));
     
     DBG("new message count in mailbox '%s' is %d", mailbox_name, new_messages);
     
@@ -724,21 +550,37 @@
     }
 }
 
-static void
-imap_check_mail(XfceMailwatchIMAPMailbox *imailbox)
+static gpointer
+imap_check_mail_th(gpointer user_data)
 {
 #define BUFSIZE 1024
+    XfceMailwatchIMAPMailbox *imailbox = user_data;
     gchar host[BUFSIZE], username[BUFSIZE], password[BUFSIZE];
     guint new_messages = 0;
     GList *mailboxes_to_check = NULL, *l;
     XfceMailwatchAuthType auth_type;
     gint nonstandard_port = -1;
-    
+    XfceMailwatchNetConn *net_conn;
+
+    /* wait for the main thread to set the thread pointer.  this is
+     * not the most elegant way to do this, but it works. */
+    while(!g_atomic_pointer_get(&imailbox->th)
+          && g_atomic_int_get(&imailbox->running))
+    {
+        g_thread_yield();
+    }
+
+    if(!g_atomic_int_get(&imailbox->running)) {
+        g_atomic_pointer_set(&imailbox->th, NULL);
+        return NULL;
+    }
+
     g_mutex_lock(imailbox->config_mx);
     
     if(!imailbox->host || !imailbox->username || !imailbox->password) {
         g_mutex_unlock(imailbox->config_mx);
-        return;
+        g_atomic_pointer_set(&imailbox->th, NULL);
+        return NULL;
     }
     
     g_strlcpy(host, imailbox->host, BUFSIZE);
@@ -758,81 +600,36 @@
     imap_escape_string(username, BUFSIZE);
     imap_escape_string(password, BUFSIZE);
     
-    if(!imap_authenticate(imailbox, host, username, password, auth_type,
-            nonstandard_port))
+    net_conn = xfce_mailwatch_net_conn_new(host, NULL);
+    xfce_mailwatch_net_conn_set_should_continue_func(net_conn,
+                                                     imap_should_continue,
+                                                     imailbox);
+    if(imap_authenticate(imailbox, net_conn, host, username, password,
+                          auth_type, nonstandard_port))
     {
-        DBG("failed to connect to imap server");
-        goto cleanup;
+        new_messages = imap_check_mailbox(imailbox, net_conn, "INBOX");
+        DBG("checked inbox, %d new messages", new_messages);
+        for(l = mailboxes_to_check; l; l = l->next) {
+            new_messages += imap_check_mailbox(imailbox, net_conn, l->data);
+            DBG("checked mail folder %s, total is now %d new messages", (gchar *)l->data, new_messages);
+        }
+        
+        xfce_mailwatch_signal_new_messages(imailbox->mailwatch,
+                XFCE_MAILWATCH_MAILBOX(imailbox), new_messages);
     }
+
+    imap_send(imailbox, net_conn, "ABCD LOGOUT\r\n");
     
-    new_messages = imap_check_mailbox(imailbox, "INBOX");
-    DBG("checked inbox, %d new messages", new_messages);
-    for(l = mailboxes_to_check; l; l = l->next) {
-        new_messages += imap_check_mailbox(imailbox, l->data);
-        DBG("checked mail folder %s, total is now %d new messages", (gchar *)l->data, new_messages);
-    }
-    
-    xfce_mailwatch_signal_new_messages(imailbox->mailwatch,
-            XFCE_MAILWATCH_MAILBOX(imailbox), new_messages);
-    
-    cleanup:
-    
-    imap_do_logout(imailbox);
-    
     if(mailboxes_to_check) {
         g_list_foreach(mailboxes_to_check, (GFunc)g_free, NULL);
         g_list_free(mailboxes_to_check);
     }
     
-    xfce_mailwatch_net_tls_teardown(&imailbox->security_info);
-    
-#undef BUFSIZE
-}
+    xfce_mailwatch_net_conn_destroy(net_conn);
+    g_atomic_pointer_set(&imailbox->th, NULL);
 
-static gpointer
-imap_check_mail_th(gpointer user_data)
-{
-    XfceMailwatchIMAPMailbox *imailbox = user_data;
-    gboolean running = FALSE;
-    GTimeVal start, now;
-    guint timeout = 0, delta = 0;
-    
-    g_async_queue_ref(imailbox->aqueue);
-    
-    g_get_current_time(&start);
-    
-    for(;;) {
-        gpointer msg = g_async_queue_try_pop(imailbox->aqueue);
-        
-        if(msg) {
-            if(msg == IMAP_CMD_START) {
-                g_get_current_time(&start);;
-                running = TRUE;
-            } else if(msg == IMAP_CMD_PAUSE)
-                running = FALSE;
-            else if(msg == IMAP_CMD_TIMEOUT)
-                timeout = GPOINTER_TO_UINT(g_async_queue_pop(imailbox->aqueue));
-            else if(msg == IMAP_CMD_QUIT) {
-                g_async_queue_unref(imailbox->aqueue);
-                g_thread_exit(NULL);
-            }
-        }
-        
-        g_get_current_time(&now);
-        
-        if(running && (msg == IMAP_CMD_UPDATE
-                || now.tv_sec - start.tv_sec >= timeout - delta))
-        {
-            imap_check_mail(imailbox);
-            g_get_current_time(&start);
-            delta = (gint)start.tv_sec - now.tv_sec;
-        } else
-            g_usleep(250000);
-    }
-    
-    /* NOTREACHED */
-    g_async_queue_unref(imailbox->aqueue);
     return NULL;
+#undef BUFSIZE
 }
 
 static XfceMailwatchMailbox *
@@ -844,24 +641,48 @@
     imailbox->timeout = XFCE_MAILWATCH_DEFAULT_TIMEOUT;
     imailbox->use_standard_port = TRUE;
     imailbox->config_mx = g_mutex_new();
-    /* init the queue */
-    imailbox->aqueue = g_async_queue_new();
-    /* and init the timeout */
-    g_async_queue_push(imailbox->aqueue, IMAP_CMD_TIMEOUT);
-    g_async_queue_push(imailbox->aqueue, 
-                       GUINT_TO_POINTER(XFCE_MAILWATCH_DEFAULT_TIMEOUT));
-    /* create checker thread */
-    imailbox->th = g_thread_create(imap_check_mail_th, imailbox, TRUE, NULL);
     
-    return (XfceMailwatchMailbox *)imailbox;
+    return XFCE_MAILWATCH_MAILBOX(imailbox);
 }
 
+static gboolean
+imap_check_mail_timeout(gpointer data)
+{
+    XfceMailwatchIMAPMailbox *imailbox = data;
+    GThread *th;
+
+    if(g_atomic_pointer_get(&imailbox->th)) {
+        xfce_mailwatch_log_message(imailbox->mailwatch,
+                                   XFCE_MAILWATCH_MAILBOX(imailbox),
+                                   XFCE_MAILWATCH_LOG_WARNING,
+                                   _("Previous thread hasn't exited yet, not checking mail this time."));
+        return TRUE;
+    }
+
+    th = g_thread_create(imap_check_mail_th, imailbox, FALSE, NULL);
+    g_atomic_pointer_set(&imailbox->th, th);
+
+    return TRUE;
+}
+
 static void
 imap_set_activated(XfceMailwatchMailbox *mailbox, gboolean activated)
 {
     XfceMailwatchIMAPMailbox *imailbox = XFCE_MAILWATCH_IMAP_MAILBOX(mailbox);
-    
-    g_async_queue_push(imailbox->aqueue, activated ? IMAP_CMD_START : IMAP_CMD_PAUSE);
+
+    if(activated == g_atomic_int_get(&imailbox->running))
+        return;
+
+    if(activated) {
+        g_atomic_int_set(&imailbox->running, TRUE);
+        imailbox->check_id = g_timeout_add(imailbox->timeout * 1000,
+                                           imap_check_mail_timeout,
+                                           imailbox);
+    } else {
+        g_atomic_int_set(&imailbox->running, FALSE);
+        g_source_remove(imailbox->check_id);
+        imailbox->check_id = 0;
+    }
 }
 
 static void
@@ -869,7 +690,22 @@
 {
     XfceMailwatchIMAPMailbox *imailbox = XFCE_MAILWATCH_IMAP_MAILBOX(mailbox);
     
-    g_async_queue_push(imailbox->aqueue, IMAP_CMD_UPDATE);
+    if(!g_atomic_pointer_get(&imailbox->th)) {
+        gboolean restart = FALSE;
+
+        if(imailbox->check_id) {
+            g_source_remove(imailbox->check_id);
+            restart = TRUE;
+        }
+
+        imap_check_mail_timeout(imailbox);
+
+        if(restart) {
+            imailbox->check_id = g_timeout_add(imailbox->timeout * 1000,
+                                               imap_check_mail_timeout,
+                                               imailbox);
+        }
+    }
 }
 
 static gboolean
@@ -941,7 +777,7 @@
     return FALSE;
 }
 
-static gboolean
+static void
 imap_config_timeout_spinbutton_changed_cb(GtkSpinButton *sb,
                                           gpointer user_data)
 {
@@ -949,10 +785,15 @@
     gint value = gtk_spin_button_get_value_as_int(sb) * 60;
     
     imailbox->timeout = value;
-    g_async_queue_push(imailbox->aqueue, IMAP_CMD_TIMEOUT);
-    g_async_queue_push(imailbox->aqueue, GUINT_TO_POINTER(value));
-    
-    return FALSE;
+
+    if(g_atomic_int_get(&imailbox->running)) {
+        /* probably shouldn't do this so frequently */
+        if(imailbox->check_id)
+            g_source_remove(imailbox->check_id);
+        imailbox->check_id = g_timeout_add(imailbox->timeout * 1000,
+                                           imap_check_mail_timeout,
+                                           imailbox);
+    }
 }
 
 static GNode *
@@ -979,7 +820,9 @@
 
 static gboolean
 imap_populate_folder_tree(XfceMailwatchIMAPMailbox *imailbox,
-        const gchar *cur_folder, GNode *parent)
+                          XfceMailwatchNetConn *net_conn,
+                          const gchar *cur_folder,
+                          GNode *parent)
 {
 #define BUFSIZE 16383
     gboolean ret = TRUE;
@@ -996,7 +839,7 @@
     
     g_snprintf(buf, BUFSIZE, "%05d LIST \"%s\" \"%%\"\r\n",
             ++imailbox->imap_tag, cur_folder);
-    if(imap_send(imailbox, buf) != strlen(buf))
+    if(imap_send(imailbox, net_conn, buf) != strlen(buf))
         return FALSE;
     DBG("sent LIST: '%s'", buf);
     
@@ -1004,7 +847,7 @@
     while(!strstr(buf, " OK") && bin_tot < BUFSIZE) {
         /* this is probably a bad idea... */
     
-        bin = imap_recv(imailbox, buf+bin_tot, BUFSIZE);
+        bin = imap_recv(imailbox, net_conn, buf+bin_tot, BUFSIZE);
         if(bin < 0) {
             DBG("imap_recv() failed");
             return FALSE;
@@ -1017,9 +860,6 @@
             return FALSE;
     }
     
-    if(g_async_queue_try_pop(imailbox->folder_tree_aqueue) == IMAP_CMD_QUIT)
-        return FALSE;
-    
     if(!strstr(buf, " OK"))
         return FALSE;
     
@@ -1029,6 +869,9 @@
         resp_lines = g_strsplit(buf, "\n", -1);
     
     for(i = 0; resp_lines[i]; i++) {
+        if(!imap_folder_tree_should_continue(net_conn, imailbox))
+            return FALSE;
+
         if(*resp_lines[i] != '*')
             continue;
         
@@ -1057,7 +900,6 @@
             
             continue;
         }
-            
         
         /* first quote before separator */
         p = strstr(resp_lines[i], "\"");
@@ -1131,12 +973,9 @@
         
         if(has_children) {
             g_strlcat(fullpath, separator, (BUFSIZE+1)/8);
-            if(!imap_populate_folder_tree(imailbox, fullpath, node))
+            if(!imap_populate_folder_tree(imailbox, net_conn, fullpath, node))
                 return FALSE;
         }
-        
-        if(g_async_queue_try_pop(imailbox->folder_tree_aqueue) == IMAP_CMD_QUIT)
-            return FALSE;
     }
     
     g_strfreev(resp_lines);
@@ -1186,12 +1025,9 @@
     GList *l;
     GNode *n;
     
-    if(imailbox->folder_tree_th) {
-        g_thread_join(imailbox->folder_tree_th);
-        imailbox->folder_tree_th = NULL;
-        g_async_queue_unref(imailbox->folder_tree_aqueue);
-        imailbox->folder_tree_aqueue = NULL;
-    }
+    g_atomic_int_set(&imailbox->folder_tree_running, FALSE);
+    while(g_atomic_pointer_get(&imailbox->folder_tree_th))
+        g_thread_yield();
     
     if(!imailbox->folder_tree_dialog)
         return FALSE;
@@ -1229,13 +1065,10 @@
     XfceMailwatchIMAPMailbox *imailbox = user_data;
     GtkTreeIter itr;
     
-    if(imailbox->folder_tree_th) {
-        g_thread_join(imailbox->folder_tree_th);
-        imailbox->folder_tree_th = NULL;
-        g_async_queue_unref(imailbox->folder_tree_aqueue);
-        imailbox->folder_tree_aqueue = NULL;
-    }
-    
+    g_atomic_int_set(&imailbox->folder_tree_running, FALSE);
+    while(g_atomic_pointer_get(&imailbox->folder_tree_th))
+        g_thread_yield();
+
     if(!imailbox->folder_tree_dialog)
         return FALSE;
     
@@ -1256,13 +1089,11 @@
 {
     XfceMailwatchIMAPMailbox *imailbox = user_data;
     
-    if(imailbox->folder_tree_th) {
-        g_thread_join(imailbox->folder_tree_th);
-        imailbox->folder_tree_th = NULL;
-        g_async_queue_unref(imailbox->folder_tree_aqueue);
-        imailbox->folder_tree_aqueue = NULL;
-    }
-    
+    /* this should never really end up spinning even once */
+    g_atomic_int_set(&imailbox->folder_tree_running, FALSE);
+    while(g_atomic_pointer_get(&imailbox->folder_tree_th))
+        g_thread_yield();
+
     if(imailbox->folder_tree_dialog)
         gtk_widget_set_sensitive(imailbox->refresh_btn, TRUE);
     
@@ -1292,16 +1123,28 @@
     gchar host[BUFSIZE], username[BUFSIZE], password[BUFSIZE];
     XfceMailwatchAuthType auth_type;
     gint nonstandard_port = -1;
+    XfceMailwatchNetConn *net_conn;
     
     TRACE("entering");
+
+    /* wait for caller to set thread pointer */
+    while(!g_atomic_pointer_get(&imailbox->folder_tree_th)
+          && g_atomic_int_get(&imailbox->folder_tree_running))
+    {
+        g_thread_yield();
+    }
+
+    if(!g_atomic_int_get(&imailbox->folder_tree_running)) {
+        g_atomic_pointer_set(&imailbox->folder_tree_th, NULL);
+        return NULL;
+    }
     
-    g_async_queue_ref(imailbox->folder_tree_aqueue);
-    
     g_mutex_lock(imailbox->config_mx);
     
     if(!imailbox->host || !imailbox->username || !imailbox->password) {
         g_mutex_unlock(imailbox->config_mx);
         g_idle_add(imap_folder_tree_th_join, imailbox);
+        g_atomic_pointer_set(&imailbox->folder_tree_th, NULL);
         return NULL;
     }
     
@@ -1317,12 +1160,16 @@
     imap_escape_string(username, BUFSIZE);
     imap_escape_string(password, BUFSIZE);
     
-    if(imap_authenticate(imailbox, host, username, password, auth_type,
-            nonstandard_port))
+    net_conn = xfce_mailwatch_net_conn_new(host, NULL);
+    xfce_mailwatch_net_conn_set_should_continue_func(net_conn,
+                                                     imap_folder_tree_should_continue,
+                                                     imailbox);
+    if(imap_authenticate(imailbox, net_conn, host, username,
+                         password, auth_type, nonstandard_port))
     {
-       if(g_async_queue_try_pop(imailbox->folder_tree_aqueue) != IMAP_CMD_QUIT) {
+       if(g_atomic_int_get(&imailbox->folder_tree_running)) {
            imailbox->folder_tree = g_node_new((gpointer)0xdeadbeef);
-           if(imap_populate_folder_tree(imailbox, "", imailbox->folder_tree))
+           if(imap_populate_folder_tree(imailbox, net_conn, "", imailbox->folder_tree))
                g_idle_add(imap_populate_folder_tree_nodes, imailbox);
            else {
                g_node_traverse(imailbox->folder_tree, G_IN_ORDER,
@@ -1336,9 +1183,10 @@
         DBG("failed to connect to imap server to probe folders");
         g_idle_add(imap_populate_folder_tree_failed, imailbox);
     }
+
+    xfce_mailwatch_net_conn_destroy(net_conn);
+    g_atomic_pointer_set(&imailbox->folder_tree_th, NULL);
     
-    g_async_queue_unref(imailbox->folder_tree_aqueue);
-    
     return NULL;
 #undef BUFSIZE
 }
@@ -1350,8 +1198,7 @@
     
     imailbox->folder_tree_dialog = NULL;
     
-    if(imailbox->folder_tree_aqueue)
-        g_async_queue_push(imailbox->folder_tree_aqueue, IMAP_CMD_QUIT);
+    g_atomic_pointer_set(&imailbox->folder_tree_th, NULL);
 }
 
 static void
@@ -1359,9 +1206,15 @@
 {
     XfceMailwatchIMAPMailbox *imailbox = user_data;
     GtkTreeIter itr;
+    GThread *th;
     
     if(!imailbox->host || !imailbox->username)
         return;
+
+    if(g_atomic_int_get(&imailbox->folder_tree_running)) {
+        g_critical("Attempt to refresh folder tree while tree fetch is in process");
+        return;
+    }
     
     gtk_widget_set_sensitive(imailbox->refresh_btn, FALSE);
     
@@ -1372,10 +1225,11 @@
     g_object_set(G_OBJECT(imailbox->render),
                 "foreground-set", TRUE,
                 "style-set", TRUE, NULL);
-    
-    imailbox->folder_tree_aqueue = g_async_queue_new();
-    imailbox->folder_tree_th = g_thread_create(imap_populate_folder_tree_th,
-                                               imailbox, TRUE, NULL);
+
+    g_atomic_int_set(&imailbox->folder_tree_running, TRUE);
+    th = g_thread_create(imap_populate_folder_tree_th,
+                         imailbox, FALSE, NULL);
+    g_atomic_pointer_set(&imailbox->folder_tree_th, th);
 }
 
 static gboolean
@@ -1458,27 +1312,36 @@
     GtkCellRenderer *render;
     GtkTreeViewColumn *col;
     GtkTreeSelection *sel;
+    GThread *th;
+
+    if(imailbox->folder_tree_dialog) {
+        gtk_window_present(GTK_WINDOW(imailbox->folder_tree_dialog));
+        return;
+    }
     
     xfce_textdomain(GETTEXT_PACKAGE, LOCALEDIR, "UTF-8");
     
     if(!imailbox->host || !imailbox->username) {
         xfce_message_dialog(toplevel, _("Error"), GTK_STOCK_DIALOG_WARNING,
-                _("No server or username is set."),
-                _("The folder list cannot be retrieved until a server, username, and probably password are set.  Also be sure to check any security settings in the Advanced dialog."),
-                GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
+                            _("No server or username is set."),
+                            _("The folder list cannot be retrieved until a server, username, and probably password are set.  Also be sure to check any security settings in the Advanced dialog."),
+                            GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
         return;
     }
     
     dlg = gtk_dialog_new_with_buttons(_("Set New Mail Folders"), toplevel,
-            GTK_DIALOG_DESTROY_WITH_PARENT|GTK_DIALOG_NO_SEPARATOR,
-            GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT, NULL);
+                                      GTK_DIALOG_DESTROY_WITH_PARENT
+                                      | GTK_DIALOG_NO_SEPARATOR,
+                                      GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
+                                      NULL);
     imailbox->folder_tree_dialog = dlg;
     topvbox = gtk_vbox_new(FALSE, BORDER/2);
     gtk_container_set_border_width(GTK_CONTAINER(topvbox), BORDER/2);
     gtk_widget_show(topvbox);
     gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dlg)->vbox), topvbox, TRUE, TRUE, 0);
     g_signal_connect(G_OBJECT(dlg), "destroy",
-            G_CALLBACK(imap_config_newmailfolders_destroy_cb), imailbox);
+                     G_CALLBACK(imap_config_newmailfolders_destroy_cb),
+                     imailbox);
     
     frame = xfce_mailwatch_create_framebox(_("New Mail Folders"), &frame_bin);
     gtk_widget_show(frame);
@@ -1490,14 +1353,15 @@
     
     sw = gtk_scrolled_window_new(NULL, NULL);
     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_NEVER,
-            GTK_POLICY_AUTOMATIC);
+                                   GTK_POLICY_AUTOMATIC);
     gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
-            GTK_SHADOW_ETCHED_IN);
+                                        GTK_SHADOW_ETCHED_IN);
     gtk_widget_show(sw);
     gtk_box_pack_start(GTK_BOX(hbox), sw, TRUE, TRUE, 0);
     
     imailbox->ts = ts = gtk_tree_store_new(IMAP_FOLDERS_N_COLUMNS,
-            G_TYPE_STRING, G_TYPE_BOOLEAN, G_TYPE_BOOLEAN, G_TYPE_STRING);
+                                           G_TYPE_STRING, G_TYPE_BOOLEAN,
+                                           G_TYPE_BOOLEAN, G_TYPE_STRING);
     
     treeview = gtk_tree_view_new_with_model(GTK_TREE_MODEL(ts));
     gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(treeview), FALSE);
@@ -1510,8 +1374,10 @@
     render = gtk_cell_renderer_pixbuf_new();
     gtk_tree_view_column_pack_start(col, render, FALSE);
 #if GTK_CHECK_VERSION(2, 6, 0)
-    g_object_set(G_OBJECT(render), "stock-id", GTK_STOCK_DIRECTORY,
-            "stock-size", GTK_ICON_SIZE_MENU, NULL);
+    g_object_set(G_OBJECT(render),
+                 "stock-id", GTK_STOCK_DIRECTORY,
+                 "stock-size", GTK_ICON_SIZE_MENU,
+                 NULL);
 #else
     {
         gint iw, ih;
@@ -1538,30 +1404,33 @@
     imailbox->render = render = gtk_cell_renderer_text_new();
     gtk_tree_view_column_pack_start(col, render, TRUE);
     gtk_tree_view_column_set_attributes(col, render,
-            "text", IMAP_FOLDERS_NAME, NULL);
+                                        "text", IMAP_FOLDERS_NAME,
+                                        NULL);
     {
         GtkStyle *style;
         gtk_widget_realize(topvbox);
         style = gtk_widget_get_style(topvbox);
         g_object_set(G_OBJECT(render), "foreground-gdk",
-                &style->fg[GTK_STATE_INSENSITIVE],
-                "foreground-set", TRUE,
-                "style", PANGO_STYLE_ITALIC,
-                "style-set", TRUE, NULL);
+                     &style->fg[GTK_STATE_INSENSITIVE],
+                     "foreground-set", TRUE,
+                     "style", PANGO_STYLE_ITALIC,
+                     "style-set", TRUE,
+                     NULL);
     }
     
     gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), col);
     gtk_tree_view_set_expander_column(GTK_TREE_VIEW(treeview), col);
     
     render = gtk_cell_renderer_toggle_new();
-    col = gtk_tree_view_column_new_with_attributes("watching", render, "active",
-            IMAP_FOLDERS_WATCHING, NULL);
+    col = gtk_tree_view_column_new_with_attributes("watching", render,
+                                                   "active", IMAP_FOLDERS_WATCHING,
+                                                   NULL);
     gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), col);
     
     gtk_widget_show(treeview);
     gtk_container_add(GTK_CONTAINER(sw), treeview);
     g_signal_connect(G_OBJECT(treeview), "button-press-event",
-            G_CALLBACK(imap_config_treeview_btnpress_cb), imailbox);
+                     G_CALLBACK(imap_config_treeview_btnpress_cb), imailbox);
     
     sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(treeview));
     gtk_tree_selection_set_mode(sel, GTK_SELECTION_MULTIPLE);
@@ -1576,14 +1445,16 @@
     gtk_box_pack_start(GTK_BOX(vbox), btn, FALSE, FALSE, 0);
     g_object_set_data(G_OBJECT(btn), "mailwatch-treeview", treeview);
     g_signal_connect(G_OBJECT(btn), "clicked",
-            G_CALLBACK(imap_config_refresh_btn_clicked_cb), imailbox);
+                     G_CALLBACK(imap_config_refresh_btn_clicked_cb), imailbox);
     
     gtk_tree_store_append(ts, &itr, NULL);
     gtk_tree_store_set(ts, &itr, IMAP_FOLDERS_NAME, _("Please wait..."), -1);
     gtk_widget_set_sensitive(btn, FALSE);
-    imailbox->folder_tree_aqueue = g_async_queue_new();
-    imailbox->folder_tree_th = g_thread_create(imap_populate_folder_tree_th,
-                                               imailbox, TRUE, NULL);
+
+    g_atomic_int_set(&imailbox->folder_tree_running, TRUE);
+    th = g_thread_create(imap_populate_folder_tree_th,
+                         imailbox, FALSE, NULL);
+    g_atomic_pointer_set(&imailbox->folder_tree_th, th);
     
     gtk_dialog_run(GTK_DIALOG(dlg));
     gtk_widget_destroy(dlg);
@@ -1911,12 +1782,9 @@
             imailbox->use_standard_port = *(param->value) == '0' ? FALSE : TRUE;
         else if(!strcmp(param->key, "nonstandard_port"))
             imailbox->nonstandard_port = atoi(param->value);
-        else if(!strcmp(param->key, "timeout")) {
+        else if(!strcmp(param->key, "timeout"))
             imailbox->timeout = atoi(param->value);
-            g_async_queue_push(imailbox->aqueue, IMAP_CMD_TIMEOUT);
-            g_async_queue_push(imailbox->aqueue,
-                    GUINT_TO_POINTER(imailbox->timeout));
-        } else if(!strcmp(param->key, "n_newmail_boxes"))
+        else if(!strcmp(param->key, "n_newmail_boxes"))
             n_newmail_boxes = atoi(param->value);
     }
     
@@ -2011,9 +1879,18 @@
 {
     XfceMailwatchIMAPMailbox *imailbox = XFCE_MAILWATCH_IMAP_MAILBOX(mailbox);
     
-    g_async_queue_push(imailbox->aqueue, IMAP_CMD_QUIT);
-    g_thread_join(imailbox->th);
-    g_async_queue_unref(imailbox->aqueue);
+    if(imailbox->check_id) {
+        g_source_remove(imailbox->check_id);
+        imailbox->check_id = 0;
+    }
+
+    g_atomic_int_set(&imailbox->folder_tree_running, FALSE);
+    while(g_atomic_pointer_get(&imailbox->folder_tree_th))
+        g_thread_yield();
+
+    g_atomic_int_set(&imailbox->running, FALSE);
+    while(g_atomic_pointer_get(&imailbox->th))
+        g_thread_yield();
     
     g_mutex_free(imailbox->config_mx);
     

Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c	2008-08-16 08:48:21 UTC (rev 5236)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c	2008-08-16 08:48:32 UTC (rev 5237)
@@ -38,38 +38,6 @@
 #include <sys/types.h>
 #endif
 
-#ifdef HAVE_SYS_SOCKET_H
-#include <sys/socket.h>
-#endif
-
-#if HAVE_NETINET_IN_H
-#include <netinet/in.h>
-#endif
-
-#ifdef HAVE_NETDB_H
-#include <netdb.h>
-#endif
-
-#ifdef HAVE_SYS_SELECT_H
-#include <sys/select.h>
-#endif
-
-#ifdef HAVE_SYS_WAIT_H
-#include <sys/wait.h>
-#endif
-
-#ifdef HAVE_FCNTL_H
-#include <fcntl.h>
-#endif
-
-#ifdef HAVE_ERRNO_H
-#include <errno.h>
-#endif
-
-#ifndef MSG_NOSIGNAL
-#define MSG_NOSIGNAL 0
-#endif
-
 #include <glib.h>
 #include <gtk/gtk.h>
 
@@ -78,6 +46,7 @@
 
 #include "mailwatch-utils.h"
 #include "mailwatch.h"
+#include "mailwatch-net-conn.h"
 
 #define BORDER                   8
 
@@ -86,12 +55,6 @@
 
 #define XFCE_MAILWATCH_POP3_MAILBOX(ptr) ((XfceMailwatchPOP3Mailbox *)ptr)
 
-#define POP3_CMD_START           GINT_TO_POINTER(1)
-#define POP3_CMD_PAUSE           GINT_TO_POINTER(2)
-#define POP3_CMD_TIMEOUT         GINT_TO_POINTER(3)
-#define POP3_CMD_QUIT            GINT_TO_POINTER(4)
-#define POP3_CMD_UPDATE          GINT_TO_POINTER(5)
-
 typedef struct
 {
     XfceMailwatchMailbox mailbox;
@@ -107,27 +70,34 @@
     gint nonstandard_port;
     XfceMailwatchAuthType auth_type;
     
-    GThread *th;
-    GAsyncQueue *aqueue;
+    gint running;
+    guint check_id;
+    gpointer th;  /* really a GThread *, but avoids casts later */
     
     XfceMailwatch *mailwatch;
     
     /* state related to the current connection (if any) */
-    gint sockfd;
-    /* secure this, dude */
-    XfceMailwatchSecurityInfo security_info;
+    XfceMailwatchNetConn *net_conn;
 } XfceMailwatchPOP3Mailbox;
 
+
+static gboolean
+pop3_should_continue(XfceMailwatchNetConn *net_conn,
+                     gpointer user_data)
+{
+    XfceMailwatchPOP3Mailbox *pmailbox = user_data;
+    return g_atomic_int_get(&pmailbox->running);
+}
+
 static gssize
 pop3_send(XfceMailwatchPOP3Mailbox *pmailbox, const gchar *buf)
 {
     GError *error = NULL;
     gssize sent;
     
-    sent = xfce_mailwatch_net_send(pmailbox->sockfd,
-                                   &pmailbox->security_info,
-                                   buf,
-                                   &error);
+    sent = xfce_mailwatch_net_conn_send_data(pmailbox->net_conn,
+                                             (guchar *)buf, strlen(buf),
+                                             &error);
     if(sent < 0) {
         xfce_mailwatch_log_message(pmailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(pmailbox),
@@ -145,11 +115,8 @@
     GError *error = NULL;
     gssize recvd;
     
-    recvd = xfce_mailwatch_net_recv(pmailbox->sockfd,
-                                    &pmailbox->security_info,
-                                    buf,
-                                    len,
-                                    &error);
+    recvd = xfce_mailwatch_net_conn_recv_line(pmailbox->net_conn,
+                                              buf, len, &error);
     
     if(recvd < 0) {
         xfce_mailwatch_log_message(pmailbox->mailwatch,
@@ -162,39 +129,7 @@
     return recvd;
 }
 
-static void
-pop3_do_logout(XfceMailwatchPOP3Mailbox *pmailbox)
-{
-    pop3_send(pmailbox, "QUIT\r\n");
-    
-    shutdown(pmailbox->sockfd, SHUT_RDWR);
-    close(pmailbox->sockfd);
-    pmailbox->sockfd = -1;
-}
-
 static gboolean
-pop3_get_addrinfo(XfceMailwatchPOP3Mailbox *pmailbox, const gchar *host,
-                  const gchar *service, struct addrinfo **addresses)
-{
-    GError *error = NULL;
-    
-    TRACE("entering (%s, %s, %p)", host, service, addresses);
-    
-    g_return_val_if_fail(host && service && addresses, FALSE);
-    
-    if(!xfce_mailwatch_net_get_addrinfo(host, service, addresses, &error)) {
-        xfce_mailwatch_log_message(pmailbox->mailwatch,
-                                   XFCE_MAILWATCH_MAILBOX(pmailbox),
-                                   XFCE_MAILWATCH_LOG_ERROR,
-                                   error->message);
-        g_error_free(error);
-        return FALSE;
-    }
-    
-    return TRUE;
-}
-
-static gboolean
 pop3_send_login_info(XfceMailwatchPOP3Mailbox *pmailbox, const gchar *username,
         const gchar *password)
 {
@@ -210,7 +145,7 @@
     g_strlcpy(buf, "CAPA\r\n", BUFSIZE);
     bout = pop3_send(pmailbox, buf);
     if(bout != strlen(buf))
-        goto cleanuperr;
+        return FALSE;
 
     off = 0;
     do {
@@ -219,7 +154,7 @@
             off += bin;
     } while(bin > 0 && !strstr(buf, ".\r\n"));
     if(bin < 0)
-        goto cleanuperr;
+        return FALSE;
 
     if((p = strstr(buf, "SASL ")) && (q = strstr(p, "\r\n"))
        && (p = strstr(p, "CRAM-MD5")) && p < q)
@@ -228,11 +163,11 @@
         g_strlcpy(buf, "AUTH CRAM-MD5\r\n", BUFSIZE);
         bout = pop3_send(pmailbox, buf);
         if(bout != strlen(buf))
-            goto cleanuperr;
+            return FALSE;
 
         bin = pop3_recv(pmailbox, buf, BUFSIZE);
         if(bin <= 0)
-            goto cleanuperr;
+            return FALSE;
         DBG("got cram-md5 challenge: %s\n", buf);
 
         if(*buf == '+' && *(buf+1) == ' ' && *(buf+2)) {
@@ -243,27 +178,27 @@
                 p = strstr(buf, "\n");
             if(!p) {
                 DBG("cram-md5 challenge wasn't a full line?");
-                goto cleanuperr;
+                return FALSE;
             }
             *p = 0;
 
             response_base64 = xfce_mailwatch_cram_md5(username, password,
                                                       buf + 2);
             if(!response_base64)
-                goto cleanuperr;
+                return FALSE;
             g_strlcpy(buf, response_base64, BUFSIZE);
             g_strlcat(buf, "\r\n", BUFSIZE);
             g_free(response_base64);
             bout = pop3_send(pmailbox, buf);
             if(bout != strlen(buf))
-                goto cleanuperr;
+                return FALSE;
 
             bin = pop3_recv(pmailbox, buf, BUFSIZE);
             if(bin <= 0)
-                goto cleanuperr;
+                return FALSE;
             DBG("got response to cram-md5 auth: %s", buf);
             if(strncmp(buf, "+OK", 3))
-                goto cleanuperr;
+                return FALSE;
 
             TRACE("leaving (success)");
 
@@ -277,44 +212,36 @@
     bout = pop3_send(pmailbox, buf);
     DBG("sent user (%d)", bout);
     if(bout != strlen(buf))
-        goto cleanuperr;
+        return FALSE;
     
     /* check for OK response */
     bin = pop3_recv(pmailbox, buf, BUFSIZE);
     DBG("response from USER (%d): %s", bin, bin>0?buf:"(nada)");
     if(bin <= 0)
-        goto cleanuperr;
+        return FALSE;
     DBG("strstr() returns %p", strstr(buf, "+OK"));
     if(g_ascii_strncasecmp(buf, "+OK", 3))
-        goto cleanuperr;
+        return FALSE;
     
     /* send the password */
     g_snprintf(buf, BUFSIZE, "PASS %s\r\n", password);
     bout = pop3_send(pmailbox, buf);
     DBG("sent password (%d)", bout);
     if(bout != strlen(buf))
-        goto cleanuperr;
+        return FALSE;
     
     /* check for OK response */
     bin = pop3_recv(pmailbox, buf, BUFSIZE);
     DBG("response from USER (%d): %s", bin, bin>0?buf:"(nada)");
     if(bin <= 0)
-        goto cleanuperr;
+        return FALSE;
     DBG("strstr() returns %p", strstr(buf, "OK"));
     if(g_ascii_strncasecmp(buf, "+OK", 3))
-        goto cleanuperr;
+        return FALSE;
     
     TRACE("leaving (success)");
     
     return TRUE;
-    
-cleanuperr:
-    
-    shutdown(pmailbox->sockfd, SHUT_RDWR);
-    close(pmailbox->sockfd);
-    pmailbox->sockfd = -1;
-    
-    return FALSE;
 #undef BUFSIZE
 }
 
@@ -324,8 +251,7 @@
     gboolean ret;
     GError *error = NULL;
     
-    ret = xfce_mailwatch_net_negotiate_tls(pmailbox->sockfd,
-            &pmailbox->security_info, host, &error);
+    ret = xfce_mailwatch_net_conn_make_secure(pmailbox->net_conn, &error);
     
     if(!ret) {
         xfce_mailwatch_log_message(pmailbox->mailwatch,
@@ -334,9 +260,6 @@
                                    _("TLS handshake failed: %s"),
                                    error->message);
         g_error_free(error);
-        shutdown(pmailbox->sockfd, SHUT_RDWR);
-        close(pmailbox->sockfd);
-        pmailbox->sockfd = -1;
     }
     
     return ret;
@@ -353,35 +276,24 @@
     TRACE("entering");
     
     if(pop3_send(pmailbox, "CAPA\r\n") != 6)
-        goto cleanuperr;
+        return FALSE;
     
     bin = pop3_recv(pmailbox, buf, BUFSIZE);
     DBG("checking for STLS caps (%d): %s", bin, bin>0?buf:"(nada)");
     if(bin <= 0)
-        goto cleanuperr;
+        return FALSE;
     if(!strstr(buf, "\r\nSTLS\r\n"))
-        goto cleanuperr;
+        return FALSE;
     
     if(pop3_send(pmailbox, "STLS\r\n") != 6)
-        goto cleanuperr;
+        return FALSE;
     
     if(pop3_recv(pmailbox, buf, BUFSIZE) < 0)
-        goto cleanuperr;
+        return FALSE;
     if(g_ascii_strncasecmp(buf, "+OK", 3))
-        goto cleanuperr;
+        return FALSE;
     
-    /* now that we've negotiated SSL, reenable using_tls */
-    pmailbox->security_info.using_tls = TRUE;
-    
     return TRUE;
-    
-    cleanuperr:
-    
-    shutdown(pmailbox->sockfd, SHUT_RDWR);
-    close(pmailbox->sockfd);
-    pmailbox->sockfd = -1;
-    
-    return FALSE;
 #undef BUFSIZE
 }
 
@@ -389,134 +301,27 @@
 pop3_connect(XfceMailwatchPOP3Mailbox *pmailbox, const gchar *host,
         const gchar *service, gint nonstandard_port)
 {
-    struct addrinfo *addresses = NULL, *ai;
-    gchar buf[16] = { 0, };
-    gpointer msg = NULL;
+    GError *error = NULL;
     
     TRACE("entering (%s)", service);
     
+    pmailbox->net_conn = xfce_mailwatch_net_conn_new(host, service);
     if(nonstandard_port > 0)
-        g_snprintf(buf, sizeof(buf), "%d", nonstandard_port);
+        xfce_mailwatch_net_conn_set_port(pmailbox->net_conn, nonstandard_port);
+    xfce_mailwatch_net_conn_set_should_continue_func(pmailbox->net_conn,
+                                                     pop3_should_continue,
+                                                     pmailbox);
     
-    if(!pop3_get_addrinfo(pmailbox, host, *buf ? buf : service, &addresses)) {
-        DBG("failed to get sockaddr");
+    if(xfce_mailwatch_net_conn_connect(pmailbox->net_conn, &error))
+        return TRUE;
+    else {
+        xfce_mailwatch_log_message(pmailbox->mailwatch,
+                                   XFCE_MAILWATCH_MAILBOX(pmailbox),
+                                   XFCE_MAILWATCH_LOG_ERROR,
+                                   "%s", error->message);
+        g_error_free(error);
         return FALSE;
     }
-    
-    for(ai = addresses; ai; ai = ai->ai_next) {
-        pmailbox->sockfd = socket(ai->ai_family, ai->ai_socktype,
-                                  ai->ai_protocol);
-        if(pmailbox->sockfd < 0)
-            continue;
-    
-#if 0
-        if(pmailbox->sockfd < 0) {
-            xfce_mailwatch_log_message(pmailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(pmailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       "socket(): %s",
-                                       strerror(errno));
-            DBG("failed to open socket");
-            return FALSE;
-        }
-#endif
-        /* this next batch of crap is necessary because it seems like a failed
-         * connection (that is, one that isn't ECONNREFUSED) takes over 3 minutes
-         * to fail!  if the panel is trying to quit, that's just unacceptable.
-         */
-        
-        if(fcntl(pmailbox->sockfd, F_SETFL,
-                 fcntl(pmailbox->sockfd, F_GETFL) | O_NONBLOCK))
-        {
-            xfce_mailwatch_log_message(pmailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(pmailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       _("Unable to set socket to non-blocking mode.  If the connect attempt hangs, the panel may hang on close."));
-        }
-        
-        if(connect(pmailbox->sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
-            gboolean failed = TRUE;
-            
-            if(errno == EINPROGRESS) {
-                gint iters_left;
-                for(iters_left = 25; iters_left >= 0; iters_left--) {
-                    fd_set wfd;
-                    struct timeval tv = { 2, 0 };
-                    int sock_err = 0;
-                    socklen_t sock_err_len = sizeof(int);
-                    
-                    FD_ZERO(&wfd);
-                    FD_SET(pmailbox->sockfd, &wfd);
-                    
-                    DBG("checking for a connection...");
-                    
-                    /* wait until the connect attempt finishes */
-                    if(select(FD_SETSIZE, NULL, &wfd, NULL, &tv) < 0)
-                        break;
-                    
-                    /* check to see if it finished, and, if so, if there was an
-                     * error, or if it completed successfully */
-                    if(FD_ISSET(pmailbox->sockfd, &wfd)) {
-                        if(!getsockopt(pmailbox->sockfd, SOL_SOCKET, SO_ERROR,
-                                       &sock_err, &sock_err_len)
-                           && !sock_err)
-                        {
-                            DBG("    connection succeeded");
-                            failed = FALSE;
-                        } else {
-#if 0
-                            xfce_mailwatch_log_message(pmailbox->mailwatch,
-                                                       XFCE_MAILWATCH_MAILBOX(pmailbox),
-                                                       XFCE_MAILWATCH_LOG_ERROR,
-                                                       _("Failed to connect to server: %s"),
-                                                       strerror(sock_err));
-#endif
-                            DBG("    connection failed: sock_err is (%d) %s",
-                                sock_err, strerror(sock_err));
-                        }
-                        break;
-                    }
-                    
-                    /* check the main thread to see if we're supposed to quit */
-                    msg = g_async_queue_try_pop(pmailbox->aqueue);
-                    if(msg) {
-                        /* put it back so pop3_check_mail_th() can read it */
-                        g_async_queue_push(pmailbox->aqueue, msg);
-                        if(msg == POP3_CMD_QUIT) {
-                            failed = TRUE;
-                            break;
-                        }
-                        msg = NULL;
-                    }
-                }
-            }
-            
-            if(failed) {
-                DBG("failed to connect");
-                close(pmailbox->sockfd);
-                pmailbox->sockfd = -1;
-                continue;
-            } else
-                break;
-        }
-        
-        if(fcntl(pmailbox->sockfd, F_SETFL,
-                 fcntl(pmailbox->sockfd, F_GETFL) & ~(O_NONBLOCK)))
-        {
-            xfce_mailwatch_log_message(pmailbox->mailwatch,
-                                       XFCE_MAILWATCH_MAILBOX(pmailbox),
-                                       XFCE_MAILWATCH_LOG_WARNING,
-                                       _("Unable to return socket to blocking mode.  Data may not be retreived correctly."));
-        }
-        
-        if(msg && msg == POP3_CMD_QUIT)
-            break;
-    }
-    
-    if(addresses)
-        freeaddrinfo(addresses);
-    
-    return (pmailbox->sockfd >= 0);
 }
 
 static inline gboolean
@@ -525,18 +330,13 @@
     gchar buf[2048];
     gint bin;
     
-    do {
-        bin = pop3_recv(pmailbox, buf, sizeof(buf)-1);
-        if(bin < 0) {
-            DBG("failed to get banner");
-            shutdown(pmailbox->sockfd, SHUT_RDWR);
-            close(pmailbox->sockfd);
-            pmailbox->sockfd = -1;
-        } else {
-            buf[bin] = 0;
-            DBG("got banner, discarding: %s\n", buf);
-        }
-    } while(bin != -1 && !strchr(buf, '\n'));
+    bin = pop3_recv(pmailbox, buf, sizeof(buf)-1);
+    if(bin < 0) {
+        DBG("failed to get banner");
+    } else {
+        buf[bin] = 0;
+        DBG("got banner, discarding: %s\n", buf);
+    }
     
     return (bin != -1);
 }
@@ -552,14 +352,12 @@
     
     switch(auth_type) {
         case AUTH_NONE:
-            pmailbox->security_info.using_tls = FALSE;
             ret = pop3_connect(pmailbox, host, "pop3", nonstandard_port);
             if(ret)
                 ret = pop3_slurp_banner(pmailbox);
             break;
         
         case AUTH_STARTTLS:
-            pmailbox->security_info.using_tls = FALSE;
             ret = pop3_connect(pmailbox, host, "pop3", nonstandard_port);
             if(ret)
                 ret = pop3_slurp_banner(pmailbox);
@@ -567,11 +365,9 @@
                 ret = pop3_do_stls(pmailbox, host, username, password);
             if(ret)
                 ret = pop3_negotiate_ssl(pmailbox, host);
-            pmailbox->security_info.using_tls = TRUE;
             break;
         
         case AUTH_SSL_PORT:
-            pmailbox->security_info.using_tls = TRUE;
             ret = pop3_connect(pmailbox, host, "pop3s", nonstandard_port);
             if(ret)
                 ret = pop3_negotiate_ssl(pmailbox, host);
@@ -584,10 +380,13 @@
             return FALSE;
     }
     
-    DBG("using_tls is %s", pmailbox->security_info.using_tls?"TRUE":"FALSE");
-        
-    if(ret && !pop3_send_login_info(pmailbox, username, password))
-        return FALSE;
+    if(ret)
+        ret = pop3_send_login_info(pmailbox, username, password);
+
+    if(!ret) {
+        xfce_mailwatch_net_conn_destroy(pmailbox->net_conn);
+        pmailbox->net_conn = NULL;
+    }
     
     return ret;
 }
@@ -621,20 +420,33 @@
     return new_messages;
 }
 
-static void
-pop3_check_mail(XfceMailwatchPOP3Mailbox *pmailbox)
+static gpointer
+pop3_check_mail_th(gpointer user_data)
 {
 #define BUFSIZE 1024
+    XfceMailwatchPOP3Mailbox *pmailbox = user_data;
     gchar host[BUFSIZE], username[BUFSIZE], password[BUFSIZE];
     guint new_messages = 0;
     XfceMailwatchAuthType auth_type;
     gint nonstandard_port = -1;
+
+    while(!g_atomic_pointer_get(&pmailbox->th)
+          && g_atomic_int_get(&pmailbox->running))
+    {
+        g_thread_yield();
+    }
+
+    if(!g_atomic_int_get(&pmailbox->running)) {
+        g_atomic_pointer_set(&pmailbox->th, NULL);
+        return NULL;
+    }
     
     g_mutex_lock(pmailbox->config_mx);
     
     if(!pmailbox->host || !pmailbox->username || !pmailbox->password) {
         g_mutex_unlock(pmailbox->config_mx);
-        return;
+        g_atomic_pointer_set(&pmailbox->th, NULL);
+        return NULL;
     }
     
     g_strlcpy(host, pmailbox->host, BUFSIZE);
@@ -646,72 +458,26 @@
     
     g_mutex_unlock(pmailbox->config_mx);
     
-    if(!pop3_authenticate(pmailbox, host, username, password, auth_type,
-            nonstandard_port))
+    if(pop3_authenticate(pmailbox, host, username, password, auth_type,
+                         nonstandard_port))
     {
-        DBG("failed to connect to pop3 server");
-        goto cleanup;
+        new_messages = pop3_check_inbox(pmailbox);
+        DBG("checked inbox, %d new messages", new_messages);
+        
+        xfce_mailwatch_signal_new_messages(pmailbox->mailwatch,
+                XFCE_MAILWATCH_MAILBOX(pmailbox), new_messages);
     }
     
-    new_messages = pop3_check_inbox(pmailbox);
-    DBG("checked inbox, %d new messages", new_messages);
+    pop3_send(pmailbox, "QUIT\r\n");
     
-    xfce_mailwatch_signal_new_messages(pmailbox->mailwatch,
-            XFCE_MAILWATCH_MAILBOX(pmailbox), new_messages);
-    
-    cleanup:
-    
-    pop3_do_logout(pmailbox);
-    
-    xfce_mailwatch_net_tls_teardown(&pmailbox->security_info);
-    
-#undef BUFSIZE
-}
-
-static gpointer
-pop3_check_mail_th(gpointer user_data)
-{
-    XfceMailwatchPOP3Mailbox *pmailbox = user_data;
-    gboolean running = FALSE;
-    GTimeVal start, now;
-    guint timeout = 0, delta = 0;
-    
-    g_async_queue_ref(pmailbox->aqueue);
-    
-    g_get_current_time(&start);
-    
-    for(;;) {
-        gpointer msg = g_async_queue_try_pop(pmailbox->aqueue);
-        
-        if(msg) {
-            if(msg == POP3_CMD_START) {
-                g_get_current_time(&start);;
-                running = TRUE;
-            } else if(msg == POP3_CMD_PAUSE)
-                running = FALSE;
-            else if(msg == POP3_CMD_TIMEOUT)
-                timeout = GPOINTER_TO_UINT(g_async_queue_pop(pmailbox->aqueue));
-            else if(msg == POP3_CMD_QUIT) {
-                g_async_queue_unref(pmailbox->aqueue);
-                g_thread_exit(NULL);
-            }
-        }
-        
-        g_get_current_time(&now);
-        
-        if(running && (msg == POP3_CMD_UPDATE
-                || now.tv_sec - start.tv_sec >= timeout - delta))
-        {
-            pop3_check_mail(pmailbox);
-            g_get_current_time(&start);
-            delta = (gint)start.tv_sec - now.tv_sec;
-        } else
-            g_usleep(250000);
+    if(pmailbox->net_conn) {
+        xfce_mailwatch_net_conn_destroy(pmailbox->net_conn);
+        pmailbox->net_conn = NULL;
     }
-    
-    /* NOTREACHED */
-    g_async_queue_unref(pmailbox->aqueue);
+
+    g_atomic_pointer_set(&pmailbox->th, NULL);
     return NULL;
+#undef BUFSIZE
 }
 
 static XfceMailwatchMailbox *
@@ -723,32 +489,71 @@
     pmailbox->timeout = XFCE_MAILWATCH_DEFAULT_TIMEOUT;
     pmailbox->use_standard_port = TRUE;
     pmailbox->config_mx = g_mutex_new();
-    /* init the queue */
-    pmailbox->aqueue = g_async_queue_new();
-    /* and init the timeout */
-    g_async_queue_push(pmailbox->aqueue, POP3_CMD_TIMEOUT);
-    g_async_queue_push(pmailbox->aqueue,
-            GUINT_TO_POINTER(XFCE_MAILWATCH_DEFAULT_TIMEOUT));
-    /* create checker thread */
-    pmailbox->th = g_thread_create(pop3_check_mail_th, pmailbox, TRUE, NULL);
     
-    return (XfceMailwatchMailbox *)pmailbox;
+    return XFCE_MAILWATCH_MAILBOX(pmailbox);
 }
 
+static gboolean
+pop3_check_mail_timeout(gpointer data)
+{
+    XfceMailwatchPOP3Mailbox *pmailbox = data;
+    GThread *new_th;
+
+    if(g_atomic_pointer_get(&pmailbox->th)) {
+        xfce_mailwatch_log_message(pmailbox->mailwatch,
+                                   XFCE_MAILWATCH_MAILBOX(pmailbox),
+                                   XFCE_MAILWATCH_LOG_WARNING,
+                                   _("Previous thread hasn't exited yet, not checking mail this time."));
+        return TRUE;
+    }
+
+    new_th = g_thread_create(pop3_check_mail_th, pmailbox, FALSE, NULL);
+    g_atomic_pointer_set(&pmailbox->th, new_th);
+
+    return TRUE;
+}
+
 static void
 pop3_set_activated(XfceMailwatchMailbox *mailbox, gboolean activated)
 {
     XfceMailwatchPOP3Mailbox *pmailbox = XFCE_MAILWATCH_POP3_MAILBOX(mailbox);
-    
-    g_async_queue_push(pmailbox->aqueue, activated ? POP3_CMD_START : POP3_CMD_PAUSE);
+
+    if(activated == g_atomic_int_get(&pmailbox->running))
+        return;
+
+    if(activated) {
+        g_atomic_int_set(&pmailbox->running, TRUE);
+        pmailbox->check_id = g_timeout_add(pmailbox->timeout * 1000,
+                                           pop3_check_mail_timeout,
+                                           pmailbox);
+    } else {
+        g_atomic_int_set(&pmailbox->running, FALSE);
+        g_source_remove(pmailbox->check_id);
+        pmailbox->check_id = 0;
+    }
 }
 
 static void
 pop3_force_update_cb(XfceMailwatchMailbox *mailbox)
 {
     XfceMailwatchPOP3Mailbox *pmailbox = XFCE_MAILWATCH_POP3_MAILBOX(mailbox);
-    
-    g_async_queue_push(pmailbox->aqueue, POP3_CMD_UPDATE);
+
+    if(!g_atomic_pointer_get(&pmailbox->th)) {
+        gboolean restart = FALSE;
+
+        if(pmailbox->check_id) {
+            g_source_remove(pmailbox->check_id);
+            restart = TRUE;
+        }
+
+        pop3_check_mail_timeout(pmailbox);
+
+        if(restart) {
+            pmailbox->check_id = g_timeout_add(pmailbox->timeout * 1000,
+                                               pop3_check_mail_timeout,
+                                               pmailbox);
+        }
+    }
 }
 
 static gboolean
@@ -820,18 +625,24 @@
     return FALSE;
 }
 
-static gboolean
+static void
 pop3_config_timeout_spinbutton_changed_cb(GtkSpinButton *sb,
                                           gpointer user_data)
 {
     XfceMailwatchPOP3Mailbox *pmailbox = user_data;
     gint value = gtk_spin_button_get_value_as_int(sb) * 60;
+
+    if(value == pmailbox->timeout)
+        return;
     
     pmailbox->timeout = value;
-    g_async_queue_push(pmailbox->aqueue, POP3_CMD_TIMEOUT);
-    g_async_queue_push(pmailbox->aqueue, GUINT_TO_POINTER(value));
-    
-    return FALSE;
+    if(g_atomic_int_get(&pmailbox->running)) {
+        if(pmailbox->check_id)
+            g_source_remove(pmailbox->check_id);
+        pmailbox->check_id = g_timeout_add(pmailbox->timeout * 1000,
+                                           pop3_check_mail_timeout,
+                                           pmailbox);
+    }
 }
 
 static void
@@ -1107,12 +918,8 @@
             pmailbox->use_standard_port = *(param->value) == '0' ? FALSE : TRUE;
         else if(!strcmp(param->key, "nonstandard_port"))
             pmailbox->nonstandard_port = atoi(param->value);
-        else if(!strcmp(param->key, "timeout")) {
+        else if(!strcmp(param->key, "timeout"))
             pmailbox->timeout = atoi(param->value);
-            g_async_queue_push(pmailbox->aqueue, POP3_CMD_TIMEOUT);
-            g_async_queue_push(pmailbox->aqueue,
-                    GUINT_TO_POINTER(pmailbox->timeout));
-        }
     }
     
     g_mutex_unlock(pmailbox->config_mx);
@@ -1174,9 +981,9 @@
 {
     XfceMailwatchPOP3Mailbox *pmailbox = XFCE_MAILWATCH_POP3_MAILBOX(mailbox);
     
-    g_async_queue_push(pmailbox->aqueue, POP3_CMD_QUIT);
-    g_thread_join(pmailbox->th);
-    g_async_queue_unref(pmailbox->aqueue);
+    g_atomic_int_set(&pmailbox->running, FALSE);
+    while(g_atomic_pointer_get(&pmailbox->th))
+        g_thread_yield();
     
     g_mutex_free(pmailbox->config_mx);
     




More information about the Goodies-commits mailing list