No description
Find a file
2025-10-10 07:45:04 +00:00
.vscode got division_of_one wrapped in an Android app using Tauri 2025-06-20 21:42:00 +00:00
src update deps and set up Makefile shortcuts 2025-10-10 02:34:01 +00:00
src-tauri disable signing for now 2025-10-10 07:45:04 +00:00
.gitignore got division_of_one wrapped in an Android app using Tauri 2025-06-20 21:42:00 +00:00
COPYING mark the project as AGPLv3 for the time being 2025-10-10 02:51:24 +00:00
deno.lock got division_of_one wrapped in an Android app using Tauri 2025-06-20 21:42:00 +00:00
FUNDING.yml mark the project as AGPLv3 for the time being 2025-10-10 02:51:24 +00:00
index.html more preparing for tabs 2025-08-06 02:01:46 +00:00
Makefile trying to get fdroidserver to build this 2025-10-10 07:04:22 +00:00
package.json fix the cargo tests yay 2025-09-09 06:06:22 +00:00
README.md update deps and set up Makefile shortcuts 2025-10-10 02:34:01 +00:00
tsconfig.json got division_of_one wrapped in an Android app using Tauri 2025-06-20 21:42:00 +00:00
vite.config.ts change the UI to a little CLI chat thing 2025-07-15 22:22:47 +00:00

Next step

Use Fort Porwarding for something real. Maybe SSH between Amber and the media PC.

How to

How to use the Makefile shortcuts

  • make apk - Build an APK for aarch64 Android targets
  • make desktop - Build a desktop release binary for the current platform

How to build

How to install build pre-requisites

sudo apt-get update
sudo apt-get install libwebkit2gtk-4.1-dev \
  build-essential \
  curl \
  wget \
  file \
  libxdo-dev \
  libssl-dev \
  libayatana-appindicator3-dev \
  librsvg2-dev

# Install deno
curl -fsSL https://deno.land/install.sh | sh

# Install deps (equiv to npm install or pnpm install)
deno install

# Set this env var to keep Deno from phoning home when it doesn't need to
export DENO_NO_UPDATE_CHECK=1

How to build for Android

Download the Android Studio Meerkat Feature Drop (brought to you by Brawndo, the Thirst Mutilator, featuring Dante from Devil May Cry, and Knuckles) https://developer.android.com/studio

Unpack and run bin/studio

export ANDROID_HOME=/home/user/Android/Sdk
export NDK_HOME=/home/user/Android/Sdk/ndk/29.0.13599879

# Sometimes Cargo will do this for you but sometimes it won't lol
rustup target add aarch64-linux-android armv7-linux-androideabi

sudo apt-get install openjdk-17-jre

# Set up signing per https://v2.tauri.app/distribute/sign/android/

# Now petition the demiurge, make a save point, and mash BUILD
# Takes about 2.5 minutes

make apk

How to run

How to run for desktop

nice deno task tauri dev -- -- --secret-key-path private/iroh-secret-key.bin

How to test Fort Porwarding

You'll need to run the server and client once each to let them save their secret keys to disk, and to figure out their public keys.

Put the secret keys under private/, since it's ignored by Git. Secrets don't go in Git!

# In Terminal 1, start the server with a well-known key, pointed at example.com's plaintext HTTP, allowing our client to connect

cargo run -p fort_porwarding -- server \
--secret-key-path private/key-server.bin \
--upstream-addr '[2600:1408:ec00:36::1736:7f31]:80' \
--allowed-client-id "$CLIENT_ID"

# In Terminal 2, start the client, which will try to connect to either of my well-known server IDs

cargo run -p fort_porwarding -- client \
--secret-key-path private/key-client.bin \
--server-id "$SERVER_ID"

# In Terminal 3, GET example.com (with SNI), forwarded over Fort Porwarding

curl -v -H Host:example.com http://127.0.0.1:58008/

Absolutely every idea

  • Networked music player
  • Chat
  • Journal
  • Mood tracker
  • SSH / VNC
  • File sharing (e.g. movies from computer, camera roll from phone)
  • Tunneling

Random notes

"App not installed as package appears to be invalid"

I fixed this on Android but after renaming the project and blowing up gen/android it broke again

I had to add the signingConfigs section to gen/android/app/build.gradle.kts.

But after I do that, it can't find key.properties for some reason... was that in Git?

10 MB to 29 MB

It's actually due to Iroh, not due to the UnifiedPush plugin.

QUIC is just fucking huge.

Event storming

  1. UnifiedPush message
  2. Service lifecycle (onStart, onDestroy)
  3. UI events (User sends message)
  4. Inbound network data (incoming peer connection, incoming peer data)
  5. Activity lifecycle (onStart, onStop)
  6. Network state change (gained network)

1 - UnifiedPush messages come directly to the Kotlin service. We ensure the Rust main task is running, do some minimal decoding if needed, then do a try_send() into a 1-slot mpsc channel on the Rust side. Rust eventually wakes up, pulls the data from that channel, and processes the UP message.

2 - Service lifecycle messages come to the Service. onStart() triggers us to ensure the Rust main task is running. onDestroy() is forwarded to the Rust main task and it might be synchronous, it might call block_on() internally waiting on the Rust main task to stop.

3 - UI events come to the JS in the Tauri Activity. From there we can call into the Tauri Rust code in the Activity, and that can hop to the Rust main task, since everything is mostly in one process. This keeps us out of Kotlin as much as possible, so the code is reusable for desktop.

4 - Inbound network data comes to Iroh in the Rust main task. No problem there since we aren't thinking about outbound events yet.

5 - Activity lifecycle events probably create corresponding events in Tauri? We can forward those the same way as we forward UI events, since they're received in Rust code in the Activity.

6 - Network state change will come through Kotlin. If it's in the same process, we can treat it like UnifiedPush, we'll ensure the Rust library is loaded, ensure the main task is running, then do a notify() type call.

Issues:

  1. (Yes, for now anyway) Does block_on() for onDestroy() make sense?
  2. (LazyLock) How can I set up a per-process singleton so that I can always get a handle on the Rust main task from the Kotlin Service, from the Rust code in the Tauri Activity, etc? I'm willing to use a global just this once, but I'll keep that as a wrapper so that for testing and desktop I can still have multiple instances.

How about outbound events?

  1. Main task to UI - Works
  2. Main task to Kotlin - Works