Skip to content

[iOS] Add force relay connection on iOS#4928

Merged
doromaraujo merged 7 commits intomainfrom
feature/force-relay-connection-ios
Dec 12, 2025
Merged

[iOS] Add force relay connection on iOS#4928
doromaraujo merged 7 commits intomainfrom
feature/force-relay-connection-ios

Conversation

@doromaraujo
Copy link
Copy Markdown
Contributor

@doromaraujo doromaraujo commented Dec 9, 2025

Describe your changes

iOS apps run in a sandbox context the same way android does, and setting environment variables from iOS's side won't work for the internal SDK peer configuration when it reads NB_FORCE_RELAY to decide whether to add an ICE listener to the handshaker.

This PR makes it so the iOS app can pass a list of environment variables in order to be exported by the time the go client starts running, the same way Android does.

Issue ticket number and link

Stack

Checklist

  • Is it a bug fix
  • Is a typo/documentation fix
  • Is a feature enhancement
  • It is a refactor
  • Created tests that fail without the change (if possible)

By submitting this pull request, you confirm that you have read and agree to the terms of the Contributor License Agreement.

Documentation

Select exactly one:

  • I added/updated documentation for this change
  • Documentation is not needed for this change (explain why)

Docs PR URL (required if "docs added" is checked)

Paste the PR link from https://github.com/netbirdio/docs here:

Summary by CodeRabbit

  • New Features
    • iOS SDK: added a public environment-list API so callers can provide configurable environment variables when starting the client (e.g., relay and other client settings).
  • Chores
    • Marked multiple SDK sources as iOS-specific to ensure platform-targeted builds and bindings.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 9, 2025

Walkthrough

Adds an iOS-only EnvList type and plumbing to export its entries to OS environment variables; updates Client.Run to accept an EnvList and apply it before running. Several SDK files were restricted to the iOS build tag.

Changes

Cohort / File(s) Summary
Run signature & env export
client/ios/NetBirdSDK/client.go
Changed func (c *Client) Run(fd int32, interfaceName string) errorfunc (c *Client) Run(fd int32, interfaceName string, envList *EnvList) error; added exportEnvList(envList) call and new helper to iterate items and set OS env vars (uses os.Setenv) with logging
New EnvList binding (iOS)
client/ios/NetBirdSDK/env_list.go
Added iOS-only EnvList type (in-memory map), NewEnvList(), Put(), Get(), AllItems() and GetEnvKeyNBForceRelay() for gomobile exposure
Add ios build tag
client/ios/NetBirdSDK/gomobile.go, client/ios/NetBirdSDK/logger.go, client/ios/NetBirdSDK/login.go, client/ios/NetBirdSDK/peer_notifier.go, client/ios/NetBirdSDK/preferences.go, client/ios/NetBirdSDK/preferences_test.go, client/ios/NetBirdSDK/routes.go
Added //go:build ios build constraint to make these files iOS-only; no functional changes to logic or exported APIs

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Inspect client.go Run call sites for required updates to callers and gomobile bindings.
  • Review exportEnvList for nil handling, error/logging semantics, and OS env side effects on iOS.
  • Verify EnvList methods are safe for gomobile (exportable types, pointer usage) and thread-safety if concurrent use is expected.
  • Confirm build-tag changes don't exclude files from non-iOS builds unexpectedly.

Suggested reviewers

  • mlsmaycon

Poem

🐰

I hop through code, with tiny feet,
I tuck new vars where run-times meet,
A Bundle here, a whisper there,
iOS Run breathes a fresher air! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 60.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title '[iOS] Add force relay connection on iOS' accurately describes the main change—enabling force relay support on iOS by passing environment variables through the Go client, mirroring Android functionality.
Description check ✅ Passed The pull request description includes the required sections with substantive content: a detailed explanation of the problem (iOS sandbox restrictions), the solution (passing environment variables to the Go client), and appropriate checklist selections. No critical information is missing.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/force-relay-connection-ios

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
client/ios/NetBirdSDK/env_list.go (2)

8-10: Consider thread safety if concurrent access is expected.

The EnvList struct uses an unprotected map[string]string. If the iOS app might call Put, Get, or AllItems concurrently from multiple threads before passing the list to Run, data races could occur. Given the expected usage pattern (create, populate, pass to Run), this is likely safe, but consider adding a sync.RWMutex if concurrent access is a possibility.

