First pass at 'push' support for Ping and Sync

This commit is contained in:
Ludovic Marcotte
2014-02-04 11:19:33 -05:00
parent 7fe48a1555
commit 2ff3b5ef5f
3 changed files with 96 additions and 19 deletions

View File

@@ -104,6 +104,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SOGoActiveSyncConstants.h"
#include "SOGoMailObject+ActiveSync.h"
#include <unistd.h>
@implementation SOGoActiveSyncDispatcher (Sync)
//
@@ -635,6 +637,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
- (void) processSyncCollection: (id <DOMElement>) 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: @"<Collection>"];
@@ -840,30 +847,67 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
{
id <DOMElement> 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: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
[s appendString: @"<Sync xmlns=\"AirSync:\"><Collections>"];
[output appendString: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[output appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
[output appendString: @"<Sync xmlns=\"AirSync:\">"];
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: @"<Limit>%d</Limit>", 300];
//[output appendFormat: @"<Status>%d</Status>", 14];
//[output appendString: @"</Sync>"];
//d = [[output dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
//[theResponse setContent: d];
//return;
}
[s appendString: @"</Collections></Sync>"];
[output appendString: @"<Collections>"];
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: @"</Collections></Sync>"];
d = [[s dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
d = [[output dataUsingEncoding: NSUTF8StringEncoding] xml2wbxml];
[theResponse setContent: d];
}

View File

@@ -112,6 +112,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "SOGoActiveSyncConstants.h"
#include "SOGoMailObject+ActiveSync.h"
#include <unistd.h>
@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: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
[s appendFormat: @"<GetItemEstimate xmlns=\"GetItemEstimate:\"><Response><Status>%d</Status><Collection>", status];
[s appendString: @"<Class>Email</Class>"];
[s appendFormat: @"<CollectionId>%@</CollectionId>", collectionId];
[s appendFormat: @"<Estimate>%d</Estimate>", [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 <DOMElement>) 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: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>"];
[s appendString: @"<!DOCTYPE ActiveSync PUBLIC \"-//MICROSOFT//DTD ActiveSync//EN\" \"http://www.microsoft.com/\">"];
[s appendString: @"<Ping xmlns=\"Ping:\">"];
[s appendFormat: @"<Status>1</Status>"];
[s appendFormat: @"<Status>%d</Status>", status];
if (status == 5)
{
[s appendFormat: @"<HeartbeatInterval>%d</HeartbeatInterval>", heartbeatInterval];
}
[s appendString: @"</Ping>"];
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)
{

View File

@@ -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
<Proxy http://127.0.0.1:20000/SOGo>
## adjust the following to your configuration