20 Commits

Author SHA1 Message Date
evgeniyChepelev 0327624b30 Multi-profiles (#80)
* fix layout on ipad

* Create multi profiles

* multi-profile server config, connection cache, and auth fixes

 Split ProfilesView into ProfilesListView, AddProfileSheet, ProfileBadge, AddProfileViewModel
- Add server URL + setup key fields to Add Profile screen
- Store per-profile connection data (ip/fqdn/managementURL) as typed model in ProfileConnectionCache
- Show cached connection info immediately on profile switch; empty if no prior data
- Fix profile deletion persistence via tombstone in profiles.json
- Fix logout to remove both netbird.cfg and state.json (cfg holds auth tokens)
- Preserve managementURL in UI after logout via cache fallback
- Guard polling from overwriting new profile's data during disconnect/reconnect cycle

* fix(multi-profile): reinitialize VPN adapter on profile switch and show current server URL

* Update project.pbxproj

* fix(multi-profile): prevent default server overwrite on logout/re-login

* Update PacketTunnelProvider.swift

* fix(multi-profile): address code review findings

- Normalize only scheme and host to lowercase when saving management
  server URL; previously the full URL was lowercased which could corrupt
  case-sensitive paths on self-hosted servers
- Move switchConnectionInfo(to:) inside the do-block so the connection
  UI is only updated after a successful profile switch
- Add ProfileConnectionCache.remove(for:) and clearConnectionData(for:)
  to prevent stale ip/fqdn/managementURL from persisting after a profile
  is deleted or logged out; call them from removeProfile and logoutProfile
- Use ASWebAuthenticationSession.Callback.customScheme on iOS 17.4+,
  falling back to the deprecated callbackURLScheme initializer on older
  versions; add a comment explaining why "http" is used and that a
  proper fix requires custom-scheme support in the SDK
- Guard presentationAnchor against a missing key window with
  assertionFailure in debug builds instead of silently returning an
  empty UIWindow
2026-04-22 10:06:51 +02:00
evgeniyChepelev 52f9e4e371 Fix on demand & auth pop-up (#85)
Fixes an issue with On-Demand (Always On) VPN where users could not re-authenticate after session (peer) expiration.
2026-04-21 13:22:14 +02:00
evgeniyChepelev 315283822c iOS home screen widget (#78)
* Add Home Screen widget with VPN toggle and refactor app activation logic

- Add NetBirdWidgetExtension target with small/medium widget sizes
- Support direct connect/disconnect from widget via interactive buttons (iOS 17+)
- Detect missing VPN config or login-required state and open app via deep link
- Poll for stable VPN state after toggle to prevent loader getting stuck
- Add widget shared state keys to GlobalConstants and sync status from MainViewModel
- Fix false "authentication required" alert on app resume after widget disconnect
- Deduplicate app activation logic into shared startActivation/stopActivation
- Extract polling helpers: updateDetailsIfChanged, updatePeersIfChanged, applyExtensionStatus
2026-04-14 10:30:08 +02:00
Maycon Santos dd44b168fa Fix DNS resolution failure when toggling exit nodes (#82)
- Route all DNS through the tunnel on iOS by always setting matchDomains=[""], eliminating the drift between Go's DNS server (which has a root zone fallback handler) and iOS 
  tunnel settings that only matched specific domains
  - Handle empty route notifications from Go — when the exit node was the only route and was deselected, the notifier sent an empty string that Swift silently dropped, leaving 
  stale 0.0.0.0/0 in the tunnel and black-holing all traffic                                                                                                                    
  - Fix route card status indicator showing green after deselecting a route by checking route.selected before evaluating peer connection status
2026-04-08 08:44:18 +02:00
evgeniyChepelev 905e0d8dc2 Tv os changes (#72)
* fix ui state for airplaine mode

* fix slide bar

* Keep VPN tunnel alive during network unavailability

- Add isNetworkUnavailable flag to NetBirdAdapter to track network state
- Modify ConnectionListener to stay in 'connecting' state when network
  is unavailable instead of transitioning to 'disconnected'
- Update PacketTunnelProvider to set network unavailable flag and
  trigger automatic reconnect when network returns
- Fix CustomLottieView to show grey 'Disconnected' state immediately
  when network is lost, without closing the VPN tunnel
- Ensure UI shows correct state after app foreground/background cycle

This allows the VPN tunnel to survive temporary network outages
(e.g. airplane mode) and automatically reconnect when network returns.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix UI state after app foreground/background cycle

Show correct connected/disconnected state immediately when app returns
from background, without replaying animations. Use extensionStatus
(iOS VPN state) as the source of truth for UI state.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* netbird credential

* Update MainView.swift

* Separate button by state

* Add gogoleServiceInfo plist reference

* Remove dead code in animation state machine and fix copy-to-clipboard UX  - Remove unreachable shouldForceReset block in CustomLottieView (already handled by earlier return) - Guard against copying empty fqdn/ip strings when disconnected - Use consistent .smooth animation for both fqdn and ip copy feedback

- Remove unreachable shouldForceReset block in CustomLottieView (already handled by earlier return)
- Guard against copying empty fqdn/ip strings when disconnected
- Use consistent .smooth animation for both fqdn and ip copy feedback

* Tab bar

* Update peer view

* Update fonts

* Redesign tvOS connection screen and add peer search

- Move logo to top-left brand anchor (smaller, semi-transparent)
- Restyle connect button with gradient fill, glow shadow, and
  press-down scale animation (TVConnectButtonStyle)
- Add search bar with clear button to peers list view

* Redesign tvOS UI with gradient backgrounds

* Update logo position

* Redesign tvOS peers & resources lists to match settings UI style

* Add color-coded connection status indicator and debug state overlay

* Stabilize connection screen layout and remove debug overlay

* Update project.pbxproj

* Delete mock data

* Update info plist

* Update project.pbxproj

* add go get

* fix Self-hosted management URL

* Fix infinite connecting state after canceling QR code auth on tvOS

* Code refactoring

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: mlsmaycon <mlsmaycon@gmail.com>
2026-03-22 11:52:24 +01:00
evgeniyChepelev 4c95a6582a Implement VPN On Demand with Wi-Fi & cellular policies (#70)
* fix ui state for airplaine mode

* fix slide bar

* Keep VPN tunnel alive during network unavailability

- Add isNetworkUnavailable flag to NetBirdAdapter to track network state
- Modify ConnectionListener to stay in 'connecting' state when network
  is unavailable instead of transitioning to 'disconnected'
- Update PacketTunnelProvider to set network unavailable flag and
  trigger automatic reconnect when network returns
- Fix CustomLottieView to show grey 'Disconnected' state immediately
  when network is lost, without closing the VPN tunnel
- Ensure UI shows correct state after app foreground/background cycle

This allows the VPN tunnel to survive temporary network outages
(e.g. airplane mode) and automatically reconnect when network returns.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix UI state after app foreground/background cycle

Show correct connected/disconnected state immediately when app returns
from background, without replaying animations. Use extensionStatus
(iOS VPN state) as the source of truth for UI state.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* netbird credential

* Update MainView.swift

* Separate button by state

* Add gogoleServiceInfo plist reference

* Remove dead code in animation state machine and fix copy-to-clipboard UX  - Remove unreachable shouldForceReset block in CustomLottieView (already handled by earlier return) - Guard against copying empty fqdn/ip strings when disconnected - Use consistent .smooth animation for both fqdn and ip copy feedback

- Remove unreachable shouldForceReset block in CustomLottieView (already handled by earlier return)
- Guard against copying empty fqdn/ip strings when disconnected
- Use consistent .smooth animation for both fqdn and ip copy feedback

* Tab bar

* Update peer view

* Add offline state handling and network warning banner

- Show "Offline" instead of "Connected" when VPN tunnel is active but device has no internet
- Add NetworkWarningBanner with "Network Issues" warning when connected without internet
- Remove InternetStatusView (online/offline indicator) from connection screen
- Add FirstLaunchView onboarding screen
- Remove unused components (CustomBackButton, Extensions, JustifiedText, SolidButton, TransparentGradientButton)
- Update AboutView, AdvancedView, ServerView, PeerTabView, RouteTabView, iOSNetworksView styling
- Add EmptyTabPlaceholder component

* Add AppButton component with liquid glass support for iOS 26+

* Update FirstLaunchView.swift

* old version

* Update project.pbxproj

* Code refactoring

* Update project.pbxproj

* VPN On Demand

* Update MainViewModel.swift

* Add granular VPN On Demand settings with per-interface rules and conflict detection

* Update project.pbxproj

* code refactoring

* Add Wi-Fi network management for VPN On Demand settings

* Fix ai comments

Prevent On Demand enable when user is not logged in
Add login status check in setOnDemandEnabled() to prevent reconnect
loops when VPN On Demand is enabled without an active session.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-20 15:20:30 +01:00
evgeniyChepelev 21d4d9dcde Fixes to the VPN connection button state when there is no internet connection (#55)
* fix ui state for airplaine mode

* fix slide bar

* Keep VPN tunnel alive during network unavailability

- Add isNetworkUnavailable flag to NetBirdAdapter to track network state
- Modify ConnectionListener to stay in 'connecting' state when network
  is unavailable instead of transitioning to 'disconnected'
- Update PacketTunnelProvider to set network unavailable flag and
  trigger automatic reconnect when network returns
- Fix CustomLottieView to show grey 'Disconnected' state immediately
  when network is lost, without closing the VPN tunnel
- Ensure UI shows correct state after app foreground/background cycle

This allows the VPN tunnel to survive temporary network outages
(e.g. airplane mode) and automatically reconnect when network returns.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Fix UI state after app foreground/background cycle

Show correct connected/disconnected state immediately when app returns
from background, without replaying animations. Use extensionStatus
(iOS VPN state) as the source of truth for UI state.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* netbird credential

* Add gogoleServiceInfo plist reference

* Remove dead code in animation state machine and fix copy-to-clipboard UX  - Remove unreachable shouldForceReset block in CustomLottieView (already handled by earlier return) - Guard against copying empty fqdn/ip strings when disconnected - Use consistent .smooth animation for both fqdn and ip copy feedback

- Remove unreachable shouldForceReset block in CustomLottieView (already handled by earlier return)
- Guard against copying empty fqdn/ip strings when disconnected
- Use consistent .smooth animation for both fqdn and ip copy feedback

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-09 22:40:51 +01:00
Diego Romar 72ab3a55c9 UI reporting wrong connection state when VPN is running (#48)
* Add method to return the current VPN connection state

By checking if there's a VPN Manager instance from preferences
whose name matches the extension's. If so, it sets the extension's
session with its connection, and returns the current VPN status.
Returns false, otherwise.

* Call loadCurrentConnectionState when app becomes active

This will be used to both report the current connection state properly
and configure the ExtensionAdpater's session before polling.

This doesn't start or create a new VPN manager, it only checks for one
that is already running in case the VPN is connected by the time the app
cold starts.

* Guard active state after async operations to prevent background polling

* Bump version to v0.0.16.2
2026-01-23 17:46:34 -03:00
shuuri-labs 4c2791ca60 Add tvOS (Apple TV) support for NetBird VPN client (#36)
* Add tvOS (Apple TV) support for NetBird VPN client

This commit introduces full tvOS support for the NetBird iOS client,
enabling VPN connectivity on Apple TV devices.

- Added NetBird TV app target with tvOS 16.0+ deployment
- Created tvOS-specific UI using SwiftUI optimized for "10-foot experience"
- Tab-based navigation: Connection, Peers, Networks, Settings
- Large touch targets and text for Siri Remote navigation

- TVMainView: Main tab navigation and connection status
- TVConnectionView: Large connect/disconnect button with status display
- TVPeersView: List of connected peers with connection details
- TVNetworksView: Network routes selection and management
- TVSettingsView: App settings and logout functionality
- TVAuthView: QR code + device code authentication flow

- Implemented OAuth device authorization flow for tvOS
- Displays QR code that user scans with phone to authenticate
- Shows user code as fallback for manual entry
- Polls for authentication completion and auto-dismisses on success

tvOS has stricter sandbox restrictions than iOS:

1. **UserDefaults-based Config Storage**
   - tvOS blocks file writes to App Group containers
   - Config stored in shared UserDefaults instead of files
   - Added Preferences methods: saveConfigToUserDefaults(),
     loadConfigFromUserDefaults(), hasConfigInUserDefaults()

2. **Preloaded Config in Go SDK**
   - SDK modified to accept config via setConfigFromJSON()
   - Avoids file I/O that would fail in tvOS sandbox
   - Config passed from UserDefaults to SDK at runtime

3. **Raw Syscall Tunnel FD Discovery**
   - tvOS SDK doesn't expose ctl_info, sockaddr_ctl, CTLIOCGINFO
   - Implemented findTunnelFileDescriptorTvOS() using raw memory ops
   - Manually defines kernel structure layouts at byte level
   - Uses getpeername() and ioctl() which ARE available on tvOS

- Added NetBirdTVNetworkExtension target
- Separate PacketTunnelProvider.swift with tvOS-specific handling
- Extensive logging for debugging via Console.app
- Handles "LoginTV" message for device auth flow
- Loads config from UserDefaults into SDK memory

- isLoginRequired() now verifies session with management server
- Previously only checked if config existed (caused post-restart failures)
- Shows QR code re-auth flow when OAuth session expires

- Added Platform.swift for iOS/tvOS conditional compilation
- Shared code uses #if os(tvOS) / #if os(iOS) where needed
- Common ViewModels work across both platforms

* cleanup

* fixed slow startup + added images

* fixed active networks not refreshing

* fix occasional failure of first connection

* hostname properly set + removed debug logging

* - Fix "invalid Prefix" display on Networks tab by showing route name
- Update ServerViewModel to use new SDK callback-based API
- Fix focus navigation on Networks and Settings tabs
- Add white text on focus for better readability across all cards
- Increase filter bar spacing to prevent highlight overlap
- Add TVSettingsInfoRow for non-interactive display items

* Fixed focus escape bug on 'change server' dialog

* fixed switching of management servers

* fixes for change server settings menu

* - Extract TVColors and TVLayout to shared TVColors.swift
- Remove duplicate TVColors structs from 5 TV view files
- Add ClearConfig IPC message to clear extension-local config on logout
- Switch MainView from viewModel.isIpad to DeviceType.isPad
- Remove unused isTV/isIpad properties from MainViewModel
- Add TVColors.swift to Xcode project

* apply recommended xcode settings

* display correct app name in tvOS UI

* added tv-specific assets, updated readme

* updated readme

* - Add checkLoginError IPC to detect extension login failures
- Remove dead shared UserDefaults fallback code in NetBirdAdapter
- Document tvOS config storage architecture in Preferences.swift
- Fix onChange deprecation warnings in TVSettingsView
- Add "no peer auth method" detection in ServerViewModel

* Fix CodeRabbit review issues: bundle IDs, force-unwraps, and error handling

- Fix mismatched bundle IDs between Debug/Release configs for tvOS targets
- Make Preferences.configFile() and stateFile() return optionals instead of
  force-unwrapping, with proper error logging when app group unavailable
- Make NetBirdAdapter.init failable to handle SDK client creation failures
- Fail fast in NetBirdAdapter.start() when tunnel file descriptor is invalid
  instead of silently passing fd=0 (stdin) to the SDK
- Ensure all handleAppMessage switch cases call completionHandler to prevent
  IPC callers from hanging indefinitely

* - Delete unused updateManagementURL() and setSetupKey() functions
  (functionality migrated to ServerViewModel)
- Remove orphaned managementURL property
- Simplify supportsKeyboard to just return true (both branches were identical)
- Updated README instructions on buiilding tvOS SDK (needs NetBird gomobile fork)

* Fix tvOS build issues from CodeRabbit review

- Use empty configPath on tvOS in loginAsync() since config uses UserDefaults
- Add JSON escaping in updateDeviceNameInConfig() for special characters
- Standardize TVOS_DEPLOYMENT_TARGET to 17.0 across all configurations
- Add missing CODE_SIGN_ENTITLEMENTS to NetBird TV Release config

* added empty box asset to tvOS app

* - Preferences.swift: Use #if os(iOS) / #else for platform-specific
  newPreferences() - iOS returns non-optional with preconditionFailure
  on misconfiguration, tvOS returns nil by design (uses IPC not SDK)

- MainViewModel: Wrap preferences property and SDK methods (rosenpass,
  presharedKey) in platform conditionals. Add tvOS stubs for methods
  called from shared UI. Wrap IPC flag methods (checkLoginRequiredFlag,
  checkNetworkUnavailableFlag) since App Group UserDefaults are
  isolated sandboxes on tvOS.

- PacketTunnelProvider: Fix optional unwrapping for clientState logging

- project.pbxproj: Add Platform.swift to iOS target (was tvOS-only)

* Add ConfigurationProvider protocol to abstract platform config storage

- Create ConfigurationProvider protocol with iOS/tvOS implementations
- iOS uses NetBirdSDKPreferences (file-based), tvOS uses UserDefaults
- Refactor MainViewModel to use ConfigurationProvider, removing platform
  conditionals and empty tvOS stubs
- tvOS now stores rosenpass/presharedKey settings locally (ready for
  future IPC integration)

* implemented rosenpass toggle

* implemented preshared key setting

* Update GitHub Actions to use macOS 15 with Xcode 16

Project uses Xcode 16 project format (objectVersion 70) which isn't
compatible with Xcode 15.x on macos-14 runners.

* Add tvOS app icons, Top Shelf images, and fix archive validation errors

- Add complete tvOS icon assets (App Icon, App Store Icon, Top Shelf)
- Add arm64 to UIRequiredDeviceCapabilities for TV Network Extension
- Add TVTopShelfImage configuration to tvOS Info.plist
- Fix iOS build cycle by reordering Embed Frameworks before Crashlytics script

* Fix tvOS SDK path and add config update logging

- Use SDKROOT for libresolv.tbd instead of hardcoded SDK version
- Add AppLogger warnings when config JSON updates fail

* re-added test targets to project.pbxproj (lost in merge)

* Replace regex-based JSON manipulation with JSONSerialization for
reading and writing config fields

* Address PR review feedback for tvOS support

- Add detailed comment explaining tvOS UserDefaults sync limitation
- Use AppLogger instead of print in Preferences.swift
- Remove unnecessary #if os() checks in tvOS PacketTunnelProvider
- Remove duplicate tvOS entitlement/plist files from NetBirdTV/
- Fix CI build destinations to use simulator

* Removed dead variables from TVPeersListContent, Updated tvOS config JSON parsing method

* update build platform (iphone 16 -> iphone 15) in an attempt to resolve github actions error

* update build platform in an attempt to resolve github actions error

* update xcode build runner an attempt to resolve github actions error

* update build.yml to specify downloading of ios 18.2 image to fix build error

* update build.yml to remove specifying of ios 18.2 image download

* downgrade macos build image to 14 to resolve ios build error on github

* downgrade macos build image to 14 to resolve ios build error on github

* upgrade build runner xcode version to 26.2 to resolve ios build error on github

* upgrade build runner xcode version to 26.2 to resolve ios build error on github

* upgrade build runner xcode version to 26.2 to resolve ios build error on github

* upgrade build runner xcode version to 26.1.1 to resolve ios build error on github

* upgrade build script sdk output path to resolve ios build error on github

* added create dummy GoogleService-Info.plist build step to github workflows

* Fix TVAuthView error UI not displaying by setting errorMessage state

* - replace pipe-delimited string parsing with typed LoginDiagnostics
struct

- removed unused initializeConfigViaExtension method and converted
some print statements to logger.debug for consistency

* more pipe -> struct refactoring

* update readme and buildscript to use gomobile-netbird for building sdk, sdk version bump

* fix initial connection bug that required user to press 'connect' again after completing sso flow

* improve app loading speed + add splash screen logo

* Fix race condition in tvOS VPN connection and revert Firebase to main thread

- Move startVPNConnection() inside sendConfigToExtension completion handler to ensure config transfer completes before VPN starts
- Revert Firebase initialization to main thread as required by Firebase documentation
- Keep ViewModelLoader with loading screen to improve perceived startup time
- Keep lazy NetworkExtensionAdapter.configureManager() call removed from init

* fix test github workflow

* fix TVColors.swift UUID in project.pbxproj

* fix gomobile-netbird run in github workflow by adding 'gomobile-netbird init' step

* Add gomobile-netbird init step to GitHub Actions workflow with proper PATH configuration

* revert build script changes

* bump network extension ver to 7 - apple states this should match the main app's ver #

* remove unused wireguardkitgo paths

* Fix version mismatch between iOS app and network extension

* Add diagnostic logging to test workflow to capture crash details

Capture full xcodebuild output and system crash logs when tests fail.
This will help debug the test crash that occurs during app bootstrapping
in CI but not locally.

- Tee test output to file before xcpretty filtering
- Search for and print crash reports from DiagnosticReports
- Upload test logs and crash reports as artifacts on failure

* use gomobile-netbird in build script, workflows

* update build workflow to use gomobile-netbird

* force pulling of latest gomobile-netbird

* install gobind manually rather than relying on gomobile init

* add gomobile-tvos-for support download module step to workflows

* checkout gomobile-tv-fork module instead of go mod, which doesn't play nicely with github actions

* Add gomobile-tvos-fork to netbird's go.mod so gobind can find bind package

* revert debugging for test workflow

* fix rosenpass toggle bug for ios - view does not read value from saved config so always appears as disabled

* temporarily disable test workflow
2026-01-16 20:58:34 +01:00
Maycon Santos 58ccfd245d Bug/network type switch crash swift logs (#39)
* Add completion handler usage when restarting client

* Fix UI stuck in connecting state during network type switches

  Message:
  When switching between wifi and cellular, the Go engine fires rapid state
  changes (connecting → disconnecting → connected) that confused the UI
  animation state machine, causing it to get stuck in "Connecting..." state.

  Changes:
  - Add isRestarting flag to suppress intermediate state updates during restart
  - Add recovery path in playDisconnectingLoop when engine reconnects
  - Add status polling guard to prevent concurrent fetchData calls
  - Add AppLogger for unified Swift logging to shared container
  - Update share logs to export both engine and app log files

* add build and test workflows and handle missing firebase files

* update jobs and docs with build script

* fix paths

* fix PeerCard.swift ref

* fix comments

* remove network extension refs

* Removed PBXBuildFile references

* use newer xcode

* handle airplane mode

* remove xcode selection

* address comments

* use macos-14

* use a subdirectory

* use a subdirectory in test

* improve reliability when handling auth

* Removed Firebase initialization in networkextension

* remove mac designed for ipad support from gui

* fix readme version

* add popoverPresentationController when running on ipad

* Uses temporary directory instead of Documents

* Removed the misleading comment about onConnected()

* Added fallback to Documents directory when App Group is unavailable

* Added tests

* Added workflow permissions

* handle potential nil in tests

* handle airplane mode freezes

* fix comment

* update airplane mode handler

* build 9

* remove print and reduce max log app size to 100kb

* fix comments

* build 10

* minor UI bugfixes (#40)

* Remove setting of statusDetailsValid to false on handleServerChanged()

This variable is used to show the splash screen until the app successfully starts polling,
then it's set to true and and it's never set to false again afterwards.

* Change DispatchQueue.global usage for Task.detached to stop network extension

Gets rid of warning: Main actor-isolated property 'networkExtensionAdapter'
can not be referenced from a Sendable closure.

The ViewModel class is marked @MainActor, which means networkExtensionAdapter
is isolated to the main actor. Accessing it from a DispatchQueue.global closure
(which runs on a background thread) violates Swift's actor isolation rules.

* Manually stop and start polling when navigating to and from ServerView

Choosing to Change Server creates a dialog that when clicked on the Confirm
button, it stops the client connection.  This is handled via the handleServerChanged method.

When app starts, though, it polls in a loop for the current state of the connection via startPollingDetails.
It is overwriting the states manually assigned inside handleServerChanged.
This commit manually turns off the polling when handleServerChanged is called, and turns it back on
after user navigates away from ServerView.

* Resolve network switch nitpicks (#41)

* Offload file IO to backgroud thread while sharing logs

* Use atomic property wrapper on isFetchingStatus to avoid racing conditions

* Add timer to fetchData to make sure isFetchingStatus is set to false

In the odd case the completionHandler for session.sendProviderMessage never gets called

* Replace usage of print with AppLogger.shared.log in PacketTunnelProvider

* Set currentNetworkType = nil on network restore

So the first post-restore path update won't incorrectly skip a type-change restart due to stale state

* Add debouncing mechanism on networkChange

To keep restarts from happening in succession if the network interfaces available
switch back and forth too quicky

networkChangeWorkItem (DispatchWorkItem) is used for this and it iss stopped
and cleard in these scenarios:
network loss, tunnel stop, rapid network type change (the latter, before potentially
scheduling a new one)

* Add startMonitoringNetworkChanges inside the monitor queue async block

To maintain order of state resetting before monitoring resumes on restart

* Use atomic property wrappers on clientState and isRestarting

Avoids potential cross-queue reads: handleNetworkChange runs
on monitorQueue (changing isRestarting) and adapter.clientState
 is written from ConnectionListener but read on monitorQueue

* Add lock to stopCompletionHandler to avoid race condition

This handler is accessed in multiple queues without synchronization:
Set in stop() - called from monitorQueue (via restartClient in PacketTunnelProvider)
Read/cleared in notifyStopCompleted() - called from:
    - DispatchQueue.global() (timeout)
    - ConnectionListener.onDisconnected() (Go SDK callback queue)

* Use guard and preconditionFailure if it fails to call NetBirdSDKNewPreferences

* Extract common getfilePath method usage when getting config and state files

File names were added to constants in GlobalConstants
Attempts to use applicationSupportDirectory as fallback if app group is not available;
Then documentDirectory, and finally, temporaryDirectory as last resort

* Use FileManager.copyItem instead of loading logs into memory

Log and delete tempDir if rootViewController isn't found

* Add timeout for restartClient

If in 30s the stopCompletionHandler (adapter.start()) isn't called,
the timeout will reset the adapter's isRestarting and packetTunnelProvider's
isRestartInProgress flags to false so the UI can recover from supressed state
updates

* Add explicit dismissal of ChangeServerAlert when clicking Confirm button

* Set currentNetworkType to nil on stopTunnel

if the extension process stays alive, the next handleNetworkChange
may treat the “first satisfied path” as a transition rather than initialization.

* Dispatch networkChangeWorkItem cancellation to monitorQueue

* Add guard usage when attempting to create log files

For rotateLogsIfNeeded and clearLogs so that isReady is marked as false
in case calling FileManager.default.createFile returns nil; on exception,
isReady is set to false and fileHandle is set to nil so that log creation doesn't
fail silently.

* Revert "Set currentNetworkType = nil on network restore"

This reverts commit eadb036e63.

* Resolve handling network changes when it switches between wifi and cellular (#42)

* Offload file IO to backgroud thread while sharing logs

* Use atomic property wrapper on isFetchingStatus to avoid racing conditions

* Add timer to fetchData to make sure isFetchingStatus is set to false

In the odd case the completionHandler for session.sendProviderMessage never gets called

* Replace usage of print with AppLogger.shared.log in PacketTunnelProvider

* Set currentNetworkType = nil on network restore

So the first post-restore path update won't incorrectly skip a type-change restart due to stale state

* Add debouncing mechanism on networkChange

To keep restarts from happening in succession if the network interfaces available
switch back and forth too quicky

networkChangeWorkItem (DispatchWorkItem) is used for this and it iss stopped
and cleard in these scenarios:
network loss, tunnel stop, rapid network type change (the latter, before potentially
scheduling a new one)

* Add startMonitoringNetworkChanges inside the monitor queue async block

To maintain order of state resetting before monitoring resumes on restart

* Use atomic property wrappers on clientState and isRestarting

Avoids potential cross-queue reads: handleNetworkChange runs
on monitorQueue (changing isRestarting) and adapter.clientState
 is written from ConnectionListener but read on monitorQueue

* Add lock to stopCompletionHandler to avoid race condition

This handler is accessed in multiple queues without synchronization:
Set in stop() - called from monitorQueue (via restartClient in PacketTunnelProvider)
Read/cleared in notifyStopCompleted() - called from:
    - DispatchQueue.global() (timeout)
    - ConnectionListener.onDisconnected() (Go SDK callback queue)

* Use guard and preconditionFailure if it fails to call NetBirdSDKNewPreferences

* Extract common getfilePath method usage when getting config and state files

File names were added to constants in GlobalConstants
Attempts to use applicationSupportDirectory as fallback if app group is not available;
Then documentDirectory, and finally, temporaryDirectory as last resort

* Use FileManager.copyItem instead of loading logs into memory

Log and delete tempDir if rootViewController isn't found

* Add timeout for restartClient

If in 30s the stopCompletionHandler (adapter.start()) isn't called,
the timeout will reset the adapter's isRestarting and packetTunnelProvider's
isRestartInProgress flags to false so the UI can recover from supressed state
updates

* Add explicit dismissal of ChangeServerAlert when clicking Confirm button

* Set currentNetworkType to nil on stopTunnel

if the extension process stays alive, the next handleNetworkChange
may treat the “first satisfied path” as a transition rather than initialization.

* Dispatch networkChangeWorkItem cancellation to monitorQueue

* Add guard usage when attempting to create log files

For rotateLogsIfNeeded and clearLogs so that isReady is marked as false
in case calling FileManager.default.createFile returns nil; on exception,
isReady is set to false and fileHandle is set to nil so that log creation doesn't
fail silently.

* Revert "Set currentNetworkType = nil on network restore"

This reverts commit eadb036e63.

* Bump version (0.0.14.12)

* Add Network.NWPath info logs on handleNetworkChange

* Remove early return on network reestablishment

To allow network type change detection to run after network restoration.
Sometimes NWPathMonitor reports NWPath with status != .satistied on network change.

* Remove setting currentNetworkType to nil when network goes down

To maintain the previously used network type and correctly detect a network change
when the connection is reestablished with another type to trigger a restart

* Bump version (0.0.14.13)

* Add logic to restart engine if recovering from network unavailable

* Bump version (0.0.14.14)

* Bump version (0.0.14.15)

This version is packaged with NetBirdSDK that executes
engine.go start's method with extra logs and execution
of PopulateNetbirdConfig in a goroutine

---------

Co-authored-by: Diego Romar <doromaraujo+github@gmail.com>
2025-12-18 18:06:10 +01:00
Diego Romar 675c560a63 Add force relay connection option (#37)
* Add some tests calling sdk method to set environment variable

* Add GlobalConstants and EnvVarPackager

* Add EnvList as parameter to NetBirdSDKClient.run method

* Add option to toggle force relay connection to AdvancedView

MainViewModel code is stil WIP

* Add usage of appGroup when using shared UserDefaults

* Use the defined App Group identifier for userPreferencesSuiteName

* Add ForceRelayAlert to be displayed when user toggles the option in AdvancedView

* Extract code that grays out background when an Alert is displayed in AdvancedView to a common function

* Remove prints

* Replace @StateObject with @EnvironmentObject property wrapper for viewModel in Alerts

Their parent view (AdvancedView) also accesses it via @EnvironmentObject property

* Replace force unwrap with flatMap

* Add default value for keyForceRelayConnection when reading from defaults

If the key isn't set, it will use the value by default

* Update forceRelayConnection property with the provided value when setForcedRelayConnection is called

* Remove redundant parameter for LogLevelAlert

* Add default value usage for keyForceRelayConnection in MainViewModel

* Wrap onConnected()'s self.completionHandler(nil) call with DispatchQueue.main.async

So that the call happens in the main thread to correctly handle UI state update (Connecting... -> Connected)
2025-12-12 14:30:17 -03:00
Pascal Fischer 3e292e101f Remove force unwrap (#23) 2025-04-24 14:43:20 +02:00
Pascal Fischer f9bea1912a Route states support (#19) 2024-12-06 16:50:13 +01:00
Pascal Fischer 462f404213 allow copy of peer ip and some fixed crashed due to nullpointer (#18) 2024-12-03 22:43:01 +01:00
pascal-fischer 577e241abd added some nullpointer checks to the extension code (#16) 2024-08-06 22:31:42 +02:00
pascal-fischer c5cb60160c Add DNS routes support (#12) 2024-07-17 16:00:30 +02:00
pascal-fischer b132cc70d7 Add route selection and detailed status output (#10) 2024-05-13 16:58:12 +02:00
pascal-fischer cd954d80cd Add log export option (#7) 2024-04-30 11:45:27 +02:00
pascal-fischer 1094707903 Add exit node support (#8)
* split default route into multiple smaller ones to avoid dns issues

* add project file
2024-04-26 22:35:39 +02:00
Maycon Santos 8209c91f03 open-source code 2024-02-28 19:22:16 +01:00