Permalink
Browse files

Bug fix for XMPPAutoPing on iOS - dispatch_time doesn't work the same…

… way on ARM as it does on x86
  • Loading branch information...
1 parent ae1d5dd commit a4ee2b20381eb44f218f39823c35a6d911b72be2 @robbiehanson committed Sep 1, 2011
Showing with 32 additions and 21 deletions.
  1. +4 −3 Extensions/XEP-0199/XMPPAutoPing.h
  2. +28 −18 Extensions/XEP-0199/XMPPAutoPing.m
@@ -22,7 +22,7 @@
XMPPJID *targetJID;
NSString *targetJIDStr;
- dispatch_time_t lastReceiveTime;
+ NSTimeInterval lastReceiveTime;
dispatch_source_t pingIntervalTimer;
BOOL awaitingPingResponse;
@@ -70,9 +70,10 @@
@property (readwrite, retain) XMPPJID *targetJID;
/**
- * The last time data was received from the target.
+ * Corresponds to the last time data was received from the target.
+ * The NSTimeInterval value comes from [NSDate timeIntervalSinceReferenceDate]
**/
-@property (readonly) dispatch_time_t lastReceiveTime;
+@property (readonly) NSTimeInterval lastReceiveTime;
@end
@@ -6,7 +6,7 @@
// Log levels: off, error, warn, info, verbose
// Log flags: trace
#if DEBUG
- static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN; // | XMPP_LOG_FLAG_TRACE;
+ static const int xmppLogLevel = XMPP_LOG_LEVEL_VERBOSE | XMPP_LOG_FLAG_TRACE;
#else
static const int xmppLogLevel = XMPP_LOG_LEVEL_WARN;
#endif
@@ -33,7 +33,7 @@ - (id)initWithDispatchQueue:(dispatch_queue_t)queue
pingInterval = 60;
pingTimeout = 10;
- lastReceiveTime = DISPATCH_TIME_FOREVER;
+ lastReceiveTime = 0;
xmppPing = [[XMPPPing alloc] initWithDispatchQueue:queue];
xmppPing.respondsToQueries = NO;
@@ -62,7 +62,7 @@ - (void)deactivate
[self stopPingIntervalTimer];
- lastReceiveTime = DISPATCH_TIME_FOREVER;
+ lastReceiveTime = 0;
awaitingPingResponse = NO;
[xmppPing deactivate];
@@ -213,15 +213,15 @@ - (void)setTargetJID:(XMPPJID *)jid
dispatch_async(moduleQueue, block);
}
-- (dispatch_time_t)lastReceiveTime
+- (NSTimeInterval)lastReceiveTime
{
if (dispatch_get_current_queue() == moduleQueue)
{
return lastReceiveTime;
}
else
{
- __block dispatch_time_t result;
+ __block NSTimeInterval result;
dispatch_sync(moduleQueue, ^{
result = lastReceiveTime;
@@ -240,18 +240,18 @@ - (void)handlePingIntervalTimerFire
BOOL sendPing = NO;
- if (lastReceiveTime == DISPATCH_TIME_FOREVER)
+ if (lastReceiveTime == 0)
{
sendPing = YES;
}
else
{
- dispatch_time_t now = dispatch_time(DISPATCH_TIME_NOW, 0);
- NSTimeInterval elapsed = ((double)(now - lastReceiveTime) / (double)NSEC_PER_SEC);
+ NSTimeInterval now = [NSDate timeIntervalSinceReferenceDate];
+ NSTimeInterval elapsed = (now - lastReceiveTime);
XMPPLogTrace2(@"%@: %@ - elapsed(%f)", [self class], THIS_METHOD, elapsed);
- sendPing = (elapsed >= pingInterval);
+ sendPing = ((elapsed < 0) || (elapsed >= pingInterval));
}
if (sendPing)
@@ -274,14 +274,24 @@ - (void)updatePingIntervalTimer
NSAssert(pingIntervalTimer != NULL, @"Broken logic (1)");
NSAssert(pingInterval > 0, @"Broken logic (2)");
+ // The timer fires every (pingInterval / 4) seconds.
+ // Upon firing it checks when data was last received from the target,
+ // and sends a ping if the elapsed time has exceeded the pingInterval.
+ // Thus the effective resolution of the timer is based on the configured pingInterval.
uint64_t interval = ((pingInterval / 4.0) * NSEC_PER_SEC);
- dispatch_time_t tt;
- if (lastReceiveTime != DISPATCH_TIME_FOREVER)
- tt = dispatch_time(lastReceiveTime, interval);
+ // The timer's first fire should occur 'interval' after lastReceiveTime.
+ // If there is no lastReceiveTime, then the timer's first fire should occur 'interval' after now.
+
+ NSTimeInterval diff;
+ if (lastReceiveTime == 0)
+ diff = 0.0;
else
- tt = dispatch_time(DISPATCH_TIME_NOW, interval);
+ diff = lastReceiveTime - [NSDate timeIntervalSinceReferenceDate];;
+
+ dispatch_time_t bt = dispatch_time(DISPATCH_TIME_NOW, (diff * NSEC_PER_SEC));
+ dispatch_time_t tt = dispatch_time(bt, interval);
dispatch_source_set_timer(pingIntervalTimer, tt, interval, 0);
}
@@ -357,7 +367,7 @@ - (void)xmppPing:(XMPPPing *)sender didNotReceivePong:(NSString *)pingID dueToTi
- (void)xmppStreamDidAuthenticate:(XMPPStream *)sender
{
- lastReceiveTime = dispatch_time(DISPATCH_TIME_NOW, 0);
+ lastReceiveTime = [NSDate timeIntervalSinceReferenceDate];
awaitingPingResponse = NO;
[self startPingIntervalTimer];
@@ -367,7 +377,7 @@ - (BOOL)xmppStream:(XMPPStream *)sender didReceiveIQ:(XMPPIQ *)iq
{
if (targetJID == nil || [targetJIDStr isEqualToString:[iq fromStr]])
{
- lastReceiveTime = dispatch_time(DISPATCH_TIME_NOW, 0);
+ lastReceiveTime = [NSDate timeIntervalSinceReferenceDate];
}
return NO;
@@ -377,23 +387,23 @@ - (void)xmppStream:(XMPPStream *)sender didReceiveMessage:(XMPPMessage *)message
{
if (targetJID == nil || [targetJIDStr isEqualToString:[message fromStr]])
{
- lastReceiveTime = dispatch_time(DISPATCH_TIME_NOW, 0);
+ lastReceiveTime = [NSDate timeIntervalSinceReferenceDate];
}
}
- (void)xmppStream:(XMPPStream *)sender didReceivePresence:(XMPPPresence *)presence
{
if (targetJID == nil || [targetJIDStr isEqualToString:[presence fromStr]])
{
- lastReceiveTime = dispatch_time(DISPATCH_TIME_NOW, 0);
+ lastReceiveTime = [NSDate timeIntervalSinceReferenceDate];
}
}
- (void)xmppStreamDidDisconnect:(XMPPStream *)sender withError:(NSError *)error
{
[self stopPingIntervalTimer];
- lastReceiveTime = DISPATCH_TIME_FOREVER;
+ lastReceiveTime = 0;
awaitingPingResponse = NO;
}

0 comments on commit a4ee2b2

Please sign in to comment.