feat: make the TCP punch a user option, with TCP as the backstop

TCP punching was the one direct transport without a switch, while UDP,
IPv6 and WebRTC each had one. Add "Enable TCP hole punching" above the
UDP toggle on both desktop and mobile, default on — including on
self-hosted servers, since unlike the other three (whose default-off
there guards against an hbbs that cannot forward their fields) TCP
punching has always been supported by every server.

Turning all four off would leave no way to punch at all, so TCP runs
regardless in that case. That backstop keys off the switches alone: a
transport that is enabled but fails to materialize — no public v6
address, no NAT port, a failed offerer — is already covered by the
relay fallback for a round that ends up with no usable direct
transport. With the TCP punch off, the fallback request is skipped
too: it exists only to carry that punch, and would otherwise reach
connect() with nothing to try and merely open a second relay.

Known cost, unchanged behavior for the peer: the request carries no
field for this choice, so a peer that receives one with no udp_port and
no offer still punches a TCP hole and listens for a connection the
controller will not make. Representing the transport choice on the
wire needs a proto field and the server forwarding it.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016HV43uh1ztv6Wm5qi3Y1ne
This commit is contained in:
rustdesk
2026-08-27 14:49:33 +08:00
co-authored by Claude Opus 5
parent 98bd7bce16
commit 787350eefb
56 changed files with 132 additions and 26 deletions
+1
View File
@@ -166,6 +166,7 @@ const String kOptionAllowRemoveWallpaper = "allow-remove-wallpaper";
const String kOptionStopService = "stop-service";
const String kOptionDirectxCapture = "enable-directx-capture";
const String kOptionAllowRemoteCmModification = "allow-remote-cm-modification";
const String kOptionEnableTcpPunch = "enable-tcp-punch";
const String kOptionEnableUdpPunch = "enable-udp-punch";
const String kOptionEnableIpv6Punch = "enable-ipv6-punch";
const String kOptionEnableWebrtc = "enable-webrtc";
@@ -563,6 +563,12 @@ class _GeneralState extends State<_General> {
kOptionDirectxCapture,
),
if (!isWeb && !incomingOnly) ...[
_OptionCheckBox(
context,
'Enable TCP hole punching',
kOptionEnableTcpPunch,
isServer: false,
),
_OptionCheckBox(
context,
'Enable UDP hole punching',
+47 -23
View File
@@ -97,6 +97,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
var _hideNetwork = false;
var _hideWebSocket = false;
var _enableTrustedDevices = false;
var _enableTcpPunch = false;
var _enableUdpPunch = false;
var _allowInsecureTlsFallback = false;
var _disableUdp = false;
@@ -142,6 +143,7 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
bind.mainGetBuildinOption(key: kOptionHideWebSocketSetting) == 'Y' ||
isWeb;
_enableTrustedDevices = mainGetBoolOptionSync(kOptionEnableTrustedDevices);
_enableTcpPunch = mainGetLocalBoolOptionSync(kOptionEnableTcpPunch);
_enableUdpPunch = mainGetLocalBoolOptionSync(kOptionEnableUdpPunch);
_enableIpv6Punch = mainGetLocalBoolOptionSync(kOptionEnableIpv6Punch);
_enableWebrtc = mainGetLocalBoolOptionSync(kOptionEnableWebrtc);
@@ -817,43 +819,65 @@ class _SettingsState extends State<SettingsPage> with WidgetsBindingObserver {
});
},
),
if (!incomingOnly)
SettingsTile.switchTile(
title: Text(translate('Enable TCP hole punching')),
initialValue: _enableTcpPunch,
onToggle: isOptionFixed(kOptionEnableTcpPunch)
? null
: (v) async {
await mainSetLocalBoolOption(kOptionEnableTcpPunch, v);
final newValue =
mainGetLocalBoolOptionSync(kOptionEnableTcpPunch);
setState(() {
_enableTcpPunch = newValue;
});
},
),
if (!incomingOnly)
SettingsTile.switchTile(
title: Text(translate('Enable UDP hole punching')),
initialValue: _enableUdpPunch,
onToggle: (v) async {
await mainSetLocalBoolOption(kOptionEnableUdpPunch, v);
final newValue =
mainGetLocalBoolOptionSync(kOptionEnableUdpPunch);
setState(() {
_enableUdpPunch = newValue;
});
},
onToggle: isOptionFixed(kOptionEnableUdpPunch)
? null
: (v) async {
await mainSetLocalBoolOption(kOptionEnableUdpPunch, v);
final newValue =
mainGetLocalBoolOptionSync(kOptionEnableUdpPunch);
setState(() {
_enableUdpPunch = newValue;
});
},
),
if (!incomingOnly)
SettingsTile.switchTile(
title: Text(translate('Enable IPv6 P2P connection')),
initialValue: _enableIpv6Punch,
onToggle: (v) async {
await mainSetLocalBoolOption(kOptionEnableIpv6Punch, v);
final newValue =
mainGetLocalBoolOptionSync(kOptionEnableIpv6Punch);
setState(() {
_enableIpv6Punch = newValue;
});
},
onToggle: isOptionFixed(kOptionEnableIpv6Punch)
? null
: (v) async {
await mainSetLocalBoolOption(kOptionEnableIpv6Punch, v);
final newValue =
mainGetLocalBoolOptionSync(kOptionEnableIpv6Punch);
setState(() {
_enableIpv6Punch = newValue;
});
},
),
if (!incomingOnly)
SettingsTile.switchTile(
title: Text(translate('Enable WebRTC P2P connection')),
initialValue: _enableWebrtc,
onToggle: (v) async {
await mainSetLocalBoolOption(kOptionEnableWebrtc, v);
final newValue = mainGetLocalBoolOptionSync(kOptionEnableWebrtc);
setState(() {
_enableWebrtc = newValue;
});
},
onToggle: isOptionFixed(kOptionEnableWebrtc)
? null
: (v) async {
await mainSetLocalBoolOption(kOptionEnableWebrtc, v);
final newValue =
mainGetLocalBoolOptionSync(kOptionEnableWebrtc);
setState(() {
_enableWebrtc = newValue;
});
},
),
SettingsTile(
title: Text(translate('Language')),
+20 -2
View File
@@ -334,6 +334,18 @@ fn request_allows_tcp_punch(webrtc_sdp_offer: &str) -> bool {
webrtc_sdp_offer.is_empty()
}
/// TCP punch is a user option like the other direct transports, but it is also the backstop:
/// with every direct transport switched off there would be nothing left to punch with, so it
/// runs regardless. Only the switches decide that — a transport that is enabled but fails to
/// materialize (no public v6 address, offerer setup error) leaves this alone, because the
/// relay fallback already covers a round that ends up with no usable direct transport.
fn tcp_punch_allowed() -> bool {
crate::get_tcp_punch_enabled()
|| !(crate::get_udp_punch_enabled()
|| crate::get_ipv6_punch_enabled()
|| crate::get_webrtc_enabled())
}
impl Client {
const CLIENT_CLIPBOARD_NAME: &'static str = "client-clipboard";
@@ -521,7 +533,13 @@ impl Client {
servers.clone(),
contained,
);
if interface.is_force_relay() || (udp.0.is_none() && !has_webrtc_offerer) {
// The fallback request exists only to carry a TCP punch, so it is pointless once TCP
// punch is off — it would reach `connect()` with nothing to try and just open a second
// relay.
if interface.is_force_relay()
|| (udp.0.is_none() && !has_webrtc_offerer)
|| !tcp_punch_allowed()
{
return fut.await;
}
let preferred_fut = fut.boxed();
@@ -849,7 +867,7 @@ impl Client {
} else {
String::new()
};
let allow_tcp_punch = request_allows_tcp_punch(&webrtc_sdp_offer);
let allow_tcp_punch = tcp_punch_allowed() && request_allows_tcp_punch(&webrtc_sdp_offer);
let punch_type = if udp_nat_port > 0 {
"UDP"
} else if allow_tcp_punch {
+7
View File
@@ -1098,6 +1098,13 @@ pub fn is_public(url: &str) -> bool {
host == "rustdesk.com" || host.ends_with(".rustdesk.com")
}
pub fn get_tcp_punch_enabled() -> bool {
config::option2bool(
keys::OPTION_ENABLE_TCP_PUNCH,
&get_local_option(keys::OPTION_ENABLE_TCP_PUNCH),
)
}
pub fn get_udp_punch_enabled() -> bool {
config::option2bool(
keys::OPTION_ENABLE_UDP_PUNCH,
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "لم يفتح المتصفح؟ استخدم الرابط أدناه لتسجيل الدخول."),
("Lock canvas", "قفل اللوحة"),
("Enable WebRTC P2P connection", "تمكين اتصال نظير إلى نظير عبر WebRTC"),
("Enable TCP hole punching", "تمكين تقنية حفر الثغرات عبر TCP"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Браўзер не адкрыўся? Скарыстайцеся спасылкай ніжэй, каб увайсці."),
("Lock canvas", "Заблакіраваць палатно"),
("Enable WebRTC P2P connection", "Выкарыстоўваць падключэнне WebRTC P2P"),
("Enable TCP hole punching", "Выкарыстоўваць TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Браузърът не се отвори? Използвайте URL адреса по-долу, за да се впишете."),
("Lock canvas", "Заключване на платното"),
("Enable WebRTC P2P connection", "Позволяване на WebRTC P2P връзка"),
("Enable TCP hole punching", "Позволяване на TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "No s'ha obert el navegador? Utilitzeu l'URL de sota per iniciar la sessió."),
("Lock canvas", "Bloca el llenç"),
("Enable WebRTC P2P connection", "Habilita la connexió WebRTC P2P"),
("Enable TCP hole punching", "Activa la perforació TCP"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "浏览器未打开?请使用下方网址登录。"),
("Lock canvas", "锁定画布"),
("Enable WebRTC P2P connection", "启用 WebRTC P2P 连接"),
("Enable TCP hole punching", "启用 TCP 打洞"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Neotevřel se prohlížeč? Pro přihlášení použijte URL níže."),
("Lock canvas", "Zamknout zobrazení"),
("Enable WebRTC P2P connection", "Povolit připojení WebRTC P2P"),
("Enable TCP hole punching", "Povolit TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Åbnede browseren ikke? Brug URL'en nedenfor til at logge ind."),
("Lock canvas", "Lås lærred"),
("Enable WebRTC P2P connection", "Aktivér WebRTC P2P-forbindelse"),
("Enable TCP hole punching", "Aktivér TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Hat sich der Browser nicht geöffnet? Melden Sie sich über die untenstehende URL an."),
("Lock canvas", "Sichtfeld sperren"),
("Enable WebRTC P2P connection", "WebRTC-P2P-Verbindung aktivieren"),
("Enable TCP hole punching", "TCP-Hole-Punching aktivieren"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Δεν άνοιξε το πρόγραμμα περιήγησης; Χρησιμοποιήστε τον παρακάτω σύνδεσμο για να συνδεθείτε."),
("Lock canvas", "Κλείδωμα καμβά"),
("Enable WebRTC P2P connection", "Ενεργοποίηση σύνδεσης WebRTC P2P"),
("Enable TCP hole punching", "Ενεργοποίηση διάτρησης οπών TCP"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Ĉu la retumilo ne malfermiĝis? Uzu la suban ligilon por ensaluti."),
("Lock canvas", "Ŝlosi kanvason"),
("Enable WebRTC P2P connection", "Ebligi WebRTC P2P-konekton"),
("Enable TCP hole punching", "Ebligi TCP-trapikadon"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "¿No se abrió el navegador? Usa la URL de abajo para iniciar sesión."),
("Lock canvas", "Bloquear lienzo"),
("Enable WebRTC P2P connection", "Habilitar conexión WebRTC P2P"),
("Enable TCP hole punching", "Habilitar perforación de agujero TCP"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Brauser ei avanenud? Sisselogimiseks kasuta allolevat URL-i."),
("Lock canvas", "Lukusta lõuend"),
("Enable WebRTC P2P connection", "Luba WebRTC P2P-ühendus"),
("Enable TCP hole punching", "Luba TCP-augustamine"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Nabigatzailea ez da ireki? Erabili beheko URLa saioa hasteko."),
("Lock canvas", "Blokeatu oihala"),
("Enable WebRTC P2P connection", "Gaitu WebRTC P2P konexioa"),
("Enable TCP hole punching", "Gaitu TCP zulo-egitea"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "مرورگر باز نشد؟ برای ورود از نشانی زیر استفاده کنید."),
("Lock canvas", "قفل کردن صفحه"),
("Enable WebRTC P2P connection", "فعال‌سازی اتصال همتا‌به‌همتای WebRTC"),
("Enable TCP hole punching", "فعال‌سازی تکنیک TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Eikö selain avautunut? Kirjaudu sisään alla olevan osoitteen kautta."),
("Lock canvas", "Lukitse näkymä"),
("Enable WebRTC P2P connection", "Ota WebRTC P2P yhteys käyttöön"),
("Enable TCP hole punching", "Ota käyttöön TCP hole punching tekniikka"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Le navigateur ne sest pas ouvert ? Utilisez lURL ci-dessous pour vous connecter."),
("Lock canvas", "Verrouiller la vue"),
("Enable WebRTC P2P connection", "Activer la connexion P2P WebRTC"),
("Enable TCP hole punching", "Activer le « hole punching » TCP"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "ბრაუზერი არ გაიხსნა? შესასვლელად გამოიყენეთ ქვემოთ მოცემული ბმული."),
("Lock canvas", "ტილოს დაბლოკვა"),
("Enable WebRTC P2P connection", "WebRTC P2P კავშირის ჩართვა"),
("Enable TCP hole punching", "TCP hole punching-ის ჩართვა"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "બ્રાઉઝર ખૂલ્યું નથી? લોગિન કરવા માટે નીચે આપેલ URL નો ઉપયોગ કરો."),
("Lock canvas", "કેનવાસ લોક કરો"),
("Enable WebRTC P2P connection", "WebRTC P2P કનેક્શન સક્ષમ કરો"),
("Enable TCP hole punching", "TCP હોલ પંચિંગ સક્ષમ કરો"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "הדפדפן לא נפתח? השתמש בכתובת שלמטה כדי להתחבר."),
("Lock canvas", "נעל לוח ציור"),
("Enable WebRTC P2P connection", "אפשר חיבור WebRTC P2P"),
("Enable TCP hole punching", "אפשר TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "ब्राउज़र नहीं खुला? लॉगिन करने के लिए नीचे दिए गए URL का उपयोग करें।"),
("Lock canvas", "कैनवास लॉक करें"),
("Enable WebRTC P2P connection", "WebRTC P2P कनेक्शन सक्षम करें"),
("Enable TCP hole punching", "TCP होल पंचिंग सक्षम करें"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Preglednik se nije otvorio? Za prijavu upotrijebite URL u nastavku."),
("Lock canvas", "Zaključaj pozadinu"),
("Enable WebRTC P2P connection", "Omogući WebRTC P2P vezu"),
("Enable TCP hole punching", "Omogući TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Nem nyílt meg a böngésző? A belépéshez használja az alábbi URL-címet."),
("Lock canvas", "Nézet zárolása"),
("Enable WebRTC P2P connection", "WebRTC P2P kapcsolat engedélyezése"),
("Enable TCP hole punching", "TCP résszűrés engedélyezése"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Browser tidak terbuka? Gunakan URL di bawah ini untuk masuk."),
("Lock canvas", "Kunci kanvas"),
("Enable WebRTC P2P connection", "Aktifkan koneksi P2P WebRTC"),
("Enable TCP hole punching", "Aktifkan TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Il browser non si è aperto? Usa l'URL qui sotto per accedere."),
("Lock canvas", "Blocca tela"),
("Enable WebRTC P2P connection", "Abilita connessione P2P WebRTC"),
("Enable TCP hole punching", "Abilita hole punching TCP"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "ブラウザが開きませんでしたか?下記の URL からログインしてください。"),
("Lock canvas", "キャンバスをロック"),
("Enable WebRTC P2P connection", "WebRTC P2P 接続を有効化する"),
("Enable TCP hole punching", "TCP ホールパンチを有効化する"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "브라우저가 열리지 않았나요? 아래 URL로 로그인하세요."),
("Lock canvas", "캔버스 잠금"),
("Enable WebRTC P2P connection", "WebRTC P2P 연결 사용"),
("Enable TCP hole punching", "TCP 홀 펀칭 사용"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Браузер ашылмады ма? Кіру үшін төмендегі сілтемені пайдаланыңыз."),
("Lock canvas", "Кенепті құлыптау"),
("Enable WebRTC P2P connection", "WebRTC P2P қосылымын іске қосу"),
("Enable TCP hole punching", "TCP hole punching'ті іске қосу"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Naršyklė neatsidarė? Prisijunkite naudodami toliau pateiktą URL."),
("Lock canvas", "Užrakinti drobę"),
("Enable WebRTC P2P connection", "Įgalinti WebRTC P2P ryšį"),
("Enable TCP hole punching", "Įgalinti TCP gręžimą (hole punching)"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Pārlūkprogramma neatvērās? Izmantojiet tālāk norādīto URL, lai pieslēgtos."),
("Lock canvas", "Bloķēt audeklu"),
("Enable WebRTC P2P connection", "Iespējot WebRTC P2P savienojumu"),
("Enable TCP hole punching", "Iespējot TCP caurumu veidošanu"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "ബ്രൗസർ തുറന്നില്ലേ? ലോഗിൻ ചെയ്യാൻ താഴെയുള്ള URL ഉപയോഗിക്കുക."),
("Lock canvas", "ക്യാൻവാസ് ലോക്ക് ചെയ്യുക"),
("Enable WebRTC P2P connection", "WebRTC P2P കണക്ഷൻ അനുവദിക്കുക"),
("Enable TCP hole punching", "TCP ഹോൾ പഞ്ചിംഗ് അനുവദിക്കുക"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Åpnet ikke nettleseren? Bruk URL-en nedenfor for å logge inn."),
("Lock canvas", "Lås lerret"),
("Enable WebRTC P2P connection", "Aktiver WebRTC P2P-tilkobling"),
("Enable TCP hole punching", "Aktiver TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Is de browser niet geopend? Gebruik onderstaande URL om in te loggen."),
("Lock canvas", "Canvas vergrendelen"),
("Enable WebRTC P2P connection", "WebRTC P2P-verbinding inschakelen"),
("Enable TCP hole punching", "TCP-hole punching inschakelen"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Przeglądarka się nie otworzyła? Użyj poniższego adresu URL, aby się zalogować."),
("Lock canvas", "Zablokuj ekran"),
("Enable WebRTC P2P connection", "Włącz połączenie P2P WebRTC"),
("Enable TCP hole punching", "Włącz tworzenie tunelu TCP"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "O navegador não abriu? Utilize o URL abaixo para iniciar sessão."),
("Lock canvas", "Bloquear tela"),
("Enable WebRTC P2P connection", "Ativar ligação P2P por WebRTC"),
("Enable TCP hole punching", "Ativar TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "O navegador não foi aberto? Use a URL abaixo para fazer login."),
("Lock canvas", "Bloquear tela"),
("Enable WebRTC P2P connection", "Habilitar conexão WebRTC P2P"),
("Enable TCP hole punching", "Habilitar TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Browserul nu s-a deschis? Folosește URL-ul de mai jos pentru a te conecta."),
("Lock canvas", "Blochează ecranul"),
("Enable WebRTC P2P connection", "Activează conexiunea P2P prin WebRTC"),
("Enable TCP hole punching", "Activează traversarea TCP (hole punching)"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Браузер не открылся? Используйте ссылку ниже для входа."),
("Lock canvas", "Заблокировать холст"),
("Enable WebRTC P2P connection", "Использовать подключение WebRTC P2P"),
("Enable TCP hole punching", "Использовать TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Non s'est abertu su navigadore? Imprea s'URL inoghe in suta pro intrare."),
("Lock canvas", "Bloca sa tela"),
("Enable WebRTC P2P connection", "Abìlita connessione P2P WebRTC"),
("Enable TCP hole punching", "Abìlita s'istampadura TCP"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Neotvoril sa prehliadač? Na prihlásenie použite URL nižšie."),
("Lock canvas", "Uzamknúť zobrazenie"),
("Enable WebRTC P2P connection", "Povoliť pripojenie WebRTC P2P"),
("Enable TCP hole punching", "Povoliť TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Brskalnik se ni odprl? Za prijavo uporabite spodnji URL."),
("Lock canvas", "Zakleni platno"),
("Enable WebRTC P2P connection", "Omogoči povezavo WebRTC P2P"),
("Enable TCP hole punching", "Omogoči preboj lukenj TCP"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Shfletuesi nuk u hap? Përdorni URL-në më poshtë për të hyrë."),
("Lock canvas", "Kyç canvas"),
("Enable WebRTC P2P connection", "Aktivizo lidhjen WebRTC P2P"),
("Enable TCP hole punching", "Aktivizo TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Pregledač se nije otvorio? Za prijavu koristite URL ispod."),
("Lock canvas", "Zaključaj pozadinu"),
("Enable WebRTC P2P connection", "Omogući WebRTC P2P konekciju"),
("Enable TCP hole punching", "Omogući TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Öppnades inte webbläsaren? Använd URL:en nedan för att logga in."),
("Lock canvas", "Lås canvas"),
("Enable WebRTC P2P connection", "Aktivera WebRTC P2P anslutning"),
("Enable TCP hole punching", "Aktivera TCP hålslagning"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "உலாவி திறக்கவில்லையா? உள்நுழைய கீழே உள்ள URL ஐப் பயன்படுத்தவும்."),
("Lock canvas", "கேன்வாஸைப் பூட்டு"),
("Enable WebRTC P2P connection", "WebRTC P2P இணைப்பு இயக்கு"),
("Enable TCP hole punching", "TCP hole punching இயக்கு"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", ""),
("Lock canvas", ""),
("Enable WebRTC P2P connection", ""),
("Enable TCP hole punching", ""),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "เบราว์เซอร์ไม่เปิดใช่ไหม? ใช้ URL ด้านล่างเพื่อเข้าสู่ระบบ"),
("Lock canvas", "ล็อคแคนวาส"),
("Enable WebRTC P2P connection", "เปิดใช้งานการเชื่อมต่อ P2P แบบ WebRTC"),
("Enable TCP hole punching", "เปิดใช้งาน TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Tarayıcı açılmadı mı? Giriş yapmak için aşağıdaki URL'yi kullanın."),
("Lock canvas", "Tuvali kilitle"),
("Enable WebRTC P2P connection", "WebRTC P2P bağlantısını etkinleştir"),
("Enable TCP hole punching", "TCP delik açmayı etkinleştir"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "瀏覽器未開啟?請使用下方網址登入。"),
("Lock canvas", "鎖定畫布"),
("Enable WebRTC P2P connection", "啟用 WebRTC P2P 連線"),
("Enable TCP hole punching", "啟用 TCP 打洞"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Браузер не відкрився? Скористайтеся посиланням нижче, щоб увійти."),
("Lock canvas", "Блокування полотна"),
("Enable WebRTC P2P connection", "Увімкнути P2P-підключення через WebRTC"),
("Enable TCP hole punching", "Увімкнути TCP hole punching"),
].iter().cloned().collect();
}
+1
View File
@@ -759,5 +759,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("Browser didn't open? Use the url below to sign in.", "Trình duyệt không mở được? Hãy dùng URL bên dưới để đăng nhập."),
("Lock canvas", "Khóa khung hình"),
("Enable WebRTC P2P connection", "Cho phép kết nối WebRTC P2P"),
("Enable TCP hole punching", "Bật TCP Hole Punching"),
].iter().cloned().collect();
}