mirror of
https://github.com/outbackdingo/firezone.git
synced 2026-01-27 10:18:54 +00:00
To make our FFI layer between Android and Rust safer, we adopt the UniFFI tool from Mozilla. UniFFI allows us to create a dedicated crate (here `client-ffi`) that contains Rust structs annotated with various attributes. These macros then generate code at compile time that is built into the shared object. Using a dedicated CLI from the UniFFI project, we can then generate Kotlin bindings from this shared object. The primary motivation for this effort is memory safety across the FFI boundary. Most importantly, we want to ensure that: - The session pointer is not used after it has been free'd - Disconnecting the session frees the pointer - Freeing the session does not happen as part of a callback as that triggers a cyclic dependency on the Rust side (callbacks are executed on a runtime and that runtime is dropped as part of dropping the session) To achieve all of these goals, we move away from callbacks altogether. UniFFI has great support for async functions. We leverage this support to expose a `suspend fn` to Android that returns `Event`s. These events map to the current callback functions. Internally, these events are read from a channel with a capacity of 1000 events. It is therefore not very time-critical that the app reads from this channel. `connlib` will happily continue even if the channel is full. 1000 events should be more than sufficient though in case the host app cannot immediately process them. We don't send events very often after all. This event-based design has major advantages: It allows us to make use of `AutoCloseable` on the Kotlin side, meaning the `session` pointer is only ever accessed as part of a `use` block and automatically closed (and therefore free'd) at the end of the block. To communicate with the session, we introduce a `TunnelCommand` which represents all actions that the host app can send to `connlib`. These are passed through a channel to the `suspend fn` which continuously listens for events and commands. Resolves: #9499 Related: #3959 --------- Signed-off-by: Thomas Eizinger <thomas@eizinger.io> Co-authored-by: Jamil Bou Kheir <jamilbk@users.noreply.github.com>
Firezone shell scripts
This directory contains various shell scripts used for development, testing, and deployment of the Firezone product.
Developer Setup
We lint shell scripts in CI. To get your PR to pass, you'll want to ensure your local development environment is set up to lint shell scripts:
- Install
shfmt:brew install shfmton macOS- Install shfmt from https://github.com/mvdan/sh/releases for other platforms
- Install
shellcheck:brew install shellcheckon macOSsudo apt-get install shellcheckon Ubuntu
Then just lint and format your shell scripts before you commit:
shfmt -i 4 **/*.sh
shellcheck --severity=warning **/*.sh
You can achieve this more easily by using pre-commit. See
CONTRIBUTING.
Editor setup
- Vim (here's an example using ALE)
- VSCode
Scripting tips
- Use
#!/usr/bin/env bashalong withset -euox pipefailin general for dev and test scripts. - In Docker images and other minimal envs, stick to
#!/bin/shand simplyset -eu.