punch reply: send it to the address the registration runs on

`punch_udp_hole` resolved the rendezvous host afresh for every reply, and
since hbb_common f688d41 that is the resolver's first answer, not one a
handshake proved: with an AAAA published for a daemon that answers only on
v4, the PunchHoleSent - the WebRTC answer, the v6 address, the relay server
- went to the address the server does not listen on, and UDP loses it
without a word. The registration itself kept working over v4, so the
device looked online and could not be reached.

The mediator holds the address its registration runs on, chosen by
`start_udp` through the handshake and replaced on every rebind. The reply
goes there: no lookup, no probe, no address family the registration is
not already using. The host is resolved only where the registration's
address is not an IP, which is not the UDP mediator's case.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aokqJuhjvB3kijXtAg5Ns
This commit is contained in:
rustdesk
2026-09-18 16:09:44 +08:00
parent b21a8d3c8c
commit 0aacd3e91a

View File

@@ -1216,7 +1216,19 @@ impl RendezvousMediator {
) -> ResultType<()> { ) -> ResultType<()> {
let mut msg_out = Message::new(); let mut msg_out = Message::new();
msg_out.set_punch_hole_sent(msg_punch); msg_out.set_punch_hole_sent(msg_punch);
let (socket, addr) = new_direct_udp_for(&self.host).await?; // To the address the registration runs on, which `start_udp` proved reachable and keeps
// current across rebinds. Resolving the host again could name an address the server does
// not answer on - an AAAA beside a daemon bound to v4 - and a reply sent there is lost.
let (socket, addr) = match &self.addr {
TargetAddr::Ip(addr) => (
Arc::new(
tokio::net::UdpSocket::bind(Config::get_any_listen_addr(addr.is_ipv4()))
.await?,
),
*addr,
),
_ => new_direct_udp_for(&self.host).await?,
};
let data = msg_out.write_to_bytes()?; let data = msg_out.write_to_bytes()?;
socket.send_to(&data, addr).await?; socket.send_to(&data, addr).await?;
// The reply is out, and with it the answer and the v6 address: declined is the listen // The reply is out, and with it the answer and the v6 address: declined is the listen