Tor API changes for mobile phone - #367
Conversation
|
needed by this |
|
tor binary/packages used from guardianproject |
|
As of August 17, 2026, this is an open, unmerged Tor integration split across two PRs:
What rs-mobile PR #42 implementsThe mobile PR adds three operating modes:
Embedded Tor runtimeThe app adds these dependencies: implementation "info.guardianproject:tor-android:0.4.8.16"
implementation "info.guardianproject:jtorctl:0.4.5.7"Version A new native Android
Flutter communicates with this manager through a method channel: External Tor supportIn external mode, rs-mobile does not manage the other Tor process. It gives libretroshare:
The default endpoint values are Despite the UI saying “External Tor / Orbot,” the current UI does not appear to expose editable host and port fields. It therefore assumes those defaults when switching modes. Hidden-node account creationThe previously inactive “Tor/I2P Hidden node” checkbox becomes a functional “Embedded Tor hidden node” option. When selected, signup:
{
"makeHidden": true,
"makeAutoTor": true
}
Network settings UIFor hidden locations, the network screen now:
What is used from tor-androidThe integration uses a relatively narrow part of Guardian Project’s project:
The app does not modify Tor itself and does not embed the tor-android source tree. It consumes the published AAR.
What libretroshare PR #367 implementsThe backend PR contains the changes that make Android-managed Tor usable by RetroShare. Pre-login Tor configurationIt adds an unauthenticated JSON endpoint: This is deliberately available before login because Tor must be configured before hidden-node initialization begins. The endpoint passes the control and SOCKS endpoints to External-process mode
This separation is important: Android owns the process lifecycle, while libretroshare owns hidden-service configuration and RetroShare routing. Hidden account creation API
bool makeHidden = false;
bool makeAutoTor = false;The JSON API accepts those fields and forwards them to Hidden-service information
to obtain:
This is what drives the onion-address display in network settings. Android compatibilityThe PR also disables a Linux “must run on the main thread” assertion on Android: #elif defined(__linux__) && !defined(__ANDROID__)Android defines Important integration gapBoth PRs are still open. More importantly, the final rs-mobile branch currently declares: implementation "org.retroshare.service:libretroshare-MinApiLevel24-debug:ebbc30e3"
Consequences with the older backend:
The mobile code intentionally catches some missing-endpoint errors, so the UI can still load with older AARs. That compatibility behavior should not be mistaken for complete Tor functionality—the libretroshare PR must be included in the Android backend artifact for the full flow to work. |
|
Having |
but private coockie is used other apps then cant use it https://gist.github.com/ndsamuelson/3c83f38ae470c82ff87d2653af11716b
|
TorControl::connect() sets the status to Connecting before attempting the synchronous TCP connection, but never reset it when the connection failed, so the status stayed at Connecting forever and TorManager::threadTick() (which only retries from the NotConnected state) never attempted to connect again. With an external Tor (e.g. Orbot not started yet, or a wrong control port) this was the main failure mode: the whole auto-Tor login sequence hung forever without reporting any error. TorControl::reconnect() had the same problem, plus it ignored the result of connectToHost() entirely: on success the status stayed at Connecting (so authentication was never attempted after an Error recovery), and on failure it was equally stuck. Now both methods fall back to NotConnected on failure, so the manager thread retries, and reconnect() properly enters SocketConnected on success.
…) thread safe threadTick() runs every 50ms and the connection attempt is synchronous, so retrying from the NotConnected state (now reachable again after a failed attempt) would hammer the control port with up to 20 connections per second. Throttle attempts to one every 2 seconds, and restore the connection log line (with an external-Tor variant) that told which endpoint is being tried. RsTor::instance() lazily creates the TorManager and used platform asserts to require the main thread, which was the guard for that unsynchronized initialisation. But RsTor methods are exposed through the JSON API and thus legitimately reached from restbed worker threads: any /rsTor/* call - including the new setExternalTorConnection endpoint and the auto-Tor login path - aborted debug builds on Linux and Apple platforms (the __ANDROID__ exception covered Android only, not iOS). Protect the initialisation with a mutex instead, and drop the asserts.
startAutoTor() waited forever for Tor to become ready, with no timeout and no error to break the loop when the control connection could not be established at all (external Tor not running, wrong control port). Since this runs synchronously inside RsLoginHelper::attemptLogin(), a mobile or headless login on an auto-Tor node would simply never return. Give up with an explicit error if the control link has not been seen up once within 30 seconds. Once the control connection has been observed, keep waiting indefinitely for Tor to bootstrap, as before.
Tor: fix stuck control connection, endless auto-Tor login, off-main-thread assert




Core/API support for hidden/auto-Tor account creation.
Implemented the libretroshare Tor API changes
Changes include:
/rsTor/setExternalTorConnectionTorProcessfor embedded Android Tor or Orbot.TorProcess.isTorAvailable().Relevant files:
I also wired rs-mobile to call this endpoint before login or account creation: