Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 30 additions & 2 deletions auth/src/desktop/auth_desktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

#include "auth/src/desktop/auth_desktop.h"

#include <algorithm>
#include <cassert>
#include <cstdint>
#include <cstring>
Expand Down Expand Up @@ -92,6 +93,19 @@ void* CreatePlatformAuth(App* const app) {
AuthImpl* const auth = new AuthImpl();
auth->api_key = app->options().api_key();
auth->app_name = app->name();

// Check environment variables for emulator if set.
if (std::getenv("USE_AUTH_EMULATOR") != nullptr) {
auth->assigned_emulator_url.append(kEmulatorLocalHost);
auth->assigned_emulator_url.append(":");
if (std::getenv("AUTH_EMULATOR_PORT") == nullptr) {
auth->assigned_emulator_url.append(kEmulatorPort);
} else {
auth->assigned_emulator_url.append(std::getenv("AUTH_EMULATOR_PORT"));
}
LogInfo("Using Auth Emulator: %s", auth->assigned_emulator_url.c_str());
}
Comment thread
AustinBenoit marked this conversation as resolved.

return auth;
}

Expand Down Expand Up @@ -576,6 +590,7 @@ void Auth::UseEmulator(std::string host, uint32_t port) {
auth_impl->assigned_emulator_url.append(host);
auth_impl->assigned_emulator_url.append(":");
auth_impl->assigned_emulator_url.append(std::to_string(port));
LogInfo("Using Auth Emulator: %s", auth_impl->assigned_emulator_url.c_str());
}

