Commit Graph
33 Commits
Author SHA1 Message Date
21pages 24aa2f6947 fix(logging): suppress hyper_util debug logs 2026-09-18 11:04:40 +08:00
rustdeskandClaude Opus 5 c50c1fef32 webrtc: report receive progress and ICE's disconnected hint
A peer that is killed, logged out or rebooted sends no reset over UDP, so a
session only learns of it by timing out. Nothing here acts on that; these are
the two observations a caller needs to.

`rx_progress` counts arriving fragments. A message reaches the caller only once
it is whole, so a large one - a clipboard image is the case that occurs - leaves
the receive loop with nothing to observe for as long as the transfer takes, and
a peer sending steadily looks exactly like one that died. A counter, not a
timestamp: `Instant::now()` costs an order of magnitude more per read, and
callers only compare successive samples.

`webrtc_disconnected` exposes the ICE state webrtc-rs already raises ~5s after
it stops hearing from the peer. It is deliberately not a fourth
`WebRTCConnectionState`: that enum gates send and receive readiness and session
cache admissibility, and a transient state must change neither.

TCP and WebSocket answer for neither, on purpose: this change leaves their
existing close, error and timeout behaviour exactly as it was.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019aokqJuhjvB3kijXtAg5Ns
2026-09-08 14:57:09 +08:00
rustdeskandClaude Opus 5 e6fe9c3332 move the modules only rustdesk uses out to the base crate
hbb_common is shared with the server, but `fs`, `platform`, `keyboard`,
`message.proto` and most of `config::keys` are reached only from the client.
Keeping them here means every change to them costs a submodule round-trip.

They move to the new `base` crate in the rustdesk tree. What stays is
what the server actually names: `rendezvous.proto`, the socket/stream layer, the
`Config` core, and the 32 option keys this crate reads itself. Those 32 are
re-exported from `base::config::keys`, so callers still see one set.

`IdPk` moves from message.proto to rendezvous.proto. It is register-pk handshake
business, the server is its only other user, and the field numbers are unchanged
so the wire format is identical.

`config::patch()` resolves a home directory through the shell lookup that lived
in `platform::linux`, so `find_cmd_path`, `CMD_*` and `run_cmds_trim_newline`
stay behind in a new `sh` module. `base::platform::linux` re-exports
them, leaving every existing `platform::linux::CMD_SH` path working.

backtrace, filetime, osascript, smithay-client-toolkit and winapi go with the
code that used them, so the server no longer builds a Wayland client toolkit and
a Windows API crate it never calls.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EZ49AbZJYfm8NTp5yDPMab
2026-09-08 08:53:58 +08:00
rustdeskandClaude Opus 5 470612bdfb log: quiet the two webrtc-rs sites that report the race's normal outcome
Racing WebRTC against UDP and TCP means one transport is cancelled on every
session that connects, and cancelling it walks agent_internal's candidate list
closing sockets that are already gone - one warn per candidate, plus the
peer_connection cascade behind it (ice cancelled by caller, SCTP without DTLS,
the SRTP sessions never opened). Trickle adds pingAllCandidates on every check
tick until the first pair arrives. None of it is a fault, and all of it lands
beside a connection that succeeded, where it reads as one: 90 of 386 lines in a
controlled-side log spent saying the design worked.

agent_gather stays at warn. A STUN server it could not reach is the one thing
upstream says that explains a session which never connected, and it is a
different module from the noise, so the two separate cleanly. Errors in the
quieted modules still print, and RUST_LOG overrides the whole spec for anyone
who wants the warns back.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01M54JAqUK4RynudFou89hod
2026-09-04 23:34:08 +08:00
rustdeskandClaude Opus 5 e8ec370b08 webrtc: split the send budget, make close_webrtc uncancellable, restore log retention
- send_bytes computed one deadline before acquiring the send gate and
  reused it for the write, so time queued behind another clone's message
  was charged to this message. A caller that only just lost the gate
  race got a few milliseconds to write in and then tore the whole peer
  connection down for missing them - the narrower the miss, the more
  certain the teardown. The write gets its own budget; the gate wait
  keeps the one it had, and still never closes (it never held the
  permit).

