Skip to content

Commit

Permalink
Reworked IDLE implementation and moved it to CTCoreFolder
Browse files Browse the repository at this point in the history
  • Loading branch information
mronge committed Nov 2, 2012
1 parent e67020c commit e0396cb
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 96 deletions.
12 changes: 0 additions & 12 deletions Source/CTCoreAccount.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,6 @@
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
Expand Down Expand Up @@ -101,18 +99,8 @@
*/
- (void)disconnect;


/**
Sends the idle command to the server.
*/
- (CTIdleResult)idle;
- (void)cancelIdle;

- (NSSet *)capabilities;

@property BOOL idling;


/* Intended for advanced use only */
- (mailimap *)session;
- (struct mailstorage *)storageStruct;
Expand Down
83 changes: 0 additions & 83 deletions Source/CTCoreAccount.m
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,6 @@
#import "MailCoreTypes.h"
#import "MailCoreUtilities.h"

#include <unistd.h>

#define IDLE_TIMEOUT (28 * 60)

@interface CTCoreAccount ()
@end

Expand Down Expand Up @@ -111,85 +107,6 @@ - (BOOL)connectToServer:(NSString *)server port:(int)port
return YES;
}

- (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;
}

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;
}

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;
}

- (void)cancelIdle {
if (self.idling) {
int r;
char c;

c = 0;
r = write(idlePipe[1], &c, 1);
}
}

- (NSSet *)capabilities {
NSMutableSet *capabilitiesSet = [NSMutableSet set];

Expand Down
11 changes: 11 additions & 0 deletions Source/CTCoreFolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@
NSString *myPath;
BOOL connected;
NSError *lastError;

BOOL idling;
int idlePipe[2];
}
/**
If an error occurred (nil or return of NO) call this method to get the error
Expand Down Expand Up @@ -153,6 +156,14 @@
*/
- (BOOL)setPath:(NSString *)path;

/**
Sends the idle command to the server.
*/
- (CTIdleResult)idleWithTimeout:(NSUInteger)timeout;
- (void)cancelIdle;
@property (atomic) BOOL idling;


/**
If the folder doesn't exist on the server this method will create it. Make sure the pathname
has been set first.
Expand Down
88 changes: 87 additions & 1 deletion Source/CTCoreFolder.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
#import "MailCoreTypes.h"
#import "MailCoreUtilities.h"

#include <unistd.h>


//int imap_fetch_result_to_envelop_list(clist * fetch_result, struct mailmessage_list * env_list);
//
int uid_list_to_env_list(clist * fetch_result, struct mailmessage_list ** result,
Expand All @@ -47,7 +50,7 @@ @interface CTCoreFolder ()
@end

@implementation CTCoreFolder
@synthesize lastError, parentAccount=myAccount;
@synthesize lastError, parentAccount=myAccount, idling;

- (id)initWithPath:(NSString *)path inAccount:(CTCoreAccount *)account; {
struct mailstorage *storage = (struct mailstorage *)[account storageStruct];
Expand Down Expand Up @@ -130,6 +133,89 @@ - (BOOL)setPath:(NSString *)path; {
return success;
}

- (CTIdleResult)idleWithTimeout:(NSUInteger)timeout {
NSAssert(!self.idling, @"Can't call idle when we are already idling!");

BOOL success = [self connect];
if (!success) {
return CTIdleError;
}

CTIdleResult result = CTIdleError;
int r = 0;

self.idling = YES;
pipe(idlePipe);

self.imapSession->imap_selection_info->sel_exists = 0;
r = mailimap_idle(self.imapSession);
if (r != MAILIMAP_NO_ERROR) {
self.lastError = MailCoreCreateErrorFromIMAPCode(r);
result = CTIdleError;
}

if (r == MAILIMAP_NO_ERROR && self.imapSession->imap_selection_info->sel_exists == 0) {
int fd;
int maxfd;
fd_set readfds;
struct timeval delay;

fd = mailimap_idle_get_fd(self.imapSession);

FD_ZERO(&readfds);
FD_SET(fd, &readfds);
FD_SET(idlePipe[0], &readfds);
maxfd = fd;
if (idlePipe[0] > maxfd) {
maxfd = idlePipe[0];
}
delay.tv_sec = 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;
}

r = mailimap_idle_done(self.imapSession);
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;
}

- (void)cancelIdle {
if (self.idling) {
int r;
char c;

c = 0;
r = write(idlePipe[1], &c, 1);
}
}

- (BOOL)create {
int err;
Expand Down

0 comments on commit e0396cb

Please sign in to comment.