1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-12-27 04:32:55 +00:00

improving IMAP IDLE support

git-svn-id: https://conky.svn.sourceforge.net/svnroot/conky/trunk/conky1@1257 7f574dfc-610e-0410-a909-a81674777703
This commit is contained in:
Brenden Matthews 2008-09-25 03:11:24 +00:00
parent c15287e798
commit e80ec4cc5f
3 changed files with 67 additions and 87 deletions

View File

@ -1647,6 +1647,33 @@ struct mail_s *parse_mail_args(char type, const char *arg)
return mail;
}
int imap_command(int sockfd, char *command, char *response, const char *verify)
{
struct timeval timeout;
fd_set fdset;
int res, numbytes;
if (send(sockfd, command, strlen(command), 0) == -1) {
perror("send");
return -1;
}
timeout.tv_sec = 60; // 60 second timeout i guess
timeout.tv_usec = 0;
FD_ZERO(&fdset);
FD_SET(sockfd, &fdset);
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
if (res > 0) {
if ((numbytes = recv(sockfd, response, MAXDATASIZE - 1, 0)) == -1) {
perror("recv");
return -1;
}
}
response[numbytes] = '\0';
if (strstr(response, verify) == NULL) {
return -1;
}
return 0;
}
void *imap_thread(void *arg)
{
int sockfd, numbytes;
@ -1663,6 +1690,7 @@ void *imap_thread(void *arg)
struct sockaddr_in their_addr; // connector's address information
struct mail_s *mail = (struct mail_s *)arg;
int has_idle = 0;
int threadfd = timed_thread_readfd(mail->p_timed_thread);
#ifdef HAVE_GETHOSTBYNAME_R
if (gethostbyname_r(mail->host, &he, hostbuff, sizeof(hostbuff), &he_res, &he_errno)) { // get the host info
@ -1733,26 +1761,7 @@ void *imap_thread(void *arg)
strncat(sendbuf, " ", MAXDATASIZE - strlen(sendbuf) - 1);
strncat(sendbuf, mail->pass, MAXDATASIZE - strlen(sendbuf) - 1);
strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
perror("send a1");
fail++;
break;
}
timeout.tv_sec = 60; // 60 second timeout i guess
timeout.tv_usec = 0;
FD_ZERO(&fdset);
FD_SET(sockfd, &fdset);
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
if (res > 0) {
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
perror("recv a1");
fail++;
break;
}
}
recvbuf[numbytes] = '\0';
if (strstr(recvbuf, "a1 OK") == NULL) {
ERR("IMAP server login failed: %s", recvbuf);
if (imap_command(sockfd, sendbuf, recvbuf, "a1 OK")) {
fail++;
break;
}
@ -1764,26 +1773,7 @@ void *imap_thread(void *arg)
strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
strncat(sendbuf, " (MESSAGES UNSEEN)\r\n",
MAXDATASIZE - strlen(sendbuf) - 1);
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
perror("send a2");
fail++;
break;
}
timeout.tv_sec = 60; // 60 second timeout i guess
timeout.tv_usec = 0;
FD_ZERO(&fdset);
FD_SET(sockfd, &fdset);
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
if (res > 0) {
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
perror("recv a2");
fail++;
break;
}
}
recvbuf[numbytes] = '\0';
if (strstr(recvbuf, "a2 OK") == NULL) {
ERR("IMAP status failed: %s", recvbuf);
if (imap_command(sockfd, sendbuf, recvbuf, "a2 OK")) {
fail++;
break;
}
@ -1817,51 +1807,13 @@ void *imap_thread(void *arg)
strncpy(sendbuf, "a4 SELECT ", MAXDATASIZE);
strncat(sendbuf, mail->folder, MAXDATASIZE - strlen(sendbuf) - 1);
strncat(sendbuf, "\r\n", MAXDATASIZE - strlen(sendbuf) - 1);
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
perror("send a4");
fail++;
break;
}
timeout.tv_sec = 60; // 60 second timeout i guess
timeout.tv_usec = 0;
FD_ZERO(&fdset);
FD_SET(sockfd, &fdset);
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
if (res > 0) {
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
perror("recv a4");
fail++;
break;
}
}
recvbuf[numbytes] = '\0';
if (strstr(recvbuf, "a4 OK") == NULL) {
ERR("IMAP status failed: %s", recvbuf);
if (imap_command(sockfd, sendbuf, recvbuf, "a4 OK")) {
fail++;
break;
}
strncpy(sendbuf, "a5 IDLE\r\n", MAXDATASIZE);
if (send(sockfd, sendbuf, strlen(sendbuf), 0) == -1) {
perror("send a5");
fail++;
break;
}
timeout.tv_sec = 60; // 60 second timeout i guess
timeout.tv_usec = 0;
FD_ZERO(&fdset);
FD_SET(sockfd, &fdset);
res = select(sockfd + 1, &fdset, NULL, NULL, &timeout);
if (res > 0) {
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
perror("recv a5");
fail++;
break;
}
}
recvbuf[numbytes] = '\0';
if (strstr(recvbuf, "+ idling") == NULL) {
ERR("IMAP status failed: %s", recvbuf);
if (imap_command(sockfd, sendbuf, recvbuf, "+ idling")) {
fail++;
break;
}
@ -1870,17 +1822,17 @@ void *imap_thread(void *arg)
while (1) {
FD_ZERO(&fdset);
FD_SET(sockfd, &fdset);
FD_SET(threadfd, &fdset);
res = pselect(MAX(sockfd + 1, threadfd + 1), &fdset, NULL, NULL, NULL, &oldmask);
if (timed_thread_test(mail->p_timed_thread)) {
break;
timed_thread_exit(mail->p_timed_thread);
}
res = pselect(sockfd + 1, &fdset, NULL, NULL, NULL, &oldmask);
if (res == -1 && errno == EINTR) {
if ((res == -1 && errno == EINTR) || FD_ISSET(threadfd, &fdset)) {
timed_thread_exit(mail->p_timed_thread);
} else if (res > 0) {
if ((numbytes = recv(sockfd, recvbuf, MAXDATASIZE - 1, 0)) == -1) {
perror("recv idling");
fail++;
printf("fail\n");
break;
}
} else {
@ -1888,9 +1840,12 @@ void *imap_thread(void *arg)
}
recvbuf[numbytes] = '\0';
if (strlen(recvbuf) > 2) {
unsigned long messages, unseen;
unsigned long messages, recent;
char *buf = recvbuf;
buf = strstr(buf, "EXISTS");
while (buf && strlen(buf) > 1 && strstr(buf + 1, "EXISTS")) {
buf = strstr(buf + 1, "EXISTS");
}
if (buf) {
// back up until we reach '*'
while (buf >= recvbuf && buf[0] != '*') {
@ -1904,14 +1859,20 @@ void *imap_thread(void *arg)
}
buf = recvbuf;
buf = strstr(buf, "RECENT");
while (buf && strlen(buf) > 1 && strstr(buf + 1, "RECENT")) {
buf = strstr(buf + 1, "RECENT");
}
if (buf) {
// back up until we reach '*'
while (buf >= recvbuf && buf[0] != '*') {
buf--;
}
if (sscanf(buf, "* %lu RECENT\r\n", &unseen) == 1) {
if (sscanf(buf, "* %lu RECENT\r\n", &recent) == 1) {
/*
* if we have > 0 recent, re-check the unseen count
*/
timed_thread_lock(mail->p_timed_thread);
mail->unseen = unseen;
mail->unseen = recent;
timed_thread_unlock(mail->p_timed_thread);
}
}

View File

@ -27,6 +27,7 @@
#include <assert.h>
#include <errno.h>
#include <time.h>
#include <unistd.h>
#ifndef HAVE_CLOCK_GETTIME
#include <sys/time.h>
#endif
@ -47,6 +48,7 @@ struct _timed_thread {
void *arg; /* thread function argument */
struct timespec interval_time; /* interval_usecs as a struct timespec */
struct timespec wait_time; /* absolute future time next timed_thread_test will wait until */
int pipefd[2];
};
/* linked list of created threads */
@ -59,6 +61,11 @@ typedef struct _timed_thread_list {
static timed_thread_list *p_timed_thread_list_head = NULL;
static timed_thread_list *p_timed_thread_list_tail = NULL;
int timed_thread_readfd(timed_thread *p_timed_thread)
{
return p_timed_thread->pipefd[0];
}
static int now(struct timespec *abstime)
{
#ifndef HAVE_CLOCK_GETTIME
@ -96,6 +103,11 @@ timed_thread *timed_thread_create(void *start_routine(void *), void *arg,
return NULL;
}
/* create thread pipe (used to tell threads to die) */
if (pipe(p_timed_thread->pipefd)) {
return NULL;
}
/* init attributes, e.g. joinable thread */
pthread_attr_init(&p_timed_thread->thread_attr);
pthread_attr_setdetachstate(&p_timed_thread->thread_attr,
@ -147,6 +159,7 @@ void timed_thread_destroy(timed_thread *p_timed_thread,
pthread_mutex_lock(&p_timed_thread->runnable_mutex);
pthread_cond_signal(&p_timed_thread->runnable_cond);
pthread_mutex_unlock(&p_timed_thread->runnable_mutex);
write(p_timed_thread->pipefd[1], "die", 3);
/* join the terminating thread */
if (p_timed_thread->thread) {
@ -236,6 +249,9 @@ void timed_thread_exit(timed_thread *p_timed_thread)
{
assert(p_timed_thread != NULL);
close(p_timed_thread->pipefd[0]);
close(p_timed_thread->pipefd[1]);
pthread_exit(NULL);
}

View File

@ -63,4 +63,7 @@ int timed_thread_register(timed_thread *p_timed_thread,
/* destroy all registered timed threads */
void timed_thread_destroy_registered_threads(void);
/* returns read file descriptor for thread pipe */
int timed_thread_readfd(timed_thread *p_timed_thread);
#endif /* #ifdef _TIMED_THREAD_H_ */