- Stream::close_webrtc awaited WebRTCStream::close, which is exactly the
  form close_detached exists to avoid: most callers sit in a select! arm
  or a future the UI can abandon, and a cancelled close is unretryable
  (is_closed is latched before the first await, so later attempts
  early-return and the handler that evicts the session never runs). It
  is now a plain fn calling close_detached - with no await point there
  is nothing to cancel. close_detached is public and carries the
  runtime-teardown guard the parent repo had written separately for its
  Drop path, so that copy goes away.

- Log retention goes back to 31 files. Raising it to 31*8 defended the
  flood case badly (a file count cannot outrun a flood; only the rate
  limits at the log sites can) while silently multiplying steady-state
  retention and disk for every ordinary install, on every platform.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ExUfAkYbq8UC9pQCiLy8TQ
2026-09-04 23:33:56 +08:00
rustdeskandClaude Opus 5 6a175cf5ee webrtc: fix the send/cache/ICE-lifetime findings; bound log retention by volume
Continues the review pass. Eight findings, each verified against the
vendored webrtc-rs (0.13 / -data 0.11 / -ice 0.13) rather than inferred:

- a mid-message dc.write() failure returned the error and left the pc
  open, so the peer kept an unterminated FRAG_MORE prefix and appended
  the next message to it - undetectable, since this framing carries no
  length or sequence number, and callers wrap sends in allow_err!. Close
  the stream when fragments are already on the wire.

- one deadline covered the connect-wait, the gate queue and every write.
  A slow ICE/DTLS completion therefore ate the budget and the write
  timed out into a pc.close() an RTT from working; and the gate arm
  closed the pc from a task that never held the permit, aborting a
  healthy sender's fragment sequence - the exact corruption the permit
  exists to prevent. Connection setup gets its own budget, and only the
  arm holding the permit tears down.

- a SESSIONS hit returned a pc built for the first caller, so a replayed
  offer could get an All-policy connection where the mediator had just
  computed Relay-only, with is_relayed() answering from the cached
  handle. It could also hand back a stream the state handler had already
  closed (it closes before it evicts). Reject both; peer_verified stays
  shared, being a fact about the certificate the entry is keyed by.

- the ICE-candidate sender lives in the on_ice_candidate handler and
  close() clears no handler, so the receiver never closed and the
  forwarder loop this API asks callers to write parked on recv() holding
  a stream clone - one leaked task plus one leaked pc per connection.
  The terminal-state handler now drops that closure. Regression test
  included (fails, by 20s timeout, with the drop removed).

- has_turn_server() accepted the RFC 7065 spelling `turn:host:port`,
  which url makes cannot-be-a-base: host_str() is None, so the server
  became a hostless "turn::3478" that still passed the scheme check.
  force_relay then built a Relay-only pc that could only time out. Parse
  host and port out of the path (IPv6 literals included), and make the
  gate require a host.

- is_relayed() read the stats report's `nominated` flag, which
  webrtc-ice sets per checklist entry and never clears, so after a pair
  switch several entries carry it and HashMap order picked the answer.
  Read the selected pair instead - which also drops a redundant stats
  round trip.

- the ICE-server parsing tests rewrote the process-global, on-disk
  `ice-servers` option while sibling loopback tests were building peer
  connections from it. Split parsing out of get_ice_servers so they can
  test it directly; the suite now passes in parallel.

- log retention is a file count, so pairing it with the new 16 MiB size
  criterion let a flooder rotate away every file predating its own
  activity. Keep enough files that ~31 days survives even at full size.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ExUfAkYbq8UC9pQCiLy8TQ
2026-09-04 23:33:56 +08:00
rustdeskandClaude Fable 5 fcc713b65b fix: cap the log file by size, and keep LogThrottle usable after poisoning
Rotating on age alone let a single day's file grow without limit, so whoever
can drive a hot log site decided how much disk this uses and no amount of
per-site throttling could bound it. Add a size criterion, which covers every
call site at once — including ones no throttle was added to.

LogThrottle: recover the guard on a poisoned lock rather than returning None.
Poisoning only means another thread panicked while holding it; the guarded
data is two counters that are still usable, and going silent for the rest of
the process is worse than a stale count. AGENTS.md permits handling lock
poisoning directly, and it forbids swallowing the error.

