Skip to content

Add Android client support and release 0.0.41 - #55

Merged
andrewchen5678 merged 3 commits into
mainfrom
android-client
Aug 21, 2026
Merged

andrewchen5678 merged 3 commits into
mainfrom
android-client

Conversation

@andrewchen5678

Copy link
Copy Markdown
Collaborator

Summary

  • Android client support in the Rust core: JNI surface (src/ffi_android.rs, bound to dev.flexaccess.ezvpn.EzvpnNative), the fd-based MobileSession shared with Apple (src/tunnel/ios.rssrc/tunnel/mobile.rs), and the Android-only in-tunnel split-DNS forwarder (src/tunnel/dns_proxy.rs).
  • build-android.sh + a build-android-lib release job publishing libezvpn-android.zip; CI runs the Android clippy and a verify-only build.
  • docs/Android-App.md for the app in the sibling ezvpn-android repo.
  • Bump version to 0.0.41 (the Android app pins this tag for its jniLibs).

Test plan

  • cargo clippy --all-targets -- -D warnings, cargo test
  • cargo ndk -t arm64-v8a --platform 29 clippy --lib -- -D warnings
  • Smoke-tested on a Nexus 7 (armeabi-v7a, Android 11) against a local server: connect, split routes, split DNS, path query, disconnect
  • CI green on this PR

🤖 Generated with Claude Code

https://claude.ai/code/session_01WZxQCX8Kwr4yZV6R96TaYP

Andrew Chen and others added 3 commits August 21, 2026 08:57
…S forwarder

Extend the fd-based mobile session (src/tunnel/ios.rs -> mobile.rs) to
Android and expose it through a JNI layer bound to the Kotlin object
dev.flexaccess.ezvpn.EzvpnNative (src/ffi_android.rs): init registers the
JVM/context that iroh's Android DNS and interface discovery need via
ndk-context, connect/run/stop/connPath delegate to the shared EzvpnHandle,
and onTunnelExit calls back into Kotlin when the data loop ends on its own.
TunDevice::from_raw_fd wraps the VpnService tun fd.

Add the Android-only in-tunnel split-DNS forwarder (src/tunnel/dns_proxy.rs):
VpnService has no per-domain DNS, so the app points the VPN's DNS at a proxy
address routed into the tun and the data path answers UDP/53 to it itself,
forwarding matched names to the tunnel resolvers and everything else to the
underlying network's resolvers through protect()ed sockets (ids rewritten
per query, TCP 53/853 refused with RST, oversized answers truncated). Every
other platform passes None and keeps OS-level conditional forwarding.

build-android.sh builds libezvpn.so per ABI (cargo-ndk, or a bare NDK
sysroot on hosts without an NDK) and stages libezvpn-android.zip; CI gets an
android clippy/build job and the release workflow publishes the zip. Docs:
docs/Android-App.md plus README/Architecture/CLAUDE.md updates.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZxQCX8Kwr4yZV6R96TaYP
- CI builds x86_64 too, matching the release workflow's ABI set
- build-android.sh checks the sysroot + libunwind.a for every selected ABI
- ffi: a stop flag silences the exit hook even when the loop ends
  concurrently with stop; parse_resolver trims the scope and rejects a
  scope on IPv4
- dns_proxy: fallback sockets made non-blocking at adoption, upstream
  reader tasks aborted with the proxy, the pending table evicts only the
  oldest query when full, question names logged at trace only
- ffi_android: init captures the JVM once with a single error path

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZxQCX8Kwr4yZV6R96TaYP
ANDROID_NDK_LATEST_HOME is a runner-machine environment variable; it is
visible to the step's shell but not to the `env` expression context, so
`${{ env.ANDROID_NDK_LATEST_HOME }}` expanded to an empty ANDROID_NDK_HOME
and cargo-ndk failed with "Error detecting NDK version for path". Export
it from the shell instead and fail loudly if the runner has no NDK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WZxQCX8Kwr4yZV6R96TaYP
@andrewchen5678
andrewchen5678 merged commit 4f1519f into main Aug 21, 2026
6 checks passed
@andrewchen5678
andrewchen5678 deleted the android-client branch August 21, 2026 17:12
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.

1 participant