Files
fips/Cargo.toml
Arjen 769c59fc4f feat(usb): the USB host role, switching phones into accessory mode
With `transports.usb.host: true` and the `usb-host` feature, the node
watches the bus over nusb, switches anything that looks like a phone into
Android Open Accessory mode, and links with the accessory it comes back
as. The phone needs only an app whose accessory filter matches the
identity every FIPS host announces (`FIPS` / `fips-link`).

Only devices exposing an MTP/PTP or adb interface are asked; an Android
phone exposes one in every USB mode, "No data transfer" included, and
keyboards, hubs, disks and serial adapters do not. A device that does not
answer the AOA protocol query is left alone until it is next plugged in.

Bulk IN keeps four 16 KiB reads queued. Bulk OUT follows a transfer that
ends on a packet boundary with a zero-length packet, unless it fills the
phone's 16 KiB read, which completes without one and would otherwise see
an empty read.

Checked against a Galaxy A52s from macOS with an echoing accessory app
(`aoa_echo_against_a_phone`, ignored by default): every size around the
packet and transfer boundaries round-trips, and a pipelined stream moves
17.8 MB/s each way, bound by the app's single-threaded echo.
2026-10-23 14:41:11 -03:00

229 lines
9.4 KiB
TOML

[package]
# Published on crates.io as `fips-mesh`, since `fips` there is an unrelated
# crate. Only the package name differs: the library is still `fips` (see
# [lib]), every binary keeps its name, and the Debian package is pinned to
# `fips` in [package.metadata.deb], so no installed file or artifact changes.
name = "fips-mesh"
version = "0.6.0-dev"
edition = "2024"
description = "A distributed, decentralized network routing protocol for mesh nodes connecting over arbitrary transports"
license = "MIT"
authors = ["Johnathan Corgan <johnathan@corganlabs.com>"]
repository = "https://github.com/jmcorgan/fips"
homepage = "https://fips.network"
readme = "README.md"
keywords = ["mesh", "p2p", "decentralized", "overlay-network", "nostr"]
categories = ["network-programming", "command-line-utilities", "cryptography"]
# What the published crate carries: the source and what builds and tests it.
# Docs, CI and the test harness stay in the repository. Patterns are anchored
# with `/`, since a bare name matches at any depth. `packaging/` ships because
# lib tests read it (src/packaging_tests.rs at run time, src/config/mod.rs by
# `include_str!`).
include = [
"/src/**",
"/build.rs",
"/benches/**",
"/README.md",
"/LICENSE",
"/CHANGELOG.md",
"/packaging/**",
]
[lib]
name = "fips"
path = "src/lib.rs"
# The root package stays first, and its version line stays the first `version`
# key in this file: the packaging scripts and workflows read the release
# version from it. `default-members` makes the bare `cargo build`, `cargo
# clippy` and `cargo test` cover the core crate too; without it they cover the
# root package only.
[workspace]
members = [".", "core"]
default-members = [".", "core"]
# fips-core's rekey simulations, explorer and model runs are CPU-bound and run
# more than twice as fast optimized. Only the core is optimized; overflow
# checks and debug assertions stay on, as in every dev and test build.
[profile.dev.package.fips-core]
opt-level = 2
[features]
default = []
# Tick-body profiler (`src/instr`). Off by default: enabling it edits 26 call
# sites in the rx loop's hot tick arm, and only a compile-time gate makes the
# default build's neutrality a property of the generated code rather than of a
# runtime check. Build with `--features profiling` for a measurement run.
profiling = []
# USB host role for the USB transport (`transports.usb.host`): switch phones
# into Android Open Accessory mode and link with them, over `nusb`. Off by
# default; a build that only ever is the accessory (an app on a phone that is
# never USB host) does not need it.
usb-host = ["dep:nusb"]
[dependencies]
ratatui = "0.30"
secp256k1 = { version = "0.30", features = ["rand", "global-context"] }
# `zeroize` clears SHA-256 states on drop. No root code hashes a secret now;
# `fips-core` enables the feature too, so it is on in every root build.
sha2 = { version = "0.11", features = ["zeroize"] }
ring = "0.17"
zeroize = { version = "1.9", features = ["zeroize_derive"] }
rand = "0.10.1"
crossbeam-channel = "0.5"
thiserror = "2.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9"
dirs = "6.0"
hex = "0.4"
clap = { version = "4.6", features = ["derive"] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
tokio = { version = "1", features = ["rt", "macros", "signal", "sync", "net", "time", "process", "io-util"] }
futures = "0.3"
nusb = { version = "0.2", optional = true, features = ["tokio"] }
simple-dns = "0.11.2"
# 0.20 picks up socket-pktinfo 0.4.1, the first release that builds on
# FreeBSD (IP_RECVDSTADDR/IP_RECVIF instead of Linux-style IP_PKTINFO).
mdns-sd = "0.20"
# Interface addresses with their prefix lengths, on Linux, macOS, FreeBSD and
# Windows. `link-local` keeps 169.254.0.0/16 and fe80::/10 addresses in the
# read; without it a link-local LAN peer would be judged off-link.
if-addrs = { version = "0.15", features = ["link-local"] }
socket2 = { version = "0.6.2", features = ["all"] }
tokio-socks = "0.5"
portable-atomic = { version = "1", features = ["std"] }
nostr = { version = "0.44", features = ["std", "nip59"] }
nostr-sdk = "0.44"
arc-swap = "1"
fips-core = { path = "core", features = ["ring"] }
[target.'cfg(unix)'.dependencies]
tun = { version = "0.8.7", features = ["async"] }
libc = "0.2"
[target.'cfg(target_os = "linux")'.dependencies]
rtnetlink = "0.21.0"
rustables = "0.8.7"
procfs = { version = "0.18", default-features = false }
# Conntrack dump for kernels without /proc/net/nf_conntrack. 0.3 is the
# release on netlink-packet-core 0.8, the version rtnetlink 0.21 uses.
netlink-packet-netfilter = "0.3"
netlink-packet-core = "0.8"
netlink-sys = "0.8"
# bluer/BlueZ needs glibc — see build.rs `bluer_available` cfg gate.
[target.'cfg(all(target_os = "linux", not(target_env = "musl")))'.dependencies]
bluer = { version = "0.17", features = ["bluetoothd", "l2cap"] }
# CoreBluetooth BLE backend (src/transport/ble/io_macos).
[target.'cfg(target_os = "macos")'.dependencies]
objc2 = "0.6"
objc2-foundation = { version = "0.3", default-features = false, features = ["std", "NSArray", "NSData", "NSDictionary", "NSEnumerator", "NSError", "NSObject", "NSStream", "NSString", "NSUUID", "NSValue"] }
objc2-core-bluetooth = "0.3"
dispatch2 = "0.3"
[target.'cfg(windows)'.dependencies]
wintun = "0.5"
windows-service = "0.8.1"
# For WSAIoctl(SIO_UDP_CONNRESET) on the UDP socket. The version socket2 and
# tokio already pull in, so the lock file gains no package.
windows-sys = { version = "0.61", features = ["Win32_Networking_WinSock", "Win32_System_IO"] }
[package.metadata.deb]
# cargo-deb otherwise names the package after the crate, `fips-mesh`.
name = "fips"
maintainer = "Johnathan Corgan <johnathan@corganlabs.com>"
copyright = "2026 Johnathan Corgan"
license-file = ["LICENSE", "0"]
section = "net"
priority = "optional"
# "$auto" runs dpkg-shlibdeps over each packaged binary and derives the real
# dependencies, including the libc6 version floor. Written by hand this field
# said only "libc6", which no glibc fails to satisfy, so a package whose
# binaries needed 2.39 installed happily on a system with 2.35 and the daemon
# then could not start. Deriving it also picks up a libdbus floor the hand
# written list lacked, and re-derives per architecture, which matters because
# arm64 links libdbus in all four binaries where amd64 links it in one.
# libgcc-s1 is written by hand beside "$auto" because cargo-deb removes every
# libgcc entry from what it derives, on the grounds that every system has one.
# testing/check-deb-depends.sh runs dpkg-shlibdeps on every build and fails if
# this floor differs from the derived one, so it cannot fall behind or run
# ahead of what the binaries need.
# systemd stays by hand: nothing links it, so nothing can derive it.
depends = "$auto, libgcc-s1 (>= 4.2), systemd"
# nftables is recommended, not required: only the opt-in fips-firewall.service runs nft.
recommends = "bluez, nftables"
extended-description = """\
FIPS is a distributed, decentralized network routing protocol for mesh \
nodes connecting over arbitrary transports including UDP, TCP, Ethernet, \
Tor, and Bluetooth (BLE). It provides encrypted peer-to-peer connectivity \
with automatic key management, TUN-based virtual networking, and .fips DNS \
resolution."""
maintainer-scripts = "packaging/debian/"
assets = [
["target/release/fips", "/usr/bin/", "755"],
["target/release/fipsctl", "/usr/bin/", "755"],
["target/release/fipstop", "/usr/bin/", "755"],
["packaging/common/fips.yaml", "/usr/share/fips/fips.yaml.example", "644"],
["packaging/common/hosts", "/etc/fips/hosts", "644"],
["packaging/common/fips.nft", "/etc/fips/fips.nft", "644"],
["packaging/debian/fips.service", "/lib/systemd/system/fips.service", "644"],
["packaging/debian/fips-dns.service", "/lib/systemd/system/fips-dns.service", "644"],
["packaging/debian/fips-firewall.service", "/lib/systemd/system/fips-firewall.service", "644"],
["packaging/common/fips-dns-setup", "/usr/lib/fips/fips-dns-setup", "755"],
["packaging/common/fips-dns-teardown", "/usr/lib/fips/fips-dns-teardown", "755"],
["packaging/debian/fips.tmpfiles", "/usr/lib/tmpfiles.d/fips.conf", "644"],
["target/release/fips-gateway", "/usr/bin/", "755"],
["packaging/debian/fips-gateway.service", "/lib/systemd/system/fips-gateway.service", "644"],
["docs/design/fips-security.md", "/usr/share/doc/fips/fips-security.md", "644"],
]
conf-files = ["/etc/fips/hosts", "/etc/fips/fips.nft"]
[dev-dependencies]
# The protocol modules' test hooks, which this crate's tests call. Enabled
# here only, so they are compiled into a build that includes tests, examples
# or benches, where dev-dependency features apply, and into no other build.
fips-core = { path = "core", features = ["test-hooks"] }
tempfile = "3.15"
criterion = { version = "0.8.2", features = ["html_reports"] }
tokio = { version = "1", features = ["test-util"] }
[[bin]]
name = "fips"
path = "src/bin/fips.rs"
[[bin]]
name = "fipsctl"
path = "src/bin/fipsctl.rs"
[[bin]]
name = "fips-gateway"
path = "src/bin/fips-gateway.rs"
[[bin]]
name = "fipstop"
path = "src/bin/fipstop/main.rs"
[[bench]]
name = "routing_next_hop"
path = "benches/routing_next_hop.rs"
harness = false
[[bench]]
name = "transport_addr_clone"
path = "benches/transport_addr_clone.rs"
harness = false
[[bench]]
name = "coord_cache"
path = "benches/coord_cache.rs"
harness = false
[[bench]]
name = "noise_aead"
path = "benches/noise_aead.rs"
harness = false