mirror of
https://github.com/jmcorgan/fips.git
synced 2026-10-29 23:27:37 +00:00
macOS now peers over BLE with Linux, Android and other Macs when the daemon runs in a login session with Bluetooth permission. CoreBluetooth is delegate-driven and moves channel bytes through Foundation streams, the same command-out, callback-in shape as the Android embedder's radio, so the backend plays the embedder's part in process rather than implementing BleIo: MacRadio drives CoreBluetooth from a private serial dispatch queue (no main run loop), installs a fresh bridge into its slot each time Bluetooth comes up, and pumps each CBL2CAPChannel with blocking stream I/O on two threads. io_radio gains what that needs: a blocking delivery for a reader on its own thread, since a dropped chunk of a byte stream breaks its framing, and a RadioIo that keeps its radio alive across Bluetooth toggles. macOS assigns the listener PSM and cannot advertise it, so a Mac serves it over GATT (Apple's L2CAP PSM characteristic, specified in psm.rs) and reads a peer's there when its advert carried none. Linux and Android cannot dial a Mac; the Mac's own dial forms the link, which the link arbitration admits. CoreBluetooth hides link addresses, so a peer's identifier is hashed into a stable locally administered BleAddr, and a configured hci0/AA:... peer cannot be dialled from a Mac. The fips binary embeds an Info.plist with a Bluetooth usage description, without which CoreBluetooth kills the process. The Mac has one radio, so more than one ble instance is a config error there. Platform-neutral parts (dial PSM decision, address mapping, advert throttle, stream pumps) are tested on every host; two ignored tests exercise real hardware.
80 lines
3.2 KiB
Rust
80 lines
3.2 KiB
Rust
use std::process::Command;
|
|
|
|
fn main() {
|
|
// Git commit hash (short)
|
|
let git_hash = Command::new("git")
|
|
.args(["rev-parse", "--short=10", "HEAD"])
|
|
.output()
|
|
.ok()
|
|
.filter(|o| o.status.success())
|
|
.map(|o| String::from_utf8_lossy(&o.stdout).trim().to_string())
|
|
.unwrap_or_default();
|
|
println!("cargo:rustc-env=FIPS_GIT_HASH={git_hash}");
|
|
|
|
// Dirty working tree
|
|
let dirty = Command::new("git")
|
|
.args(["status", "--porcelain"])
|
|
.output()
|
|
.ok()
|
|
.filter(|o| o.status.success())
|
|
.map(|o| !o.stdout.is_empty())
|
|
.unwrap_or(false);
|
|
if dirty {
|
|
println!("cargo:rustc-env=FIPS_GIT_DIRTY=-dirty");
|
|
} else {
|
|
println!("cargo:rustc-env=FIPS_GIT_DIRTY=");
|
|
}
|
|
|
|
// Build target triple
|
|
if let Ok(target) = std::env::var("TARGET") {
|
|
println!("cargo:rustc-env=FIPS_TARGET={target}");
|
|
}
|
|
|
|
// Rebuild when commits change
|
|
println!("cargo:rerun-if-changed=.git/HEAD");
|
|
println!("cargo:rerun-if-changed=.git/refs/");
|
|
|
|
// Support reproducible builds (Debian packaging)
|
|
println!("cargo:rerun-if-env-changed=SOURCE_DATE_EPOCH");
|
|
|
|
// bluer/BlueZ is glibc-linux only: musl cross-compiles (OpenWrt) can't
|
|
// satisfy libdbus-sys's pkg-config cross-compile requirement, and musl
|
|
// router targets don't run BlueZ by default anyway.
|
|
println!("cargo:rustc-check-cfg=cfg(bluer_available)");
|
|
let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default();
|
|
let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default();
|
|
let bluer_available = target_os == "linux" && target_env != "musl";
|
|
if bluer_available {
|
|
println!("cargo:rustc-cfg=bluer_available");
|
|
}
|
|
|
|
// Whether the BLE transport is compiled at all.
|
|
//
|
|
// This is the set of platforms that have a concrete `BleIo` backend, not
|
|
// the set that could plausibly have one. A platform listed here with no
|
|
// backend behind it does not get "BLE, degraded" — it gets an in-memory
|
|
// transport that starts, reports itself up and never peers, with no error
|
|
// anywhere. Add a platform here only in the same change that adds its
|
|
// backend; `transport::ble` carries a compile-time tripwire that refuses
|
|
// a build where the two disagree.
|
|
println!("cargo:rustc-check-cfg=cfg(ble_available)");
|
|
if bluer_available || target_os == "android" || target_os == "macos" {
|
|
println!("cargo:rustc-cfg=ble_available");
|
|
}
|
|
|
|
// CoreBluetooth is privacy-gated (TCC). A process that touches it without
|
|
// an `NSBluetoothAlwaysUsageDescription` in its Info.plist is killed on
|
|
// the spot, and a bare executable has no bundle to carry one — so embed
|
|
// the plist in the binary's `__TEXT,__info_plist` section, where the OS
|
|
// looks for an unbundled tool's.
|
|
if target_os == "macos" {
|
|
let plist = std::path::Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap())
|
|
.join("packaging/macos/Info.plist");
|
|
println!("cargo:rerun-if-changed={}", plist.display());
|
|
println!(
|
|
"cargo:rustc-link-arg-bin=fips=-Wl,-sectcreate,__TEXT,__info_plist,{}",
|
|
plist.display()
|
|
);
|
|
}
|
|
}
|