The engine sent clipboard over every transport at once, so the server always saw the payload even with RTC/LAN up. Now the RTC and LAN transports report their directly-reachable peers (data-channel open / TCP connected) into a shared set, and the RTC transport records who's present from presence chirps. send() skips the SSE relay when every present peer is directly reachable — so once P2P is established the server only ever carries signaling/presence, never content. Falls back to the relay whenever a present peer isn't directly reachable, or before the direct link is up. Also drop empty-text clipboards in the sink (were surfacing as blank "unknown" feed rows). Proven by examples/prefer_direct.rs: two engines link directly on the live server; a send reaches the peer but never appears on the server bus (only presence does). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
50 lines
1.8 KiB
Rust
50 lines
1.8 KiB
Rust
//! Proves the relay carries content only until a direct path exists. A and B
|
|
//! join a room on the LIVE server and link directly (LAN/RTC). After that, A's
|
|
//! send must reach B but must NOT appear on the server bus.
|
|
//! cargo run --example prefer_direct -- <room>
|
|
//! (run an external SSE listener on the same room to confirm suppression)
|
|
|
|
use std::sync::mpsc;
|
|
use std::time::Duration;
|
|
|
|
use tethercore::{Engine, Message, MessageHandler};
|
|
|
|
struct Collector(mpsc::Sender<String>);
|
|
impl MessageHandler for Collector {
|
|
fn on_message(&self, m: Message) {
|
|
eprintln!(" B.on_message: kind={:?} text={:?} from={:?}", m.kind, m.text, m.from);
|
|
let _ = self.0.send(m.text);
|
|
}
|
|
fn on_status(&self, _c: bool) {}
|
|
}
|
|
|
|
fn main() {
|
|
let server = "https://tether.pecord.io".to_string();
|
|
let room = std::env::args().nth(1).unwrap_or_else(|| "prefer-direct-demo".into());
|
|
|
|
let (tx, rx) = mpsc::channel();
|
|
let a = Engine::new(server.clone(), room.clone(), "dev-a".into(), "macos".into(), "A".into(), "".into());
|
|
let b = Engine::new(server, room, "dev-b".into(), "ios".into(), "B".into(), "".into());
|
|
a.start(Box::new(Collector(mpsc::channel().0)));
|
|
b.start(Box::new(Collector(tx)));
|
|
|
|
// Let presence + the direct (LAN/RTC) link establish.
|
|
eprintln!("waiting ~12s for presence + direct link…");
|
|
std::thread::sleep(Duration::from_secs(12));
|
|
|
|
let secret = "DIRECT-ONLY-SECRET";
|
|
eprintln!("A sends — should go P2P, NOT via the relay");
|
|
a.send(secret.to_string());
|
|
|
|
let mut got = false;
|
|
while let Ok(t) = rx.recv_timeout(Duration::from_secs(4)) {
|
|
if t == secret { got = true; break; }
|
|
}
|
|
println!(
|
|
"{}",
|
|
if got { "✅ B received the secret over the direct path" } else { "❌ B never got the secret" }
|
|
);
|
|
a.stop();
|
|
b.stop();
|
|
}
|