fix: signal graceful leave at the transport so a disconnect doesn't show "reconnecting"
Field-testing the reconnect fix surfaced a follow-on bug: clicking Disconnect (or quitting) showed the peer as yellow "Reconnecting" on the other end instead of leaving cleanly. Logs showed the remote saw NeighborDown first and the gossip `Leave` arrived ~15s later (broadcast then router torn down ~450ms after, so NeighborDown — now meaning "reconnecting" — beats the slow, swarm-routed Leave). Fix: make graceful leave a prompt, reliable TRANSPORT signal instead of relying on gossip. On leave/quit, IrohTransport::leave() explicitly closes each live connection with a distinguished goodbye code (GOODBYE_CODE) and aborts all supervisors (so none linger redialing the about-to-close endpoint). The remote's supervisor inspects the close reason: an application close with our goodbye code => emit the new ConnEvent::Left (evict now); a timeout/reset/other code => transient drop, reconnect as before. core handles ConnEvent::Left exactly like a PeerLeft (cancel grace timer, disconnect, drop jitter, UI remove). ActiveSession now holds the transport and calls leave() before shutting the router down. Tracks the live connection per peer in Shared.live_conns (inserted on link up, removed on drop) so leave() can close them. The gossip Leave path stays as a harmless backup. New test dialer_reports_left_on_graceful_close: a close with the goodbye code reports Left and does NOT reconnect (mirror of the code-0 transient-drop test). clippy clean, 4 transport tests pass. NOT yet field-verified. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -54,6 +54,12 @@ pub enum ConnEvent {
|
||||
Connecting(EndpointId),
|
||||
/// A live audio link is established and carrying datagrams.
|
||||
Connected(EndpointId),
|
||||
/// The peer closed its link *gracefully* (an explicit QUIC application close,
|
||||
/// which only happens on an intentional leave/quit — a network drop yields a
|
||||
/// timeout, not this). Distinct from a transient drop so the core can evict
|
||||
/// the peer immediately instead of waiting out the reconnect grace window.
|
||||
/// This is the prompt, reliable leave signal; the gossip `Leave` is too slow.
|
||||
Left(EndpointId),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
|
||||
Reference in New Issue
Block a user