mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2026-10-14 21:20:48 +08:00
fix(port): handle stale macOS wildcard guards
Co-authored-by: wonfen <eiwonfen@gmail.com>
This commit is contained in:
@@ -352,9 +352,8 @@ fn claims_overlap(left: &BindClaim, right: &BindClaim) -> bool {
|
|||||||
/// rebind it at once (measured on macOS 26). "Is anything answering?" survives that asymmetry;
|
/// rebind it at once (measured on macOS 26). "Is anything answering?" survives that asymmetry;
|
||||||
/// "can I bind?" does not.
|
/// "can I bind?" does not.
|
||||||
///
|
///
|
||||||
/// Restrictions, both deliberate: a wildcard claim can be blocked by a listener on any address, so
|
/// Restrictions, both deliberate: every concrete guard for a wildcard claim must be checked before
|
||||||
/// one refused connection cannot clear it — leaving `allow-lan` setups exposed to the same false
|
/// it can be cleared. UDP has no lingering state, so a refused UDP bind is always a live socket.
|
||||||
/// positive. UDP has no lingering state, so a refused UDP bind is always a live socket.
|
|
||||||
fn nothing_is_serving(claim: &BindClaim) -> bool {
|
fn nothing_is_serving(claim: &BindClaim) -> bool {
|
||||||
const ANSWER_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(200);
|
const ANSWER_TIMEOUT: std::time::Duration = std::time::Duration::from_millis(200);
|
||||||
|
|
||||||
@@ -477,12 +476,17 @@ fn bind_claim(claim: &BindClaim) -> io::Result<Vec<Socket>> {
|
|||||||
}
|
}
|
||||||
guard_addresses.sort_unstable();
|
guard_addresses.sort_unstable();
|
||||||
guard_addresses.dedup();
|
guard_addresses.dedup();
|
||||||
|
let mut stale_guard = false;
|
||||||
for address in guard_addresses {
|
for address in guard_addresses {
|
||||||
match bind_socket(&BindClaim::new(claim.name, address, claim.port, claim.transport)) {
|
let guard_claim = BindClaim::new(claim.name, address, claim.port, claim.transport);
|
||||||
|
match bind_socket(&guard_claim) {
|
||||||
Ok(socket) => sockets.push(socket),
|
Ok(socket) => sockets.push(socket),
|
||||||
// Only a conflict proves the port is taken; a vanished guard address proves nothing.
|
// Only a conflict proves the port is taken; a vanished guard address proves nothing.
|
||||||
Err(error) if is_bind_conflict(&error) => {
|
Err(error) if is_bind_conflict(&error) => {
|
||||||
// The caller only sees the claim, so name the address that actually lost.
|
if nothing_is_serving(&guard_claim) {
|
||||||
|
stale_guard = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
logging!(
|
logging!(
|
||||||
warn,
|
warn,
|
||||||
LogType::Network,
|
LogType::Network,
|
||||||
@@ -497,6 +501,9 @@ fn bind_claim(claim: &BindClaim) -> io::Result<Vec<Socket>> {
|
|||||||
Err(_) => {}
|
Err(_) => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if stale_guard {
|
||||||
|
return Ok(sockets);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let socket = bind_socket(claim)?;
|
let socket = bind_socket(claim)?;
|
||||||
|
|||||||
Reference in New Issue
Block a user