[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