fix: premature socket teardown on CLOSE + duplicate CLOSE echo
build / build (push) Has been cancelled
build / build (push) Has been cancelled
Two bugs when upstream closes: 1. Data loss: gatuna received CLOSE from gatunad and immediately RST'd the socket to curl while the drain pump still had queued payloads in _deliverChannel. Fix: OnRemoteClose() completes the channel writer and cancels the read pump, but lets the drain pump finish naturally. Drain pump no longer takes _cts.Token — it stops on channel completion and closes the socket gracefully (FIN, OS flushes in background). 2. Duplicate CLOSE: gatuna echoed CLOSE back to gatunad (server already knows — it initiated). SendClose() now guarded by _closeSent flag. OnRemoteClose() never sends CLOSE at all. Server-side: remove session from store before sending CLOSE so the retransmit timer stops before CLOSE is queued. Only log CLOSE if the session actually existed (dedup).
This commit is contained in:
+3
-2
@@ -224,8 +224,9 @@ async fn handle_frame(
|
||||
}
|
||||
}
|
||||
Frame::Close { session_id, reason: _ } => {
|
||||
info!("CLOSE session {session_id} from {src}");
|
||||
store.lock().expect("store poisoned").remove(&session_id);
|
||||
if store.lock().expect("store poisoned").remove(&session_id).is_some() {
|
||||
info!("CLOSE session {session_id} from {src}");
|
||||
}
|
||||
}
|
||||
Frame::Ping { nonce } => {
|
||||
let pong = Frame::Pong { nonce };
|
||||
|
||||
@@ -275,12 +275,12 @@ pub fn spawn_pump(
|
||||
}
|
||||
|
||||
if should_close {
|
||||
store.lock().expect("store poisoned").remove(&session_id);
|
||||
let close = Frame::Close {
|
||||
session_id,
|
||||
reason: Some(REASON_MAX_RETRIES),
|
||||
};
|
||||
let _ = tx.try_send((peer_mac, close.encode()));
|
||||
store.lock().expect("store poisoned").remove(&session_id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -330,8 +330,8 @@ pub fn spawn_pump(
|
||||
break;
|
||||
}
|
||||
}
|
||||
store.lock().expect("store poisoned").remove(&session_id);
|
||||
let close = Frame::Close { session_id, reason: None };
|
||||
let _ = tx.send((peer_mac, close.encode())).await;
|
||||
store.lock().expect("store poisoned").remove(&session_id);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user