diff --git a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m index e93fc3325..a2f2b3a44 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher+Sync.m +++ b/ActiveSync/SOGoActiveSyncDispatcher+Sync.m @@ -104,6 +104,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "SOGoActiveSyncConstants.h" #include "SOGoMailObject+ActiveSync.h" +#include + @implementation SOGoActiveSyncDispatcher (Sync) // @@ -635,6 +637,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // - (void) processSyncCollection: (id ) theDocumentElement inBuffer: (NSMutableString *) theBuffer + changeDetected: (BOOL *) changeDetected { NSString *collectionId, *realCollectionId, *syncKey, *davCollectionTag, *bodyPreferenceType; SOGoMicrosoftActiveSyncFolderType folderType; @@ -666,6 +669,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. { davCollectionTag = @"-1"; first_sync = YES; + *changeDetected = YES; } // We check our sync preferences and we stash them @@ -716,7 +720,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // If we got any changes or if we have applied any commands // let's regenerate our SyncKey based on the collection tag. if ([changeBuffer length] || [commandsBuffer length]) - davCollectionTag = [collection davCollectionTag]; + { + davCollectionTag = [collection davCollectionTag]; + *changeDetected = YES; + } // Generate the response buffer [theBuffer appendString: @""]; @@ -840,30 +847,67 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. { id aCollection; NSArray *allCollections; - NSMutableString *s; + NSMutableString *output, *s; NSData *d; - int i; + int i, j, heartbeatInterval; + BOOL changeDetected; // We initialize our output buffer - s = [NSMutableString string]; + output = [NSMutableString string]; - [s appendString: @""]; - [s appendString: @""]; - [s appendString: @""]; + [output appendString: @""]; + [output appendString: @""]; + [output appendString: @""]; - allCollections = (id)[theDocumentElement getElementsByTagName: @"Collection"]; + heartbeatInterval = [[[(id)[theDocumentElement getElementsByTagName: @"HeartbeatInterval"] lastObject] textValue] intValue]; - for (i = 0; i < [allCollections count]; i++) + // We check to see if our heartbeat interval falls into the supported ranges. + if (heartbeatInterval > 300 || heartbeatInterval < 1) { - aCollection = [allCollections objectAtIndex: i]; + // Interval is too long, inform the client. + heartbeatInterval = 300; - [self processSyncCollection: aCollection inBuffer: s]; + //[output appendFormat: @"%d", 300]; + //[output appendFormat: @"%d", 14]; + //[output appendString: @""]; + //d = [[output dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml]; + //[theResponse setContent: d]; + //return; } - [s appendString: @""]; + [output appendString: @""]; + + allCollections = (id)[theDocumentElement getElementsByTagName: @"Collection"]; + + // We enter our loop detection change + for (i = 0; i < (heartbeatInterval/60); i++) + { + s = [NSMutableString string]; + + for (j = 0; j < [allCollections count]; j++) + { + aCollection = [allCollections objectAtIndex: j]; + + [self processSyncCollection: aCollection inBuffer: s changeDetected: &changeDetected]; + } + + if (changeDetected) + { + NSLog(@"Change detected, we push the content."); + [output appendString: s]; + break; + } + else + { + NSLog(@"Sleeping 60 seconds while detecting changes..."); + sleep(60); + } + } + + [output appendString: @""]; - d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml]; + d = [[output dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml]; [theResponse setContent: d]; } diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m index a87c9ddb6..bb14a17fc 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher.m +++ b/ActiveSync/SOGoActiveSyncDispatcher.m @@ -112,6 +112,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "SOGoActiveSyncConstants.h" #include "SOGoMailObject+ActiveSync.h" +#include + @implementation SOGoActiveSyncDispatcher - (void) _setFolderSyncKey: (NSString *) theSyncKey @@ -599,7 +601,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. @"deleted"]; sinceDateQualifier = [EOQualifier qualifierWithQualifierFormat: @"(DATE >= %@)", filter]; - qualifier = [[EOAndQualifier alloc] initWithQualifiers: notDeletedQualifier, sinceDateQualifier, nil]; @@ -614,7 +615,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [s appendString: @""]; [s appendFormat: @"%d", status]; - [s appendString: @"Email"]; [s appendFormat: @"%@", collectionId]; [s appendFormat: @"%d", [uids count]]; @@ -623,7 +623,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml]; [theResponse setContent: d]; - } // @@ -900,7 +899,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. } // -// We ignore everything for now +// Ping requests make a little sense because the request +// doesn't contain the SyncKey on the client. So we can't +// really know if something has changed on the server. What we +// do for now is simply return Status=5 with the HeartbeatInterval +// set at 60 seconds or we wait 60 seconds before responding with +// Status=1 // - (void) processPing: (id ) theDocumentElement inResponse: (WOResponse *) theResponse @@ -908,11 +912,37 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NSMutableString *s; NSData *d; + int heartbeatInterval, status; + + if (theDocumentElement) + heartbeatInterval = [[[(id)[theDocumentElement getElementsByTagName: @"HeartbeatInterval"] lastObject] textValue] intValue]; + else + heartbeatInterval = 60; + + if (heartbeatInterval > 60 || heartbeatInterval == 0) + { + heartbeatInterval = 60; + status = 5; + } + else + { + NSLog(@"Got Ping request with valid interval - sleeping for 60 seconds."); + sleep(60); + status = 1; + } + + // We generate our response s = [NSMutableString string]; [s appendString: @""]; [s appendString: @""]; [s appendString: @""]; - [s appendFormat: @"1"]; + [s appendFormat: @"%d", status]; + + if (status == 5) + { + [s appendFormat: @"%d", heartbeatInterval]; + } + [s appendString: @""]; d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml]; @@ -1432,6 +1462,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. [context setObject: deviceId forKey: @"DeviceId"]; d = [[theRequest content] wbxml2xml]; + documentElement = nil; if (!d) { diff --git a/Apache/SOGo.conf b/Apache/SOGo.conf index 9748c1051..c5f2ffeee 100644 --- a/Apache/SOGo.conf +++ b/Apache/SOGo.conf @@ -44,8 +44,10 @@ ProxyPass /SOGo http://127.0.0.1:20000/SOGo retry=0 # # Enable to use Microsoft Active Sync support +# Note that you MUST have many sogod workers to use Active Sync. +# See the SOGo Installation and Configuration guide for more details. # -#ProxyPass /Microsoft-Server-ActiveSync http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync retry=0 +#ProxyPass /Microsoft-Server-ActiveSync http://127.0.0.1:20000/SOGo/Microsoft-Server-ActiveSync retry=60 connectiontimeout=5 timeout=360 ## adjust the following to your configuration