Wire the Discoverable presence posture to n0 DNS publish/lookup, the last
core piece of W7 (friends-first contacts). When a friend moves networks and
their saved address goes stale, they flip Discoverable to publish their
current address; everyone else resolves it by node id. Asymmetric: only the
mover publishes.
- src/discovery.rs (pure seam, +3 tests): lookup_plan(network_mode, want_publish)
-> LookupPlan { resolver, publisher }. Relay-capable modes always resolve and
publish only when Discoverable; DirectOnly (the explicit no-server posture)
gets neither, overriding the toggle. DISCOVERY_TIMEBOX = 30 min.
- apply_discovery (core edge): clears + reinstalls the bound endpoint's
address-lookup services at runtime (no endpoint rebuild). memory-lookup always;
n0 PkarrResolver + DnsAddressLookup when resolver; PkarrPublisher when publisher.
Toggling publish off drops the publisher (republish task ends; TTL-30s record
expires). build_net_stack now binds uniformly with Minimal + per-mode relay and
installs discovery via apply_discovery (drops the per-mode presets::N0 build).
- Toggle + time-box: SetPresenceMode re-applies discovery and arms/cancels a
discovery_deadline; a select! branch fires at the deadline -> revert to Normal,
stop publishing, and emit UiEvent::PresenceModeReverted so the GUI mirrors and
persists it. Re-selecting Discoverable restarts the clock.
Decisions (user, 2026-06-16): 30-min auto-revert (not sticky); resolver always
on in relay-capable modes so a stationary friend in Normal can look up a mover.
266 lib tests green, clippy clean (--all-targets). Runtime smoke-tested: the new
Minimal+apply_discovery path binds and runs with no error/panic for both Normal
and Discoverable startup postures. Cross-network publish->lookup and the live
30-min revert still want a 2-machine field test (P7).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
64 lines
1.9 KiB
Rust
64 lines
1.9 KiB
Rust
pub mod audio;
|
|
pub mod codec;
|
|
pub mod dsp;
|
|
pub mod network;
|
|
pub mod core;
|
|
pub mod app;
|
|
pub mod config;
|
|
pub mod identity;
|
|
pub mod friends;
|
|
pub mod presence;
|
|
pub mod presence_net;
|
|
pub mod theme;
|
|
pub mod notify;
|
|
pub mod screenshare;
|
|
pub mod sanitize;
|
|
pub mod avatar;
|
|
pub mod recents;
|
|
pub mod discovery;
|
|
|
|
use std::path::PathBuf;
|
|
use std::sync::OnceLock;
|
|
|
|
/// Resolves the log file path once: `$XDG_STATE_HOME/peerspeak/peerspeak.log`
|
|
/// (via `dirs::state_dir`), falling back to the system temp dir. Computed lazily
|
|
/// so we never hardcode a per-user path.
|
|
fn log_path() -> &'static PathBuf {
|
|
static LOG_PATH: OnceLock<PathBuf> = OnceLock::new();
|
|
LOG_PATH.get_or_init(|| {
|
|
let mut dir = dirs::state_dir()
|
|
.or_else(dirs::cache_dir)
|
|
.unwrap_or_else(std::env::temp_dir);
|
|
dir.push("peerspeak");
|
|
let _ = std::fs::create_dir_all(&dir);
|
|
dir.push("peerspeak.log");
|
|
dir
|
|
})
|
|
}
|
|
|
|
/// The resolved log file path. Exposed so diagnostic tools (e.g. the audio
|
|
/// probe) can tail the same log the app writes to.
|
|
pub fn log_file_path() -> PathBuf {
|
|
log_path().clone()
|
|
}
|
|
|
|
pub fn log_msg(msg: &str) {
|
|
// Format the whole line into one buffer first, then emit it with a single
|
|
// `write_all`. The file is opened with `O_APPEND`, so a lone `write()` is
|
|
// atomic w.r.t. concurrent writers; building the line up front avoids the
|
|
// multi-syscall `writeln!` path that would let threads interleave fragments.
|
|
let line = match std::time::SystemTime::now().duration_since(std::time::UNIX_EPOCH) {
|
|
Ok(time) => format!("[{}.{:03}] {}\n", time.as_secs(), time.subsec_millis(), msg),
|
|
Err(_) => format!("{}\n", msg),
|
|
};
|
|
if let Ok(mut file) = std::fs::OpenOptions::new()
|
|
.create(true)
|
|
.append(true)
|
|
.open(log_path())
|
|
{
|
|
use std::io::Write;
|
|
let _ = file.write_all(line.as_bytes());
|
|
}
|
|
}
|
|
|