Skip to content

Commit

Permalink
Merge pull request #1847 from ably/fix/1177-RSH8b-RSH3g2a
Browse files Browse the repository at this point in the history
Proper RSH8b and RSH3g2a behavior.
  • Loading branch information
maratal authored Jan 18, 2024
2 parents eda7a54 + f5b7359 commit 4ff1202
Show file tree
Hide file tree
Showing 10 changed files with 231 additions and 47 deletions.
3 changes: 3 additions & 0 deletions Source/ARTAuth.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#import "ARTPushActivationState.h"
#import "ARTFormEncode.h"
#import "ARTInternalLog.h"
#import "ARTLocalDeviceStorage.h"
#import "ARTLocalDevice+Private.h"

@implementation ARTAuth {
ARTQueuedDealloc *_dealloc;
Expand Down Expand Up @@ -824,6 +826,7 @@ - (void)setLocalDeviceClientId_nosync:(NSString *)clientId {
return;
}
[_rest.device_nosync setClientId:clientId];
[_rest.storage setObject:clientId forKey:ARTClientIdKey];
[_rest.push getActivationMachine:^(ARTPushActivationStateMachine *stateMachine) {
if (![stateMachine.current_nosync isKindOfClass:[ARTPushActivationStateNotActivated class]]) {
[stateMachine sendEvent:[[ARTPushActivationEventGotPushDeviceDetails alloc] init]];
Expand Down
72 changes: 54 additions & 18 deletions Source/ARTLocalDevice.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
NSString *const ARTDeviceSecretKey = @"ARTDeviceSecret";
NSString *const ARTDeviceIdentityTokenKey = @"ARTDeviceIdentityToken";
NSString *const ARTAPNSDeviceTokenKey = @"ARTAPNSDeviceToken";
NSString *const ARTClientIdKey = @"ARTClientId";

NSString *const ARTAPNSDeviceDefaultTokenType = @"default";
NSString *const ARTAPNSDeviceLocationTokenType = @"location";
Expand All @@ -46,17 +47,24 @@ @interface ARTLocalDevice ()

@implementation ARTLocalDevice

- (instancetype)initWithClientId:(NSString *)clientId storage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger {
- (instancetype)initWithStorage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger {
if (self = [super init]) {
self.clientId = clientId;
self.storage = storage;
_logger = logger;
}
return self;
}

+ (ARTLocalDevice *)load:(NSString *)clientId storage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger {
ARTLocalDevice *device = [[ARTLocalDevice alloc] initWithClientId:clientId storage:storage logger:logger];
- (void)generateAndPersistPairOfDeviceIdAndSecret {
self.id = [self.class generateId];
self.secret = [self.class generateSecret];

[_storage setObject:self.id forKey:ARTDeviceIdKey];
[_storage setSecret:self.secret forDevice:self.id];
}

+ (instancetype)deviceWithStorage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger {
ARTLocalDevice *device = [[ARTLocalDevice alloc] initWithStorage:storage logger:logger];
device.platform = ARTDevicePlatform;
#if TARGET_OS_IOS
switch ([[UIDevice currentDevice] userInterfaceIdiom]) {
Expand All @@ -75,21 +83,25 @@ + (ARTLocalDevice *)load:(NSString *)clientId storage:(id<ARTDeviceStorage>)stor
NSString *deviceId = [storage objectForKey:ARTDeviceIdKey];
NSString *deviceSecret = deviceId == nil ? nil : [storage secretForDevice:deviceId];

if (deviceId == nil || deviceSecret == nil) { // generate both at the same time
deviceId = [self generateId];
deviceSecret = [self generateSecret];
[storage setObject:deviceId forKey:ARTDeviceIdKey];
[storage setSecret:deviceSecret forDevice:deviceId];
if (deviceId == nil || deviceSecret == nil) {
[device generateAndPersistPairOfDeviceIdAndSecret]; // Should be removed later once spec issue #180 resolved.
}
else {
device.id = deviceId;
device.secret = deviceSecret;
}

device.id = deviceId;
device.secret = deviceSecret;

id identityTokenDetailsInfo = [storage objectForKey:ARTDeviceIdentityTokenKey];
ARTDeviceIdentityTokenDetails *identityTokenDetails = [ARTDeviceIdentityTokenDetails unarchive:identityTokenDetailsInfo withLogger:logger];
device->_identityTokenDetails = identityTokenDetails;

NSString *clientId = [storage objectForKey:ARTClientIdKey];
if (clientId == nil && identityTokenDetails.clientId != nil) {
clientId = identityTokenDetails.clientId; // Older versions of the SDK did not persist clientId, so as a fallback when loading data persisted by these versions we use the clientId of the stored identity token
[storage setObject:clientId forKey:ARTClientIdKey];
}
device.clientId = clientId;

NSArray *supportedTokenTypes = @[
ARTAPNSDeviceDefaultTokenType,
ARTAPNSDeviceLocationTokenType
Expand All @@ -102,6 +114,34 @@ + (ARTLocalDevice *)load:(NSString *)clientId storage:(id<ARTDeviceStorage>)stor
return device;
}

- (void)setupDetailsWithClientId:(NSString *)clientId {
NSString *deviceId = self.id;
NSString *deviceSecret = self.secret;

if (deviceId == nil || deviceSecret == nil) {
[self generateAndPersistPairOfDeviceIdAndSecret];
}

self.clientId = clientId;
[_storage setObject:clientId forKey:ARTClientIdKey];
}

- (void)resetDetails {
// Should be replaced later to resetting device's id/secret once spec issue #180 resolved.
[self generateAndPersistPairOfDeviceIdAndSecret];

self.clientId = nil;
[_storage setObject:nil forKey:ARTClientIdKey];
[self setAndPersistIdentityTokenDetails:nil];
NSArray *supportedTokenTypes = @[
ARTAPNSDeviceDefaultTokenType,
ARTAPNSDeviceLocationTokenType
];
for (NSString *tokenType in supportedTokenTypes) {
[self setAndPersistAPNSDeviceToken:nil tokenType:tokenType];
}
}

+ (NSString *)generateId {
return [NSUUID new].UUIDString;
}
Expand Down Expand Up @@ -146,16 +186,12 @@ - (void)setAndPersistIdentityTokenDetails:(ARTDeviceIdentityTokenDetails *)token
_identityTokenDetails = tokenDetails;
if (self.clientId == nil) {
self.clientId = tokenDetails.clientId;
[self.storage setObject:tokenDetails.clientId forKey:ARTClientIdKey];
}
}

- (BOOL)isRegistered {
return _identityTokenDetails != nil;
}

- (void)clearIdentityTokenDetailsAndClientId {
[self setAndPersistIdentityTokenDetails:nil];
self.clientId = nil;
}

@end
6 changes: 3 additions & 3 deletions Source/ARTPushActivationState.m
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,8 @@ @implementation ARTPushActivationPersistentState
} else if ([local apnsDeviceToken]) {
[machine sendEvent:[ARTPushActivationEventGotPushDeviceDetails new]];
}
[machine.rest setupLocalDevice_nosync];
[machine registerForAPNS];
#endif

return [ARTPushActivationStateWaitingForPushDeviceDetails newWithMachine:machine logger:logger];
Expand All @@ -116,7 +118,6 @@ - (ARTPushActivationState *)transition:(ARTPushActivationEvent *)event {
return self;
}
else if ([event isKindOfClass:[ARTPushActivationEventCalledActivate class]]) {
[self.machine registerForAPNS];
return validateAndSync(self.machine, event, self.logger);
}
return nil;
Expand Down Expand Up @@ -274,8 +275,7 @@ - (ARTPushActivationState *)transition:(ARTPushActivationEvent *)event {
}
else if ([event isKindOfClass:[ARTPushActivationEventDeregistered class]]) {
#if TARGET_OS_IOS
ARTLocalDevice *local = self.machine.rest.device_nosync;
[local clearIdentityTokenDetailsAndClientId];
[self.machine.rest resetLocalDevice_nosync];
#endif
[self.machine callDeactivatedCallback:nil];
return [ARTPushActivationStateNotActivated newWithMachine:self.machine logger:self.logger];
Expand Down
24 changes: 19 additions & 5 deletions Source/ARTRest.m
Original file line number Diff line number Diff line change
Expand Up @@ -744,10 +744,9 @@ - (ARTLocalDevice *)device {
}

- (ARTLocalDevice *)device_nosync {
NSString *clientId = self.auth.clientId_nosync;
__block ARTLocalDevice *ret;
dispatch_sync(ARTRestInternal.deviceAccessQueue, ^{
ret = [self deviceWithClientId_onlyCallOnDeviceAccessQueue:clientId];
dispatch_sync([ARTRestInternal deviceAccessQueue], ^{
ret = [self sharedDevice_onlyCallOnDeviceAccessQueue];
});
return ret;
}
Expand All @@ -765,7 +764,7 @@ + (dispatch_queue_t)deviceAccessQueue {

static BOOL sharedDeviceNeedsLoading_onlyAccessOnDeviceAccessQueue = YES;

- (ARTLocalDevice *)deviceWithClientId_onlyCallOnDeviceAccessQueue:(NSString *)clientId {
- (ARTLocalDevice *)sharedDevice_onlyCallOnDeviceAccessQueue {
// The device is shared in a static variable because it's a reflection
// of what's persisted. Having a device instance per ARTRest instance
// could leave some instances in a stale state, if, through another
Expand All @@ -776,12 +775,27 @@ - (ARTLocalDevice *)deviceWithClientId_onlyCallOnDeviceAccessQueue:(NSString *)c

static id device;
if (sharedDeviceNeedsLoading_onlyAccessOnDeviceAccessQueue) {
device = [ARTLocalDevice load:clientId storage:self.storage logger:self.logger];
device = [ARTLocalDevice deviceWithStorage:self.storage logger:self.logger];
sharedDeviceNeedsLoading_onlyAccessOnDeviceAccessQueue = NO;
}
return device;
}

- (void)setupLocalDevice_nosync {
ARTLocalDevice *device = [self device_nosync];
NSString *clientId = self.auth.clientId_nosync;
dispatch_sync([ARTRestInternal deviceAccessQueue], ^{
[device setupDetailsWithClientId:clientId];
});
}

- (void)resetLocalDevice_nosync {
ARTLocalDevice *device = [self device_nosync];
dispatch_sync([ARTRestInternal deviceAccessQueue], ^{
[device resetDetails];
});
}

- (void)resetDeviceSingleton {
dispatch_sync([ARTRestInternal deviceAccessQueue], ^{
sharedDeviceNeedsLoading_onlyAccessOnDeviceAccessQueue = YES;
Expand Down
8 changes: 5 additions & 3 deletions Source/PrivateHeaders/Ably/ARTLocalDevice+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ extern NSString *const ARTDeviceIdKey;
extern NSString *const ARTDeviceSecretKey;
extern NSString *const ARTDeviceIdentityTokenKey;
extern NSString *const ARTAPNSDeviceTokenKey;
extern NSString *const ARTClientIdKey;

extern NSString *const ARTAPNSDeviceDefaultTokenType;
extern NSString *const ARTAPNSDeviceLocationTokenType;
Expand All @@ -19,18 +20,19 @@ NSString* ARTAPNSDeviceTokenKeyOfType(NSString * _Nullable tokenType);

@property (nonatomic) id<ARTDeviceStorage> storage;

+ (ARTLocalDevice *)load:(NSString *)clientId storage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger;
+ (instancetype)deviceWithStorage:(id<ARTDeviceStorage>)storage logger:(nullable ARTInternalLog *)logger;
- (nullable NSString *)apnsDeviceToken;
- (void)setAndPersistAPNSDeviceToken:(nullable NSString *)deviceToken tokenType:(NSString *)tokenType;
- (void)setAndPersistAPNSDeviceToken:(nullable NSString *)deviceToken;
- (void)setAndPersistIdentityTokenDetails:(nullable ARTDeviceIdentityTokenDetails *)tokenDetails;
- (BOOL)isRegistered;
- (void)clearIdentityTokenDetailsAndClientId;
- (void)resetDetails;
- (void)setupDetailsWithClientId:(nullable NSString *)clientId;

+ (NSString *)generateId;
+ (NSString *)generateSecret;

+ (NSString *)apnsDeviceTokenOfType:(nullable NSString *)tokenType fromStorage:(id<ARTDeviceStorage>)storage;
+ (nullable NSString *)apnsDeviceTokenOfType:(nullable NSString *)tokenType fromStorage:(id<ARTDeviceStorage>)storage;

@end

Expand Down
3 changes: 3 additions & 0 deletions Source/PrivateHeaders/Ably/ARTRest+Private.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ NS_ASSUME_NONNULL_BEGIN
- (nullable NSObject<ARTCancellable> *)internetIsUp:(void (^)(BOOL isUp))cb;

#if TARGET_OS_IOS
- (void)setupLocalDevice_nosync;
- (void)resetLocalDevice_nosync;

// This is only intended to be called from test code.
- (void)resetDeviceSingleton;

Expand Down
Loading

0 comments on commit 4ff1202

Please sign in to comment.