</review_comment_end>


27-29: Return a defensive copy of the map to prevent accidental external modification.

AllItems() is part of the gomobile-bound public API and currently returns the internal map directly. While the current internal usage in exportEnvList only reads values, returning the underlying map could allow external callers to accidentally (or intentionally) modify the internal state. Consider making a copy to follow defensive programming patterns consistent with other similar methods in the codebase.

 func (el *EnvList) AllItems() map[string]string {
-	return el.data
+	result := make(map[string]string, len(el.data))
+	for k, v := range el.data {
+		result[k] = v
+	}
+	return result
 }
client/ios/NetBirdSDK/client.go (1)

439-453: Function logic is correct; consider simplifying logging.

The exportEnvList function properly handles nil input and iterates through environment variables with appropriate error handling. The verbose logging (current value, setting action, success confirmation) is helpful for debugging but could be simplified to reduce log volume.

Optional simplification to reduce log verbosity:

 func exportEnvList(list *EnvList) {
 	if list == nil {
 		return
 	}
 	for k, v := range list.AllItems() {
-		log.Debugf("Env variable %s's value is currently: %s", k, os.Getenv(k))
 		log.Debugf("Setting env variable %s: %s", k, v)
-
 		if err := os.Setenv(k, v); err != nil {
 			log.Errorf("could not set env variable %s: %v", k, err)
-		} else {
-			log.Debugf("Env variable %s was set successfully", k)
 		}
 	}
 }

</review_comment_end>

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f4f825 and f2b2b49.

