[Goodies-commits] r3904 - in xfce4-mailwatch-plugin/trunk: . libmailwatch-core

Brian Tarricone kelnos at xfce.org
Thu Jan 31 12:40:48 CET 2008


Author: kelnos
Date: 2008-01-31 11:40:48 +0000 (Thu, 31 Jan 2008)
New Revision: 3904

Modified:
   xfce4-mailwatch-plugin/trunk/configure.ac
   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
   xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.c
   xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.h
Log:
use getaddrinfo() properly and add (untested) support for ipv6


Modified: xfce4-mailwatch-plugin/trunk/configure.ac
===================================================================
--- xfce4-mailwatch-plugin/trunk/configure.ac	2008-01-31 11:40:37 UTC (rev 3903)
+++ xfce4-mailwatch-plugin/trunk/configure.ac	2008-01-31 11:40:48 UTC (rev 3904)
@@ -65,6 +65,18 @@
 fi
 AM_CONDITIONAL([HAVE_SSL_SUPPORT], [test "x$GNUTLS_FOUND" = "xyes"])
 
+dnl to ipv6, or to not ipv6
+AC_MSG_CHECKING([whether to support IPv6])
+AC_ARG_WITH([ipv6],
+            [AC_HELP_STRING([--disable-ipv6],
+                            [Disable IPv6 support (default=enabled)])],
+            [enable_ipv6_support=$withval], [enable_ipv6_support=yes])
+AC_MSG_RESULT([$enable_ipv6_support])
+if test "x$enable_ipv6_support" = "xyes"; then
+    AC_DEFINE([ENABLE_IPV6_SUPPORT], [1],
+              [Define if IPv6 support should be enabled])
+fi
+
 dnl check for debugging support
 XDT_FEATURE_DEBUG
 

Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-gmail.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-gmail.c	2008-01-31 11:40:37 UTC (rev 3903)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-gmail.c	2008-01-31 11:40:48 UTC (rev 3904)
@@ -156,18 +156,16 @@
 }
 
 static gboolean
-gmail_get_sockaddr(XfceMailwatchGMailMailbox *gmailbox, const gchar *host,
-                  const gchar *service, struct sockaddr_in *addr)
+gmail_get_addrinfo(XfceMailwatchGMailMailbox *gmailbox, const gchar *host,
+                  const gchar *service, struct addrinfo **addresses)
 {
-    struct addrinfo hints = { 0, PF_INET, SOCK_STREAM, IPPROTO_TCP,
-            0, NULL, NULL, NULL };
     GError *error = NULL;
     
-    TRACE("entering (%s, %s, %p)", host, service, addr);
+    TRACE("entering (%s, %s, %p)", host, service, addresses);
     
-    g_return_val_if_fail(host && service && addr, FALSE);
+    g_return_val_if_fail(host && service && addresses, FALSE);
     
-    if(!xfce_mailwatch_net_get_sockaddr(host, service, &hints, addr, &error)) {
+    if(!xfce_mailwatch_net_get_addrinfo(host, service, addresses, &error)) {
         xfce_mailwatch_log_message(gmailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(gmailbox),
                                    XFCE_MAILWATCH_LOG_ERROR,
@@ -183,110 +181,133 @@
 static gboolean
 gmail_connect(XfceMailwatchGMailMailbox *gmailbox, gint *port)
 {
-    struct sockaddr_in addr;
+    struct addrinfo *addresses = NULL, *ai;
+    gpointer msg = NULL;
     
-    if(!gmail_get_sockaddr(gmailbox, GMAIL_HOST, "https", &addr)) {
+    if(!gmail_get_addrinfo(gmailbox, GMAIL_HOST, "https", &addresses)) {
         DBG("failed to get sockaddr");
         return FALSE;
     }
     
-    *port = ntohs(addr.sin_port);
+    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(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-    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;
-    }
-    
-    /* 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, (struct sockaddr *)&addr,
-            sizeof(struct sockaddr_in)))
-    {
-        gboolean failed = TRUE;
+        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(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);
-                gpointer msg;
-                
-                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 {
-                        xfce_mailwatch_log_message(gmailbox->mailwatch,
-                                                   XFCE_MAILWATCH_MAILBOX(gmailbox),
-                                                   XFCE_MAILWATCH_LOG_ERROR,
-                                                   _("Failed to connect to server: %s"),
-                                                   strerror(sock_err));
-                        DBG("    connection failed: sock_err is %d", 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;
+        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(failed) {
-            DBG("failed to connect");
-            close(gmailbox->sockfd);
-            gmailbox->sockfd = -1;
-            return FALSE;
+        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(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."));
-    }
-    
-    return TRUE;
+    return (gmailbox->sockfd >= 0);
 }
 
 static gboolean
@@ -299,7 +320,7 @@
     gboolean ret = FALSE, first_recv = TRUE;
     GError *error = NULL;
     gchar buf[BUFSIZE+1], *base64_creds, *p, *q;
-    gint bin, port, respcode, tmp;
+    gint bin, port = 0, respcode, tmp;
     
     if(!gmail_connect(gmailbox, &port)) {
         DBG("failed to connect to gmail server");

Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c	2008-01-31 11:40:37 UTC (rev 3903)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-imap.c	2008-01-31 11:40:48 UTC (rev 3904)
@@ -205,18 +205,16 @@
 }
 
 static gboolean
-imap_get_sockaddr(XfceMailwatchIMAPMailbox *imailbox, const gchar *host,
-                  const gchar *service, struct sockaddr_in *addr)
+imap_get_addrinfo(XfceMailwatchIMAPMailbox *imailbox, const gchar *host,
+                  const gchar *service, struct addrinfo **addresses)
 {
-    struct addrinfo hints = { 0, PF_INET, SOCK_STREAM, IPPROTO_TCP,
-            0, NULL, NULL, NULL };
     GError *error = NULL;
         
-    TRACE("entering (%s, %s, %p)", host, service, addr);
+    TRACE("entering (%s, %s, %p)", host, service, addresses);
     
-    g_return_val_if_fail(host && service && addr, FALSE);
+    g_return_val_if_fail(host && service && addresses, FALSE);
     
-    if(!xfce_mailwatch_net_get_sockaddr(host, service, &hints, addr, &error)) {
+    if(!xfce_mailwatch_net_get_addrinfo(host, service, addresses, &error)) {
         xfce_mailwatch_log_message(imailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(imailbox),
                                    XFCE_MAILWATCH_LOG_ERROR,
@@ -364,113 +362,130 @@
 imap_connect(XfceMailwatchIMAPMailbox *imailbox, const gchar *host,
         const gchar *service, gint nonstandard_port)
 {
-    struct sockaddr_in addr;
-    
+    struct addrinfo *addresses = NULL, *ai;
+    gchar buf[16] = { 0, };
+    gpointer msg = NULL;
+
     TRACE("entering (%s)", service);
     
-    if(!imap_get_sockaddr(imailbox, host, service, &addr)) {
-        DBG("failed to get sockaddr");
-        return FALSE;
-    }
-    
     if(nonstandard_port > 0)
-        addr.sin_port = htons(nonstandard_port);
+        g_snprintf(buf, sizeof(buf), "%d", nonstandard_port);
     
-    imailbox->sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-    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");
+    if(!imap_get_addrinfo(imailbox, host, *buf ? buf : service, &addresses)) {
+        DBG("failed to get sockaddr");
         return FALSE;
     }
     
-    /* 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, (struct sockaddr *)&addr,
-            sizeof(struct sockaddr_in)))
-    {
-        gboolean failed = TRUE;
+    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(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);
-                gpointer msg;
-                
-                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 {
-                        xfce_mailwatch_log_message(imailbox->mailwatch,
-                                                   XFCE_MAILWATCH_MAILBOX(imailbox),
-                                                   XFCE_MAILWATCH_LOG_ERROR,
-                                                   _("Failed to connect to server: %s"),
-                                                   strerror(sock_err));
-                        DBG("    connection failed: sock_err is %d", 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;
+        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(failed) {
-            DBG("failed to connect");
-            close(imailbox->sockfd);
-            imailbox->sockfd = -1;
-            return FALSE;
+        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(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."));
-    }
-    
-    return TRUE;
+    return (imailbox->sockfd >= 0);
 }
 
 static inline gboolean

Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c	2008-01-31 11:40:37 UTC (rev 3903)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-mailbox-pop3.c	2008-01-31 11:40:48 UTC (rev 3904)
@@ -173,18 +173,16 @@
 }
 
 static gboolean
-pop3_get_sockaddr(XfceMailwatchPOP3Mailbox *pmailbox, const gchar *host,
-                  const gchar *service, struct sockaddr_in *addr)
+pop3_get_addrinfo(XfceMailwatchPOP3Mailbox *pmailbox, const gchar *host,
+                  const gchar *service, struct addrinfo **addresses)
 {
-    struct addrinfo hints = { 0, PF_INET, SOCK_STREAM, IPPROTO_TCP,
-            0, NULL, NULL, NULL };
     GError *error = NULL;
     
-    TRACE("entering (%s, %s, %p)", host, service, addr);
+    TRACE("entering (%s, %s, %p)", host, service, addresses);
     
-    g_return_val_if_fail(host && service && addr, FALSE);
+    g_return_val_if_fail(host && service && addresses, FALSE);
     
-    if(!xfce_mailwatch_net_get_sockaddr(host, service, &hints, addr, &error)) {
+    if(!xfce_mailwatch_net_get_addrinfo(host, service, addresses, &error)) {
         xfce_mailwatch_log_message(pmailbox->mailwatch,
                                    XFCE_MAILWATCH_MAILBOX(pmailbox),
                                    XFCE_MAILWATCH_LOG_ERROR,
@@ -323,113 +321,131 @@
 pop3_connect(XfceMailwatchPOP3Mailbox *pmailbox, const gchar *host,
         const gchar *service, gint nonstandard_port)
 {
-    struct sockaddr_in addr;
+    struct addrinfo *addresses = NULL, *ai;
+    gchar buf[16] = { 0, };
+    gpointer msg = NULL;
     
     TRACE("entering (%s)", service);
     
-    if(!pop3_get_sockaddr(pmailbox, host, service, &addr)) {
-        DBG("failed to get sockaddr");
-        return FALSE;
-    }
-    
     if(nonstandard_port > 0)
-        addr.sin_port = htons(nonstandard_port);
+        g_snprintf(buf, sizeof(buf), "%d", nonstandard_port);
     
-    pmailbox->sockfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
-    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");
+    if(!pop3_get_addrinfo(pmailbox, host, *buf ? buf : service, &addresses)) {
+        DBG("failed to get sockaddr");
         return FALSE;
     }
     
-    /* 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.
-     */
+    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(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, (struct sockaddr *)&addr,
-            sizeof(struct sockaddr_in)))
-    {
-        gboolean failed = TRUE;
+#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(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);
-                gpointer msg;
-                
-                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 {
-                        xfce_mailwatch_log_message(pmailbox->mailwatch,
-                                                   XFCE_MAILWATCH_MAILBOX(pmailbox),
-                                                   XFCE_MAILWATCH_LOG_ERROR,
-                                                   _("Failed to connect to server: %s"),
-                                                   strerror(sock_err));
-                        DBG("    connection failed: sock_err is %d", 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;
+        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(failed) {
-            DBG("failed to connect");
-            close(pmailbox->sockfd);
-            pmailbox->sockfd = -1;
-            return FALSE;
+        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(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."));
-    }
-    
-    return TRUE;
+    return (pmailbox->sockfd >= 0);
 }
 
 static inline gboolean

Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.c
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.c	2008-01-31 11:40:37 UTC (rev 3903)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.c	2008-01-31 11:40:48 UTC (rev 3904)
@@ -164,19 +164,32 @@
 #endif  /* defined(HAVE_SSL_SUPPORT) */
 
 gboolean
-xfce_mailwatch_net_get_sockaddr(const gchar *host, const gchar *service,
-        struct addrinfo *hints, struct sockaddr_in *addr, GError **error)
+xfce_mailwatch_net_get_addrinfo(const gchar *host,
+                                const gchar *service,
+                                struct addrinfo **results,
+                                GError **error)
 {
-    struct addrinfo *res = NULL;
+    struct addrinfo hints;
     gint ret;
     
+    g_return_val_if_fail(results && !*results, FALSE);  /* FIXME: set |error| */
+    
+    memset(&hints, 0, sizeof(hints));
+#ifdef ENABLE_IPV6_SUPPORT
+    hints.ai_family = AF_UNSPEC;
+#else
+    hints.ai_family = AF_INET;
+#endif
+    hints.ai_socktype = SOCK_STREAM;
+    hints.ai_flags = AI_ADDRCONFIG;
+    
     /* according to getaddrinfo(3), this should be reentrant.  however, calling
      * it from several threads often causes a crash.  bactraces show that we're
      * indeed inside getaddrinfo() in more than one thread, and I can't figure
      * out any other explanation. */
     
     xfce_mailwatch_threads_enter();
-    ret = getaddrinfo(host, service, hints, &res);
+    ret = getaddrinfo(host, service, &hints, results);
     xfce_mailwatch_threads_leave();
     if(ret) {
         if(error) {
@@ -186,18 +199,6 @@
         return FALSE;
     }
     
-    if(res->ai_addrlen != sizeof(struct sockaddr_in)) {
-        if(error) {
-            g_set_error(error, XFCE_MAILWATCH_ERROR, 0,
-                        "getaddrinfo(): res->ai_addrlen != sizeof(struct sockaddr_in)");
-        }
-        freeaddrinfo(res);
-        return FALSE;
-    }
-    
-    memcpy(addr, res->ai_addr, sizeof(struct sockaddr_in));
-    freeaddrinfo(res);
-    
     return TRUE;
 }
 

Modified: xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.h
===================================================================
--- xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.h	2008-01-31 11:40:37 UTC (rev 3903)
+++ xfce4-mailwatch-plugin/trunk/libmailwatch-core/mailwatch-utils.h	2008-01-31 11:40:48 UTC (rev 3904)
@@ -64,10 +64,9 @@
 #endif
 } XfceMailwatchSecurityInfo;
 
-gboolean xfce_mailwatch_net_get_sockaddr(const gchar *host,
+gboolean xfce_mailwatch_net_get_addrinfo(const gchar *host,
                                          const gchar *service,
-                                         struct addrinfo *hints,
-                                         struct sockaddr_in *addr,
+                                         struct addrinfo **results,
                                          GError **error);
 gboolean xfce_mailwatch_net_negotiate_tls(gint sockfd,
                                           XfceMailwatchSecurityInfo *security_info,




More information about the Goodies-commits mailing list