-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
RSA4c #519
RSA4c #519
Changes from 8 commits
e536b3d
8d98976
ac032fe
3f17d0f
2c704bc
6c4391b
ea0e5e9
0c86eb8
6939c90
b6d6f92
efa57ab
8c81364
7021e1f
3462531
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -33,6 +33,7 @@ | |
#import "ARTRealtimeTransport.h" | ||
#import "ARTFallback.h" | ||
#import "ARTAuthDetails.h" | ||
#import "ARTGCD.h" | ||
|
||
@interface ARTConnectionStateChange () | ||
|
||
|
@@ -153,7 +154,20 @@ - (NSString *)getClientId { | |
} | ||
|
||
- (NSString *)description { | ||
return [NSString stringWithFormat:@"Realtime: %@", self.clientId]; | ||
NSString *info; | ||
if (self.options.token) { | ||
info = [NSString stringWithFormat:@"token: %@", self.options.token]; | ||
} | ||
else if (self.options.authUrl) { | ||
info = [NSString stringWithFormat:@"authUrl: %@", self.options.authUrl]; | ||
} | ||
else if (self.options.authCallback) { | ||
info = [NSString stringWithFormat:@"authCallback: %@", self.options.authCallback]; | ||
} | ||
else { | ||
info = [NSString stringWithFormat:@"key: %@", self.options.key]; | ||
} | ||
return [NSString stringWithFormat:@"%@ - \n\t %@;", [super description], info]; | ||
} | ||
|
||
- (ARTAuth *)getAuth { | ||
|
@@ -268,11 +282,12 @@ - (void)transition:(ARTRealtimeConnectionState)state withErrorInfo:(ARTErrorInfo | |
|
||
- (void)transitionSideEffects:(ARTConnectionStateChange *)stateChange { | ||
ARTStatus *status = nil; | ||
__weak __typeof(self) weakSelf = self; | ||
|
||
switch (stateChange.current) { | ||
case ARTRealtimeConnecting: { | ||
[self unlessStateChangesBefore:[ARTDefault realtimeRequestTimeout] do:^{ | ||
[self transition:ARTRealtimeDisconnected withErrorInfo:[ARTErrorInfo createWithCode:0 status:ARTStateConnectionFailed message:@"timed out"]]; | ||
[weakSelf onConnectionTimeOut]; | ||
}]; | ||
|
||
if (!_reachability) { | ||
|
@@ -295,19 +310,19 @@ - (void)transitionSideEffects:(ARTConnectionStateChange *)stateChange { | |
if (self.connection.state != ARTRealtimeFailed && self.connection.state != ARTRealtimeClosed && self.connection.state != ARTRealtimeDisconnected) { | ||
[_reachability listenForHost:[_transport host] callback:^(BOOL reachable) { | ||
if (reachable) { | ||
switch (_connection.state) { | ||
switch ([[weakSelf connection] state]) { | ||
case ARTRealtimeDisconnected: | ||
case ARTRealtimeSuspended: | ||
[self transition:ARTRealtimeConnecting]; | ||
[weakSelf transition:ARTRealtimeConnecting]; | ||
default: | ||
break; | ||
} | ||
} else { | ||
switch (_connection.state) { | ||
switch ([[weakSelf connection] state]) { | ||
case ARTRealtimeConnecting: | ||
case ARTRealtimeConnected: { | ||
ARTErrorInfo *unreachable = [ARTErrorInfo createWithCode:-1003 message:@"unreachable host"]; | ||
[self transition:ARTRealtimeDisconnected withErrorInfo:unreachable]; | ||
[weakSelf transition:ARTRealtimeDisconnected withErrorInfo:unreachable]; | ||
break; | ||
} | ||
default: | ||
|
@@ -322,7 +337,7 @@ - (void)transitionSideEffects:(ARTConnectionStateChange *)stateChange { | |
case ARTRealtimeClosing: { | ||
[_reachability off]; | ||
[self unlessStateChangesBefore:[ARTDefault realtimeRequestTimeout] do:^{ | ||
[self transition:ARTRealtimeClosed]; | ||
[weakSelf transition:ARTRealtimeClosed]; | ||
}]; | ||
[self.transport sendClose]; | ||
break; | ||
|
@@ -365,7 +380,7 @@ - (void)transitionSideEffects:(ARTConnectionStateChange *)stateChange { | |
[stateChange setRetryIn:self.options.disconnectedRetryTimeout]; | ||
|
||
[self unlessStateChangesBefore:stateChange.retryIn do:^{ | ||
[self transition:ARTRealtimeConnecting]; | ||
[weakSelf transition:ARTRealtimeConnecting]; | ||
}]; | ||
|
||
break; | ||
|
@@ -376,7 +391,7 @@ - (void)transitionSideEffects:(ARTConnectionStateChange *)stateChange { | |
_transport = nil; | ||
[stateChange setRetryIn:self.options.suspendedRetryTimeout]; | ||
[self unlessStateChangesBefore:stateChange.retryIn do:^{ | ||
[self transition:ARTRealtimeConnecting]; | ||
[weakSelf transition:ARTRealtimeConnecting]; | ||
}]; | ||
[_authorizationEmitter emit:[NSNumber numberWithInt:ARTAuthorizationFailed] with:[ARTErrorInfo createWithCode:ARTStateAuthorizationFailed message:@"Connection has been suspended"]]; | ||
break; | ||
|
@@ -433,6 +448,24 @@ - (void)transitionSideEffects:(ARTConnectionStateChange *)stateChange { | |
[self.connection emit:stateChange.current with:stateChange]; | ||
} | ||
|
||
- (void)onConnectionTimeOut { | ||
NSInteger errorCode; | ||
if (self.auth.authorizing && (self.options.authUrl || self.options.authCallback)) { | ||
errorCode = ARTCodeErrorAuthConfiguredProviderFailure; | ||
} | ||
else { | ||
errorCode = ARTCodeErrorConnectionTimedOut; | ||
} | ||
switch (self.connection.state) { | ||
case ARTRealtimeConnected: | ||
[self transition:ARTRealtimeConnected withErrorInfo:[ARTErrorInfo createWithCode:errorCode status:ARTStateConnectionFailed message:@"timed out"]]; | ||
break; | ||
default: | ||
[self transition:ARTRealtimeDisconnected withErrorInfo:[ARTErrorInfo createWithCode:errorCode status:ARTStateConnectionFailed message:@"timed out"]]; | ||
break; | ||
} | ||
} | ||
|
||
- (void)unlessStateChangesBefore:(NSTimeInterval)deadline do:(void(^)())callback { | ||
// Defer until next event loop execution so that any event emitted in the current | ||
// one doesn't cancel the timeout. | ||
|
@@ -536,13 +569,26 @@ - (void)onClosed { | |
} | ||
} | ||
|
||
- (void)onAuth { | ||
[self.logger info:@"R:%p server has requested an authorise", self]; | ||
switch (self.connection.state) { | ||
case ARTRealtimeConnecting: | ||
case ARTRealtimeConnected: | ||
[self transportReconnectWithRenewedToken]; | ||
break; | ||
default: | ||
NSAssert(false, @"Invalid Realtime state: expected Connecting or Connected"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would reserve those assertions for bugs on the library. If e. g. the server sends an AUTH while the connection is closing, that would be a bug in the server, and we probably should treat those more gracefully than crashing, e. g. log and ignore. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done b6d6f92. |
||
break; | ||
} | ||
} | ||
|
||
- (void)onError:(ARTProtocolMessage *)message { | ||
// TODO work out which states this can be received in | ||
if (message.channel) { | ||
[self onChannelMessage:message]; | ||
} else { | ||
ARTErrorInfo *error = message.error; | ||
if ([self shouldRenewToken:&error]) { | ||
[self.transport close]; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Then it's closed again at 621? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't precise the problem that was occurring if the |
||
[self transportReconnectWithRenewedToken]; | ||
return; | ||
} | ||
|
@@ -567,12 +613,43 @@ - (void)transportReconnectWithHost:(NSString *)host { | |
[self.transport connect]; | ||
} | ||
|
||
- (void)transportReconnectWithRenewedToken { | ||
_renewingToken = true; | ||
- (void)transportReconnectWithTokenDetails:(ARTTokenDetails *)tokenDetails error:(NSError *)error { | ||
if (error && (self.options.authUrl || self.options.authCallback)) { | ||
[self.connection setErrorReason:[ARTErrorInfo createWithCode:ARTCodeErrorAuthConfiguredProviderFailure message:error.localizedDescription]]; | ||
return; | ||
} | ||
[_transport close]; | ||
_transport = [[_transportClass alloc] initWithRest:self.rest options:self.options resumeKey:_transport.resumeKey connectionSerial:_transport.connectionSerial]; | ||
_transport.delegate = self; | ||
[_transport connectForcingNewToken:true]; | ||
[_transport connectWithToken:tokenDetails.token error:error]; | ||
} | ||
|
||
- (void)transportReconnectWithRenewedToken { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unless I'm missing something, all this logic will only apply when There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @ricardopereira have you made the change on this? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mattheworiordan No, working on it right now. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done efa57ab. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That one broke some tests, unfortunately... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 😔 Yes, I'm on it. Thanks There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed 3462531. |
||
self.auth.delegate = nil; | ||
@try { | ||
_renewingToken = true; | ||
__weak __typeof(self) weakSelf = self; | ||
dispatch_block_t work = artDispatchScheduled([ARTDefault realtimeRequestTimeout], ^{ | ||
[weakSelf onConnectionTimeOut]; | ||
}); | ||
[self.auth authorize:nil options:self.options callback:^(ARTTokenDetails *tokenDetails, NSError *error) { | ||
// Cancel scheduled work | ||
artDispatchCancel(work); | ||
// It's still valid? | ||
switch ([[weakSelf connection] state]) { | ||
case ARTRealtimeClosing: | ||
case ARTRealtimeClosed: | ||
return; | ||
default: | ||
break; | ||
} | ||
[[weakSelf getLogger] debug:__FILE__ line:__LINE__ message:@"R:%p WS:%p authorised: %@ error: %@", weakSelf, [weakSelf getTransport], tokenDetails, error]; | ||
[weakSelf transportReconnectWithTokenDetails:tokenDetails error:error]; | ||
}]; | ||
} | ||
@finally { | ||
self.auth.delegate = self; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also no idea why this. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, your comment above is relevant about this case. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done efa57ab. |
||
} | ||
} | ||
|
||
- (void)onAck:(ARTProtocolMessage *)message { | ||
|
@@ -584,7 +661,9 @@ - (void)onNack:(ARTProtocolMessage *)message { | |
} | ||
|
||
- (void)onChannelMessage:(ARTProtocolMessage *)message { | ||
// TODO work out which states this can be received in / error info? | ||
if (message.channel == nil) { | ||
return; | ||
} | ||
ARTRealtimeChannel *channel = [self.channels get:message.channel]; | ||
[channel onChannelMessage:message]; | ||
} | ||
|
@@ -886,6 +965,9 @@ - (void)realtimeTransport:(id)transport didReceiveMessage:(ARTProtocolMessage *) | |
case ARTProtocolMessageClosed: | ||
[self onClosed]; | ||
break; | ||
case ARTProtocolMessageAuth: | ||
[self onAuth]; | ||
break; | ||
default: | ||
[self onChannelMessage:message]; | ||
break; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This kind of things could really use an explanatory comment. I have no idea why this change. I mean, I assume you don't want to increase the reference count in all those callback blocks but I'm not sure if there's some subtle reason for that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you're right, I don't want to increase the ref count on those blocks because, for example, the
unlessStateChangesBefore
is setting a timer and if theARTRealtime
instance is released before that timer, then it could create a retain cycle and then we have a leak. That could also bring some instability in the test suite because we are creating a lot ofARTRealtime
instances. I will add a comment about it. Thanks.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done 6939c90.