mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-15 17:01:06 +03:00
Compare commits
6 Commits
fix-16226-
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
851d2df88c | ||
|
|
be757de462 | ||
|
|
a437eb9bc6 | ||
|
|
39d4f1854b | ||
|
|
bd028ad350 | ||
|
|
b48fe17b52 |
@@ -780,6 +780,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("RustDesk could not load a GStreamer component needed for screen capture ({})", "RustDesk non è riuscito a caricare un componente GStreamer necessario per l'acquisizione dello schermo ({})"),
|
||||
("Relay fallback delay in seconds", "Ritardo fallback relay (secondi)"),
|
||||
("relay-fallback-delay-tip", "Quanto tempo una connessione relay già attiva attende la connessione WebRTC diretta prima di essere usata. Aumentalo per dare a una connessione diretta lenta più tempo per funzionare; diminuiscilo per passare prima al relay sulle reti in cui non è possibile effettuare una connessione diretta. Lascia vuoto per il valore predefinito di 2,5 secondi."),
|
||||
("To start a voice call, enable \"Audio capture\" on the \"Screen share\" page.", "")
|
||||
("To start a voice call, enable \"Audio capture\" on the \"Screen share\" page.", "Per avviare una chiamata vocale, attiva nella pagina 'Condivisione schermo' la voce 'Cattura audio'.")
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -780,6 +780,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("RustDesk could not load a GStreamer component needed for screen capture ({})", "RustDesk가 화면 캡처에 필요한 GStreamer 구성 요소를 불러오지 못했습니다 ({})"),
|
||||
("Relay fallback delay in seconds", "릴레이 대체 작동 지연 시간 (초)"),
|
||||
("relay-fallback-delay-tip", "이미 연결된 중계 연결이 직접 WebRTC 연결을 얼마나 기다린 후 대신 사용되는지입니다. 값을 늘리면 느린 직접 연결에 더 많은 시간을 주고, 줄이면 직접 연결이 불가능한 네트워크에서 더 빨리 중계로 전환합니다. 비워 두면 기본값 2.5초가 사용됩니다."),
|
||||
("To start a voice call, enable \"Audio capture\" on the \"Screen share\" page.", "")
|
||||
("To start a voice call, enable \"Audio capture\" on the \"Screen share\" page.", "음성 통화를 시작하려면 '화면 공유' 페이지에서 '오디오 캡처'를 사용함으로 하세요.")
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -730,7 +730,7 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("preset-password-in-use-tip", "Установленный пароль сейчас используется."),
|
||||
("Enable privacy mode", "Использовать режим конфиденциальности"),
|
||||
("allow-remote-toolbar-docking-any-edge", "Разрешать прикрепление удалённой панели инструментов к любому краю окна"),
|
||||
("API Token", "API-токен"),
|
||||
("API Token", "Токен API"),
|
||||
("Deploy", "Развернуть"),
|
||||
("Custom ID (optional)", "Пользовательский ID (необязательно)"),
|
||||
("server_requires_deployment_tip", "Сервер требует явного развёртывания этого устройства. Развернуть сейчас?"),
|
||||
@@ -748,23 +748,23 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("Show on the minimized toolbar", "Показывать на свёрнутой панели инструментов"),
|
||||
("All monitors", "Все мониторы"),
|
||||
("#{} monitor", "Монитор {}"),
|
||||
("conn-e2ee-unavailable-tip", "Не удалось проверить сквозное шифрование.\nУдаленное устройство, возможно, еще настраивается. Повторите попытку позже.\nЕсли это повторяется, сервер может быть ненадежным.\nВсе равно продолжить?"),
|
||||
("conn-e2ee-unavailable-tip", "Невозможно проверить сквозное шифрование.\nУдалённое устройство, возможно, ещё настраивается. Повторите попытку позже.\nЕсли это повторяется, сервер может быть ненадёжным.\nВсё равно продолжить?"),
|
||||
("ID whitelisting", "Список разрешённых ID"),
|
||||
("Use ID whitelisting", "Использовать белый список ID"),
|
||||
("id_whitelist_tip", "Только ID из белого списка могут получить доступ к моему устройству."),
|
||||
("id_whitelist_wildcard_tip", "Поддерживаются подстановочные знаки: '*' соответствует любому количеству символов, '?' — ровно одному символу"),
|
||||
("id_whitelist_wildcard_tip", "Поддерживаются подстановочные знаки: \"*\" соответствует любому количеству символов, \"?\" — ровно одному символу"),
|
||||
("Invalid ID", "Неправильный ID"),
|
||||
("Your ID is blocked by the peer", "Ваш ID заблокирован удалённым устройством"),
|
||||
("Your ip is blocked by the peer", "Ваш IP-адрес заблокирован удалённым устройством"),
|
||||
("id_whitelist_caveat_tip", "ID сообщается подключающимся клиентом. Белый список уменьшает поверхность атаки и не заменяет пароль или 2FA"),
|
||||
("whitelist_cidr_tip", "Поддерживается нотация CIDR, например 192.168.1.0/24"),
|
||||
("whitelist_cidr_tip", "Поддерживается нотация CIDR, например: 192.168.1.0/24"),
|
||||
("Continue", "Продолжить"),
|
||||
("Browser didn't open? Use the url below to sign in.", "Браузер не открылся? Используйте ссылку ниже для входа."),
|
||||
("Lock canvas", "Заблокировать холст"),
|
||||
("Sync clipboard between sessions", "Синхронизировать буфер обмена между сеансами"),
|
||||
("sync-clipboard-between-sessions-tip", "Текст или изображения, скопированные в одном удалённом сеансе, также отправляются в буфер обмена других подключённых сеансов."),
|
||||
("terminal-clipboard-write-tip", ""),
|
||||
("Allow terminal apps to copy to clipboard", ""),
|
||||
("terminal-clipboard-write-tip", "Приложение в терминале хочет скопировать текст в буфер обмена этого устройства. Если соответствующее разрешение предоставлено, оно применяется к приложениям в терминале во всех соединениях, пока вы не отключите его в настройках. Ручные копирование и вставка не затрагиваются."),
|
||||
("Allow terminal apps to copy to clipboard", "Разрешить приложениям в терминале копирование в буфер обмена"),
|
||||
("Enable", "Включить"),
|
||||
("Reuse one connection for port forwarding", "Использовать одно подключение для перенаправления портов"),
|
||||
("port-forward-mux-tip", "Передавать все соединения одного перенаправления портов через одно подключение к удалённому устройству вместо повторного подключения и входа для каждого из них."),
|
||||
@@ -780,6 +780,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
|
||||
("RustDesk could not load a GStreamer component needed for screen capture ({})", "RustDesk не удалось загрузить компонент GStreamer, необходимый для захвата экрана ({})"),
|
||||
("Relay fallback delay in seconds", "Задержка перед переходом на ретранслятор в секундах"),
|
||||
("relay-fallback-delay-tip", "Сколько времени уже установленное соединение через ретранслятор ждёт прямое соединение WebRTC, прежде чем будет использовано вместо него. Увеличьте, чтобы дать медленному прямому соединению больше времени; уменьшите, чтобы быстрее переходить на ретранслятор в сетях, где прямое соединение невозможно. Оставьте пустым для значения по умолчанию 2.5 секунды."),
|
||||
("To start a voice call, enable \"Audio capture\" on the \"Screen share\" page.", "")
|
||||
("To start a voice call, enable \"Audio capture\" on the \"Screen share\" page.", "Чтобы начать голосовой вызов, включите \"Захват аудио\" на странице \"Демонстрация экрана\" настроек.")
|
||||
].iter().cloned().collect();
|
||||
}
|
||||
|
||||
@@ -542,6 +542,26 @@ extern "C"
|
||||
SHAddToRecentDocs(SHARD_PATHW, path);
|
||||
}
|
||||
|
||||
// Hyper-V Enhanced Session names do not have the usual "rdp" prefix.
|
||||
static bool is_rdp_session_by_protocol(DWORD session_id)
|
||||
{
|
||||
LPSTR buffer = nullptr;
|
||||
DWORD bytes = 0;
|
||||
if (!WTSQuerySessionInformationA(
|
||||
WTS_CURRENT_SERVER_HANDLE, session_id, WTSClientProtocolType, &buffer, &bytes)) {
|
||||
flog("Failed to query protocol for session %lu: Windows error %lu\n",
|
||||
session_id, GetLastError());
|
||||
return false;
|
||||
}
|
||||
std::unique_ptr<char, decltype(&WTSFreeMemory)> protocol_info(buffer, WTSFreeMemory);
|
||||
if (!buffer || bytes < sizeof(USHORT)) {
|
||||
flog("Failed to query protocol for session %lu: Windows error %lu\n",
|
||||
session_id, static_cast<DWORD>(ERROR_INVALID_DATA));
|
||||
return false;
|
||||
}
|
||||
return *reinterpret_cast<const USHORT *>(buffer) == WTS_PROTOCOL_TYPE_RDP;
|
||||
}
|
||||
|
||||
DWORD get_current_session(BOOL include_rdp)
|
||||
{
|
||||
auto rdp_or_console = WTSGetActiveConsoleSessionId();
|
||||
@@ -573,6 +593,10 @@ extern "C"
|
||||
{
|
||||
rdp_or_console = info.SessionId;
|
||||
}
|
||||
else if (is_rdp_session_by_protocol(info.SessionId))
|
||||
{
|
||||
rdp_or_console = info.SessionId;
|
||||
}
|
||||
}
|
||||
}
|
||||
WTSFreeMemory(pInfos);
|
||||
@@ -666,6 +690,9 @@ extern "C"
|
||||
else if (include_rdp && !strnicmp(info.pWinStationName, ica, nica)) {
|
||||
sessionIds.push_back(std::wstring(L"ICA:") + std::to_wstring(info.SessionId));
|
||||
}
|
||||
else if (include_rdp && is_rdp_session_by_protocol(info.SessionId)) {
|
||||
sessionIds.push_back(std::wstring(L"RDP:") + std::to_wstring(info.SessionId));
|
||||
}
|
||||
}
|
||||
}
|
||||
WTSFreeMemory(pInfos);
|
||||
|
||||
@@ -299,12 +299,6 @@ pub struct Connection {
|
||||
tx_input: std_mpsc::Sender<MessageInput>,
|
||||
// handle input messages
|
||||
video_ack_required: bool,
|
||||
// Diagnostics only, gated by `RUSTDESK_QOS_VERBOSE`: how long the shared
|
||||
// write path blocked this second. The video send is inline in the message
|
||||
// loop, so a slow write also delays the delay probe and its reply.
|
||||
video_send_max_ms: u32,
|
||||
video_send_sum_ms: u32,
|
||||
video_send_count: u32,
|
||||
server_audit_conn: String,
|
||||
server_audit_file: String,
|
||||
controlled_context: Option<ControlledContext>,
|
||||
@@ -510,9 +504,6 @@ impl Connection {
|
||||
show_my_cursor: false,
|
||||
tx_input,
|
||||
video_ack_required: false,
|
||||
video_send_max_ms: 0,
|
||||
video_send_sum_ms: 0,
|
||||
video_send_count: 0,
|
||||
server_audit_conn: "".to_owned(),
|
||||
server_audit_file: "".to_owned(),
|
||||
controlled_context,
|
||||
@@ -959,17 +950,10 @@ impl Connection {
|
||||
video_service::notify_video_frame_fetched(vf.display as usize, id, Some(instant.into()));
|
||||
}
|
||||
}
|
||||
let send_begin = video_service::qos_diag_verbose().then(Instant::now);
|
||||
if let Err(err) = conn.stream.send(&value as &Message).await {
|
||||
conn.on_close(&err.to_string(), false).await;
|
||||
break;
|
||||
}
|
||||
if let Some(begin) = send_begin {
|
||||
let blocked = begin.elapsed().as_millis() as u32;
|
||||
conn.video_send_max_ms = conn.video_send_max_ms.max(blocked);
|
||||
conn.video_send_sum_ms = conn.video_send_sum_ms.saturating_add(blocked);
|
||||
conn.video_send_count += 1;
|
||||
}
|
||||
},
|
||||
Some((instant, value)) = rx.recv() => {
|
||||
let latency = instant.elapsed().as_millis() as i64;
|
||||
@@ -1056,21 +1040,6 @@ impl Connection {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if video_service::qos_diag_verbose() && conn.video_send_count > 0 {
|
||||
// Joined with `qos_trace` on `t`: a probe that waits behind a
|
||||
// blocked write is not a slow network.
|
||||
log::debug!(
|
||||
"qos_send t={} id={id} frames={} send_max={} send_sum={} queued={}",
|
||||
hbb_common::get_time(),
|
||||
conn.video_send_count,
|
||||
conn.video_send_max_ms,
|
||||
conn.video_send_sum_ms,
|
||||
rx_video.len()
|
||||
);
|
||||
conn.video_send_max_ms = 0;
|
||||
conn.video_send_sum_ms = 0;
|
||||
conn.video_send_count = 0;
|
||||
}
|
||||
conn.file_remove_log_control.on_timer().drain(..).map(|x| conn.send_to_cm(x)).count();
|
||||
#[cfg(feature = "hwcodec")]
|
||||
conn.update_supported_encoding();
|
||||
|
||||
@@ -625,7 +625,7 @@ impl VideoQoS {
|
||||
.clamp(MIN_AUTO_FPS.min(user_cap), user_cap)
|
||||
.min(current);
|
||||
user.delay.fps = Some(fps);
|
||||
log::debug!(
|
||||
log::trace!(
|
||||
"qos_trace t={} id={id} timeout={elapsed} fps={fps}",
|
||||
hbb_common::get_time()
|
||||
);
|
||||
|
||||
@@ -655,12 +655,6 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
let capture_width = c.width;
|
||||
let capture_height = c.height;
|
||||
let (mut second_instant, mut send_counter) = (Instant::now(), 0);
|
||||
// Diagnostics only. `send_counter` counts capture rounds, which is not the
|
||||
// number of frames that reached a connection: the encoder's own rate control
|
||||
// drops frames when the bitrate cannot carry them. `wait_max_ms` is how long
|
||||
// a round waited for the previous frame to be picked up, so a blocked write
|
||||
// shows up here as capture stalling rather than as a slow network.
|
||||
let (mut sent_counter, mut wait_max_ms) = (0usize, 0u32);
|
||||
|
||||
while sp.ok() {
|
||||
#[cfg(windows)]
|
||||
@@ -671,8 +665,6 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
&mut spf,
|
||||
client_record,
|
||||
&mut send_counter,
|
||||
&mut sent_counter,
|
||||
&mut wait_max_ms,
|
||||
&mut second_instant,
|
||||
&sp.name(),
|
||||
)?;
|
||||
@@ -793,9 +785,6 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
capture_width,
|
||||
capture_height,
|
||||
)?;
|
||||
if !send_conn_ids.is_empty() {
|
||||
sent_counter += 1;
|
||||
}
|
||||
frame_controller.set_send(now, send_conn_ids);
|
||||
send_counter += 1;
|
||||
}
|
||||
@@ -855,9 +844,6 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
capture_width,
|
||||
capture_height,
|
||||
)?;
|
||||
if !send_conn_ids.is_empty() {
|
||||
sent_counter += 1;
|
||||
}
|
||||
frame_controller.set_send(now, send_conn_ids);
|
||||
send_counter += 1;
|
||||
}
|
||||
@@ -899,7 +885,6 @@ fn run(vs: VideoService) -> ResultType<()> {
|
||||
break;
|
||||
}
|
||||
}
|
||||
wait_max_ms = wait_max_ms.max(wait_begin.elapsed().as_millis() as u32);
|
||||
DISPLAY_CONN_IDS.lock().unwrap().remove(&display_idx);
|
||||
|
||||
let elapsed = now.elapsed();
|
||||
@@ -1330,22 +1315,12 @@ pub fn make_display_changed_msg(
|
||||
Some(msg_out)
|
||||
}
|
||||
|
||||
/// Per-second pipeline diagnostics, off unless `RUSTDESK_QOS_VERBOSE` is set.
|
||||
/// The default log level is `debug`, so an unconditional line here would land in
|
||||
/// every user's log file once a second forever. Nothing enables it implicitly.
|
||||
pub(crate) fn qos_diag_verbose() -> bool {
|
||||
static VERBOSE: std::sync::OnceLock<bool> = std::sync::OnceLock::new();
|
||||
*VERBOSE.get_or_init(|| std::env::var("RUSTDESK_QOS_VERBOSE").is_ok())
|
||||
}
|
||||
|
||||
fn check_qos(
|
||||
encoder: &mut Encoder,
|
||||
ratio: &mut f32,
|
||||
spf: &mut Duration,
|
||||
client_record: bool,
|
||||
send_counter: &mut usize,
|
||||
sent_counter: &mut usize,
|
||||
wait_max_ms: &mut u32,
|
||||
second_instant: &mut Instant,
|
||||
name: &str,
|
||||
) -> ResultType<()> {
|
||||
@@ -1371,21 +1346,7 @@ fn check_qos(
|
||||
if second_instant.elapsed() > Duration::from_secs(1) {
|
||||
*second_instant = Instant::now();
|
||||
video_qos.update_display_data(&name, *send_counter);
|
||||
// Diagnostics only, joined with `qos_trace` on `t`: the controller's target
|
||||
// is not the rate the encoder produced, and neither is the rate the send
|
||||
// path accepted.
|
||||
if qos_diag_verbose() {
|
||||
log::debug!(
|
||||
"qos_video t={} display={name} captured={} sent={} wait_max={}",
|
||||
hbb_common::get_time(),
|
||||
*send_counter,
|
||||
*sent_counter,
|
||||
*wait_max_ms
|
||||
);
|
||||
}
|
||||
*send_counter = 0;
|
||||
*sent_counter = 0;
|
||||
*wait_max_ms = 0;
|
||||
}
|
||||
drop(video_qos);
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user