📒 Files selected for processing (2)
  • client/ios/NetBirdSDK/client.go (3 hunks)
  • client/ios/NetBirdSDK/env_list.go (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: Management / Unit (amd64, postgres)
  • GitHub Check: Management / Unit (amd64, mysql)
  • GitHub Check: Management / Unit (amd64, sqlite)
  • GitHub Check: Relay / Unit (amd64, -race)
  • GitHub Check: Relay / Unit (386)
  • GitHub Check: Client / Unit (386)
  • GitHub Check: Client / Unit (amd64)
  • GitHub Check: Client (Docker) / Unit
  • GitHub Check: Client / Unit
  • GitHub Check: JS / Lint
  • GitHub Check: iOS / Build
  • GitHub Check: Client / Unit
  • GitHub Check: Android / Build
  • GitHub Check: Client / Unit
  • GitHub Check: release
  • GitHub Check: release_ui_darwin
  • GitHub Check: Windows
  • GitHub Check: Linux
  • GitHub Check: Darwin
🔇 Additional comments (2)
client/ios/NetBirdSDK/env_list.go (1)

31-34: LGTM! Clean re-export for iOS bindings.

Exporting peer.EnvKeyNBForceRelay through GetEnvKeyNBForceRelay() provides the iOS app with type-safe access to the environment variable key.

</review_comment_end>

client/ios/NetBirdSDK/client.go (1)

94-95: LGTM! Clean integration of environment variable support.

The Run method now accepts an envList parameter and exports it immediately before configuration loading, ensuring environment variables are available when needed. The nil handling is delegated to exportEnvList, which handles it gracefully.

</review_comment_end>

@sonarqubecloud
Copy link
Copy Markdown

sonarqubecloud Bot commented Dec 9, 2025

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f2b2b49 and 5bfdaab.

📒 Files selected for processing (8)
  • client/ios/NetBirdSDK/client.go (3 hunks)
  • client/ios/NetBirdSDK/gomobile.go (1 hunks)
  • client/ios/NetBirdSDK/logger.go (1 hunks)
  • client/ios/NetBirdSDK/login.go (1 hunks)
  • client/ios/NetBirdSDK/peer_notifier.go (1 hunks)
  • client/ios/NetBirdSDK/preferences.go (1 hunks)
  • client/ios/NetBirdSDK/preferences_test.go (1 hunks)
  • client/ios/NetBirdSDK/routes.go (1 hunks)
✅ Files skipped from review due to trivial changes (3)
  • client/ios/NetBirdSDK/login.go
  • client/ios/NetBirdSDK/preferences.go
  • client/ios/NetBirdSDK/preferences_test.go
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (19)
  • GitHub Check: Relay / Unit (386)
  • GitHub Check: Relay / Unit (amd64, -race)
  • GitHub Check: Management / Unit (amd64, postgres)
  • GitHub Check: Client / Unit (386)
  • GitHub Check: Management / Unit (amd64, mysql)
  • GitHub Check: Client (Docker) / Unit
  • GitHub Check: Management / Unit (amd64, sqlite)
  • GitHub Check: Client / Unit (amd64)
  • GitHub Check: Client / Unit
  • GitHub Check: Linux
  • GitHub Check: Darwin
  • GitHub Check: iOS / Build
  • GitHub Check: Android / Build
  • GitHub Check: Client / Unit
  • GitHub Check: JS / Lint
  • GitHub Check: Windows
  • GitHub Check: Client / Unit
  • GitHub Check: release_ui_darwin
  • GitHub Check: release
🔇 Additional comments (7)
client/ios/NetBirdSDK/logger.go (1)

1-2: LGTM! iOS build constraint added correctly.

The build tag appropriately restricts this file to iOS compilation without changing any behavior.

client/ios/NetBirdSDK/gomobile.go (1)

1-2: LGTM! iOS build constraint added correctly.

The build tag appropriately restricts this gomobile binding file to iOS compilation.

client/ios/NetBirdSDK/peer_notifier.go (1)

1-2: LGTM! iOS build constraint added correctly.

The build tag appropriately restricts this file to iOS compilation without affecting the existing peer notification types and methods.

client/ios/NetBirdSDK/routes.go (1)

1-2: LGTM! iOS build constraint added correctly.

The build tag appropriately restricts this file to iOS compilation without affecting the existing route selection types and methods.

client/ios/NetBirdSDK/client.go (3)

1-2: LGTM! iOS build constraint added correctly.

The build tag appropriately restricts this file to iOS compilation, aligning with the PR's platform-specific changes.


9-9: LGTM! Import added for environment variable support.

The os import is necessary for the new os.Setenv functionality in exportEnvList.


96-97: LGTM! Run signature updated to accept environment variables.

The addition of the envList *EnvList parameter enables iOS apps to pass environment variables before the Go client starts, which aligns with the PR objective. The call to exportEnvList at the start of Run ensures variables are set before configuration loading and authentication.

Comment on lines +441 to +455
func exportEnvList(list *EnvList) {
if list == nil {
return
}
for k, v := range list.AllItems() {
log.Debugf("Env variable %s's value is currently: %s", k, os.Getenv(k))
log.Debugf("Setting env variable %s: %s", k, v)

if err := os.Setenv(k, v); err != nil {
log.Errorf("could not set env variable %s: %v", k, err)
} else {
log.Debugf("Env variable %s was set successfully", k)
}
}
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid logging environment variable values to prevent credential leakage.

Lines 446-447 log both the current and new values of environment variables. Environment variables in this context (e.g., NB_FORCE_RELAY) may contain sensitive information such as authentication tokens, API keys, or relay credentials. Debug logs can be captured by logging frameworks, persisted to disk, or forwarded to external systems, creating a security risk.

Apply this diff to log only the key names without exposing values:

 func exportEnvList(list *EnvList) {
 	if list == nil {
 		return
 	}
 	for k, v := range list.AllItems() {
-		log.Debugf("Env variable %s's value is currently: %s", k, os.Getenv(k))
-		log.Debugf("Setting env variable %s: %s", k, v)
+		log.Debugf("Setting env variable: %s", k)
 
 		if err := os.Setenv(k, v); err != nil {
 			log.Errorf("could not set env variable %s: %v", k, err)
 		} else {
 			log.Debugf("Env variable %s was set successfully", k)
 		}
 	}
 }
🤖 Prompt for AI Agents
In client/ios/NetBirdSDK/client.go around lines 441 to 455, the function
exportEnvList logs environment variable values (current and new), which can leak
credentials; change the logging to only mention the environment variable names
and whether the set succeeded or failed, removing any prints of os.Getenv(k) or
v; on error include the variable name and the error only, and on success log
that the variable was set without including its value.

@doromaraujo doromaraujo merged commit 08f31fb into main Dec 12, 2025
53 of 59 checks passed
@doromaraujo doromaraujo deleted the feature/force-relay-connection-ios branch December 12, 2025 17:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants