@@ -131,6 +131,15 @@ PersistentConnection::~PersistentConnection() {
131
131
// executing code which requires reference to this.
132
132
safe_this_.ClearReference ();
133
133
134
+ // Clear OnCompletion function for pending token future
135
+ {
136
+ MutexLock future_lock (pending_token_future_mutex_);
137
+ if (pending_token_future_.status () != kFutureStatusInvalid ) {
138
+ pending_token_future_.OnCompletion (nullptr , nullptr );
139
+ pending_token_future_ = Future<std::string>();
140
+ }
141
+ }
142
+
134
143
// Destroy the client so that no more event will be triggered from this point.
135
144
realtime_.reset (nullptr );
136
145
}
@@ -487,21 +496,75 @@ void PersistentConnection::TryScheduleReconnect() {
487
496
}
488
497
489
498
assert (connection_state_ == kDisconnected );
490
-
499
+ bool force_refresh = force_auth_refresh_;
500
+ force_auth_refresh_ = false ;
491
501
LogDebug (" %s Scheduling connection attempt" , log_id_.c_str ());
492
502
493
- // TODO(chkuang): Implement Retry
494
- Reconnect ();
503
+ // TODO(chkuang): Implement Exponential Backoff Retry
504
+ connection_state_ = kGettingToken ;
505
+ LogDebug (" %s Trying to fetch auth token" , log_id_.c_str ());
506
+
507
+ // Get Token Asynchronously to make sure the token is not expired.
508
+ Future<std::string> future;
509
+ bool succeeded = app_->function_registry ()->CallFunction (
510
+ ::firebase::internal::FnAuthGetTokenAsync, app_, &force_refresh, &future);
511
+ if (succeeded && future.status () != kFutureStatusInvalid ) {
512
+ // Set pending future
513
+ MutexLock future_lock (pending_token_future_mutex_);
514
+ pending_token_future_ = future;
515
+ future.OnCompletion (OnTokenFutureComplete, this );
516
+ } else {
517
+ // Auth is not available now. Start the connection anyway.
518
+ OpenNetworkConnection ();
519
+ }
495
520
}
496
521
497
- void PersistentConnection::Reconnect () {
498
- assert (connection_state_ == kDisconnected );
499
- connection_state_ = kGettingToken ;
522
+ void PersistentConnection::OnTokenFutureComplete (
523
+ const Future<std::string>& result_data, void * user_data) {
524
+ assert (user_data);
525
+ PersistentConnection* connection =
526
+ static_cast <PersistentConnection*>(user_data);
527
+ ThisRefLock lock (&connection->safe_this_ );
528
+ // If the connection is destroyed or being destroyed, do nothing.
529
+ if (!lock.GetReference ()) return ;
530
+
531
+ {
532
+ // Clear pending future
533
+ MutexLock future_lock (connection->pending_token_future_mutex_ );
534
+ connection->pending_token_future_ = Future<std::string>();
535
+ }
500
536
501
- LogDebug (" %s Trying to fetch auth token" , log_id_.c_str ());
502
- GetAuthToken (&auth_token_);
537
+ connection->scheduler_ ->Schedule (
538
+ new callback::CallbackValue2<ThisRef, Future<std::string>>(
539
+ connection->safe_this_ , result_data,
540
+ [](ThisRef ref, Future<std::string> future) {
541
+ ThisRefLock lock (&ref);
542
+ if (lock.GetReference ()) {
543
+ lock.GetReference ()->HandleTokenFuture (future);
544
+ }
545
+ }));
546
+ }
503
547
504
- OpenNetworkConnection ();
548
+ void PersistentConnection::HandleTokenFuture (Future<std::string> future) {
549
+ if (future.error () == 0 ) {
550
+ if (connection_state_ == kGettingToken ) {
551
+ LogDebug (" %s Successfully fetched token, opening connection" ,
552
+ log_id_.c_str ());
553
+ auth_token_ = *future.result ();
554
+ OpenNetworkConnection ();
555
+ } else {
556
+ assert (connection_state_ == kDisconnected );
557
+ LogDebug (
558
+ " %s Not opening connection after token refresh, because "
559
+ " connection was set to disconnected" ,
560
+ log_id_.c_str ());
561
+ }
562
+ } else {
563
+ connection_state_ = kDisconnected ;
564
+ LogDebug (" %s Error fetching token: %s" , log_id_.c_str (),
565
+ future.error_message ());
566
+ TryScheduleReconnect ();
567
+ }
505
568
}
506
569
507
570
void PersistentConnection::OpenNetworkConnection () {
@@ -945,6 +1008,7 @@ void PersistentConnection::HandleAuthTokenResponse(const Variant& message,
945
1008
}
946
1009
} else {
947
1010
auth_token_.clear ();
1011
+ force_auth_refresh_ = true ;
948
1012
event_handler_->OnAuthStatus (false );
949
1013
950
1014
std::string reason = GetStringValue (message, kServerResponseData );
0 commit comments