void InitializeTokenRefresher(AuthData* auth_data) {
Expand Down Expand Up @@ -667,6 +682,8 @@ void IdTokenRefreshThread::Initialize(AuthData* auth_data) {
thread_ = firebase::Thread(
[](IdTokenRefreshThread* refresh_thread) {
Auth* auth = refresh_thread->auth;
ExponentialBackoff backoff;

while (!refresh_thread->is_shutting_down()) {
// Note: Make sure to always make future_impl.mutex the innermost
// lock, to prevent deadlocks!
Expand Down Expand Up @@ -700,8 +717,19 @@ void IdTokenRefreshThread::Initialize(AuthData* auth_data) {
// is completed.
future_sem.Wait();

// (We don't actually care about the results of the token request.
// The token listener will handle that.)
if (future.error() != 0) {
// Token refresh failed (e.g. network outage). Wait with
// exponential backoff to prevent tight retry loops and avoid
// overloading backend servers upon reconnect. Matches Android
// DefaultTokenRefresher (30s initial, doubling up to 16m max).
if (!refresh_thread->is_shutting_down()) {
refresh_thread->wakeup_sem_.TimedWait(backoff.NextDelayMs());
}
continue;
} else {
// Refresh succeeded! Reset backoff to minimum interval.
backoff.Reset();
}
} else {
auth->auth_data_->future_impl.mutex().Release();
refresh_thread->ref_count_mutex_.Release();
Expand Down
44 changes: 44 additions & 0 deletions auth/src/desktop/auth_desktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#ifndef FIREBASE_AUTH_SRC_DESKTOP_AUTH_DESKTOP_H_
#define FIREBASE_AUTH_SRC_DESKTOP_AUTH_DESKTOP_H_

#include <algorithm>
#include <cstdint>
#include <memory>
#include <string>
Expand Down Expand Up @@ -179,6 +180,49 @@ struct AuthImpl {
const int kMinutesPerTokenRefresh = 58;
const int kMsPerTokenRefresh =
kMinutesPerTokenRefresh * internal::kMillisecondsPerMinute;
// Exponential backoff parameters when token refresh fails (e.g. network
// outage), matching Android DefaultTokenRefresher.
const int kMinRetryBackoffMs = 30 * 1000; // 30 seconds base delay
const int kMaxRetryBackoffMs = 16 * 60 * 1000; // 16 minutes max delay

// Encapsulates deterministic exponential backoff parameters and calculation
// when token refresh fails (e.g. network outage), matching Android
// DefaultTokenRefresher (30s initial, doubling up to 16m max).
class ExponentialBackoff {
public:
explicit ExponentialBackoff(int min_delay_ms = kMinRetryBackoffMs,
int max_delay_ms = kMaxRetryBackoffMs,
double multiplier = 2.0)
: min_delay_ms_(std::max(0, min_delay_ms)),
max_delay_ms_(std::max(min_delay_ms_, max_delay_ms)),
multiplier_(std::max(1.0, multiplier)),
current_delay_ms_(min_delay_ms_) {}

// Resets the backoff delay to the initial minimum delay.
void Reset() { current_delay_ms_ = min_delay_ms_; }

// Returns the delay to wait for the current retry attempt, and advances
// the internal delay for subsequent attempts up to max_delay_ms.
int NextDelayMs() {
int delay = current_delay_ms_;
if (static_cast<double>(current_delay_ms_) * multiplier_ >=
static_cast<double>(max_delay_ms_)) {
current_delay_ms_ = max_delay_ms_;
} else {
current_delay_ms_ = static_cast<int>(current_delay_ms_ * multiplier_);
}
return delay;
}

// Returns the current delay without advancing it.
int current_delay_ms() const { return current_delay_ms_; }

private:
int min_delay_ms_;
int max_delay_ms_;
double multiplier_;
int current_delay_ms_;
};

void InitializeUserDataPersist(AuthData* auth_data);
void DestroyUserDataPersist(AuthData* auth_data);
Expand Down
35 changes: 2 additions & 33 deletions auth/src/desktop/rpcs/auth_request.cc
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,6 @@ const char* kHeaderFirebaseLocale = "X-Firebase-Locale";
AuthRequest::AuthRequest(::firebase::App& app, const char* schema,
bool deliver_heartbeat)
: RequestJson(schema), app(app) {
CheckEnvEmulator();

if (deliver_heartbeat) {
std::shared_ptr<heartbeat::HeartbeatController> heartbeat_controller =
app.GetHeartbeatController();
Expand Down Expand Up @@ -76,52 +74,23 @@ AuthRequest::AuthRequest(::firebase::App& app, const char* schema,
}

std::string AuthRequest::GetUrl() {
std::string emulator_url;
Auth* auth_ptr = Auth::GetAuth(&app);
std::string assigned_emulator_url =
static_cast<AuthImpl*>(auth_ptr->auth_data_->auth_impl)
->assigned_emulator_url;
if (assigned_emulator_url.empty()) {
emulator_url = env_emulator_url;
} else {
emulator_url = assigned_emulator_url;
}

if (emulator_url.empty()) {
if (assigned_emulator_url.empty()) {
std::string url(kHttps);
url += kServerURL;
return url;
} else {
std::string url(kHttp);
url += emulator_url;
url += assigned_emulator_url;
url += "/";
url += kServerURL;
return url;
}
}

void AuthRequest::CheckEnvEmulator() {
if (!env_emulator_url.empty()) {
LogInfo("Environment Emulator Url already set: %s",
env_emulator_url.c_str());
return;
}

// Use emulator as long as this env variable is set, regardless its value.
if (std::getenv("USE_AUTH_EMULATOR") == nullptr) {
LogInfo("USE_AUTH_EMULATOR not set.");
return;
}
env_emulator_url.append(kEmulatorLocalHost);
env_emulator_url.append(":");
// Use AUTH_EMULATOR_PORT if it is set to non empty string,
// otherwise use the default port.
if (std::getenv("AUTH_EMULATOR_PORT") == nullptr) {
env_emulator_url.append(kEmulatorPort);
} else {
env_emulator_url.append(std::getenv("AUTH_EMULATOR_PORT"));
}
}

} // namespace auth
} // namespace firebase
2 changes: 0 additions & 2 deletions auth/src/desktop/rpcs/auth_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,6 @@ class AuthRequest
std::string GetUrl();

private:
void CheckEnvEmulator();
std::string env_emulator_url;
::firebase::App& app;
};

Expand Down
4 changes: 4 additions & 0 deletions release_build_files/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,10 @@ workflow use only during the development of your app, not for publicly shipping
code.

## Release Notes
### Upcoming
- Changes
- Auth (Desktop): Fixed log spam and high CPU utilization when offline by moving `USE_AUTH_EMULATOR` environment variable check to initialization and eliminating per-request logging (#1629).

### 13.11.0
- Changes
- General (Android): Update to Firebase Android BoM version 34.17.0.
Expand Down
Loading