Keep map_or over clippy's is_none_or: that was stabilized in Rust 1.82 and CI
pins 1.75.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ExUfAkYbq8UC9pQCiLy8TQ
2026-09-04 23:33:31 +08:00
rustdeskandClaude Fable 5 bf95d52749 feat: add LogThrottle for sites whose rate a peer controls
Debug output is written to the log file, so a log site that fires per received
message lets whoever is sending decide how much a machine writes to disk.
Dropping the line instead would hide real faults, so collapse it: one line per
interval carrying the count of everything suppressed since the last one, with
the first occurrence after a quiet period always reported so an isolated fault
is not delayed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01ExUfAkYbq8UC9pQCiLy8TQ
2026-09-04 23:33:31 +08:00
fufesou c9823ad735 refact(logs): keep logs, 31 -> 90 days
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-08-31 10:00:01 +08:00
21pages 5d2acc7340 fix: improve machine_uid handling and add pk decryption fallback
- Cache machine_uid in get_uuid with retry logic for macOS
  - Fallback to pk decryption when machine_uid decryption fails
  - Add is_encrypted check to prevent duplicate encryption
  - Add get_existing_key_pair to get key pair without generating new one

Signed-off-by: 21pages <sunboeasy@gmail.com>
2026-02-14 11:11:03 +08:00
fufesou 1f5ec1219f refact(crate): libloading x11
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-01-21 11:09:44 +08:00
fufesou 6df5c2c0ce feat: linux, get_home_trusted
Signed-off-by: fufesou <linlong1266@gmail.com>
2025-12-22 23:18:35 +08:00
lc 812fc3a5cb fix too much webrtc logs 2025-11-27 20:06:19 +08:00
lc f8d1d4207d move out dummy webrtc mod 2025-11-14 01:09:08 +08:00
lc 8ae4651bc7 make webrtc-rs optional feature 2025-11-13 16:53:07 +08:00
lc 442160d704 add webrtc stream 2025-11-12 19:46:55 +08:00
fufesou ccb2214a0e refact: env logger, filter modules
Signed-off-by: fufesou <linlong1266@gmail.com>
2025-11-02 22:56:25 +08:00
fufesou 54c4d869ed refact: tls native-tls fallback rustls-tls
Signed-off-by: fufesou <linlong1266@gmail.com>
2025-10-31 12:37:23 +08:00
21pages bbc8e2f31a add mobile fallback platform verifier
Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-10-30 13:13:04 +08:00
RustDesk 84a13ad7f3 Revert "mobile wss use rustls_platform_verifier" 2025-10-30 10:27:55 +08:00
21pages bf9a79fda5 mobile wss use rustls_platform_verifier
Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-10-27 10:29:26 +08:00
RustDesk 44a7277827 time_based_rand 2025-06-10 12:04:45 +08:00
RustDesk df95f44499 more udp punch 2025-06-10 12:01:43 +08:00
RustDesk b69b097c6f kcp stream 2025-06-03 19:41:30 +08:00
RustDesk 368dc1ab56 Update Cargo.toml 2025-04-30 20:51:38 +08:00
YinMo19 6be5600b77 [enhance] split into stream.rs. 2025-04-25 11:03:16 +08:00
YinMo19 3ef70f0e4d [clean] test passed.
- clean unused.
2025-04-24 22:27:16 +08:00
YinMo19 7d5cc2ed47 [enhance] test ver. Add text for test. 2025-04-24 03:11:54 +08:00
YinMo19 d299e4909f [fix bug] fix twice enc.
- fix twice enc.
- enable proxy (temp ver.)
- rewite websocket::next.
2025-04-22 02:55:17 +08:00
YinMo19 58103659e7 [enhance] add websocket NOT a config feature. 2025-04-18 02:53:39 +08:00
YinMo19 c156d2eef7 [enhance] websocket 2025-04-17 11:42:58 +08:00
RustDesk f9a10eaa1f Update lib.rs 2025-02-15 18:41:34 +08:00
21pages 49c6b24a7a init
Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-01-20 16:06:27 +08:00