Permalink
Browse files

Reworking the IDLE implementation

  • Loading branch information...
1 parent 483a932 commit 4dd4759fb52f5089be41d14e2dc4dc06fdb9a849 @mronge mronge committed Oct 31, 2012
Showing with 92 additions and 35 deletions.
  1. +6 −12 Source/CTCoreAccount.h
  2. +76 −23 Source/CTCoreAccount.m
  3. +10 −0 Source/MailCoreTypes.h
View
@@ -31,6 +31,7 @@
#import <Foundation/Foundation.h>
#import <libetpan/libetpan.h>
+#import "MailCoreTypes.h"
/**
CTCoreAccount is the base class with which you establish a connection to the
@@ -45,6 +46,8 @@
BOOL connected;
NSError *lastError;
NSString *pathDelimiter;
+
+ int idlePipe[2];
}
/**
If an error occurred (nil or return of NO) call this method to get the error
@@ -101,21 +104,12 @@
/**
Sends the idle command to the server.
- @return Return YES on success, NO on error. Call method lastError to get error if one occurred
*/
-- (BOOL)idle;
+- (CTIdleResult)idle;
+- (void)cancelIdle;
-/**
- Blocks the connection until data arrives.
- @return Returns nil on error
-*/
-- (NSString *)read;
+@property BOOL idling;
-/**
- Sends the done command to the server.
- @return Return YES on success, NO on error. Call method lastError to get error if one occurred
-*/
-- (BOOL)done;
/* Intended for advanced use only */
- (mailimap *)session;
View
@@ -34,6 +34,10 @@
#import "MailCoreTypes.h"
#import "MailCoreUtilities.h"
+#include <unistd.h>
+
+#define IDLE_TIMEOUT (28 * 60)
+
@interface CTCoreAccount ()
@end
@@ -107,34 +111,83 @@ - (BOOL)connectToServer:(NSString *)server port:(int)port
return YES;
}
-- (BOOL)idle {
- int err = mailimap_idle([self session]);
-
- if (err != MAILIMAP_NO_ERROR) {
- self.lastError = MailCoreCreateErrorFromIMAPCode(err);
- return NO;
+- (CTIdleResult)idle {
+ NSAssert(!self.idling, @"Can't call idle when we are already idling!");
+
+ CTIdleResult result = CTIdleError;
+ int r = 0;
+
+ self.idling = YES;
+ pipe(idlePipe);
+
+ self.session->imap_selection_info->sel_exists = 0;
+ r = mailimap_idle(self.session);
+ if (r != MAILIMAP_NO_ERROR) {
+ self.lastError = MailCoreCreateErrorFromIMAPCode(r);
+ result = CTIdleError;
}
- return YES;
-}
-
-- (NSString*)read {
- char * buf = mailimap_read_line([self session]);
-
- if (buf == NULL) {
- return nil;
+
+ if (r == MAILIMAP_NO_ERROR && self.session->imap_selection_info->sel_exists == 0) {
+ int fd;
+ int maxfd;
+ fd_set readfds;
+ struct timeval delay;
+
+ fd = mailimap_idle_get_fd(self.session);
+
+ FD_ZERO(&readfds);
+ FD_SET(fd, &readfds);
+ FD_SET(idlePipe[0], &readfds);
+ maxfd = fd;
+ if (idlePipe[0] > maxfd) {
+ maxfd = idlePipe[0];
+ }
+ delay.tv_sec = IDLE_TIMEOUT;
+ delay.tv_usec = 0;
+
+ r = select(maxfd + 1, &readfds, NULL, NULL, &delay);
+ if (r == 0) {
+ result = CTIdleTimeout;
+ } else if (r == -1) {
+ // select error condition, just ignore this
+ } else {
+ if (FD_ISSET(fd, &readfds)) {
+ // The server sent something down
+ result = CTIdleNewData;
+ } else if (FD_ISSET(idlePipe[0], &readfds)) {
+ // the idle was explicitly cancelled
+ char ch;
+ read(idlePipe[0], &ch, 1);
+ result = CTIdleCancelled;
+ }
+ }
+ } else if (r == MAILIMAP_NO_ERROR) {
+ result = CTIdleNewData;
}
-
- return [NSString stringWithCString:buf encoding:NSUTF8StringEncoding];
+
+ r = mailimap_idle_done(self.session);
+ if (r != MAILIMAP_NO_ERROR) {
+ self.lastError = MailCoreCreateErrorFromIMAPCode(r);
+ result = CTIdleError;
+ }
+
+ close(idlePipe[1]);
+ close(idlePipe[0]);
+ idlePipe[1] = -1;
+ idlePipe[0] = -1;
+ self.idling = NO;
+
+ return result;
}
-- (BOOL)done {
- int err = mailimap_idle_done([self session]);
-
- if (err != MAILIMAP_NO_ERROR) {
- self.lastError = MailCoreCreateErrorFromIMAPCode(err);
- return NO;
+- (void)cancelIdle {
+ if (self.idling) {
+ int r;
+ char c;
+
+ c = 0;
+ r = write(idlePipe[1], &c, 1);
}
- return YES;
}
- (void)disconnect {
View
@@ -43,6 +43,16 @@ typedef enum
CTFetchAttrEnvelope = 1 << 1,
} CTFetchAttributes;
+/** Constants for IDLE **/
+
+typedef enum
+{
+ CTIdleNewData = 0,
+ CTIdleTimeout,
+ CTIdleCancelled,
+ CTIdleError,
+} CTIdleResult;
+
/** Connection Constants **/
/* when the connection is plain text */

0 comments on commit 4dd4759

Please sign in to comment.