jbenet / ios-ntp

SNTP implementation for iOS
http://code.google.com/p/ios-ntp/
MIT License
370 stars 112 forks source link

Possible to use NetAssociation with systemUptime? #41

Closed warpling closed 8 years ago

warpling commented 8 years ago

Like many others I use NTP to detect time manipulation, and to retrieve accurate time. This is often difficult to deal with when a user leaves the app, changes the time, comes back, and NTP takes a bit of time to figure out the new offset.

Would it be possible to get an NTP response with an offset, and associate it with the current systemUptime? Once established, seconds since uptime would becoming a meaningful measure of time and we wouldn't need further NTP checks or to use the system time.

Does this seem plausible? cc @gavineadie

gavineadie commented 8 years ago

I don't know about the second paragraph, but the "bit of time" problem in your first para can be overcome creating just one association and letting it run .. you get an answer "immediately." You don't care about milliSec accuracy so there is no need to use multiple time servers, multiple data points and statistics to get to a refined offset.

I wrote this up with skeleton code in the README.

warpling commented 8 years ago

I used the code in the README as a starting point for what I'm working on :)

The delay seemingly still exists between the NetAssociation receiving UIApplicationWillEnterForegroundNotification and receiving a new report?

Say that the system time is 13:00 and the NetAssociation has received a report. When the NetAssociation is asked for the timeOffset it'll correctly report 0. Now if we leave the app, and change the time to 14:00, come back to the app, and immediately query for the timeOffset it'll be 0, until the next report comes in and the timeOffset is corrected, at which point it'll correctly report ~3600.

warpling commented 8 years ago

It seems to be working! I made a timeTotem object that gets created the first time my NetAssociation gets a report:

@interface TimeTotem : NSObject {
    NSTimeInterval systemUptime;
    NSDate *time;
}

- (instancetype) initWithSystemUptime:(NSTimeInterval)systemUptime networkTime:(NSDate*)networkTime;
- (NSDate*) totemTime;

@end

@implementation TimeTotem

- (instancetype) initWithSystemUptime:(NSTimeInterval)aSystemUptime networkTime:(NSDate*)networkTime {
    self = [super init];
    if (self) {
        systemUptime = aSystemUptime;
        time = networkTime;
    }
    return self;
}

- (NSDate*) totemTime {
    NSTimeInterval interval = [[NSProcessInfo processInfo] systemUptime] - systemUptime;
    return [time dateByAddingTimeInterval:interval];
}

@end

The totemTime continues to be trustworthy even when the network goes down or is slow!

gavineadie commented 8 years ago

Seems fair. I'd probably just throw the NetAssociation away when going into background and get a new one when reappearing in the foreground (assuming time checks are not required while in the background).