Merge branch 'master' into master

This commit is contained in:
tom
2022-07-18 14:25:33 +08:00
committed by GitHub
63 changed files with 1609 additions and 717 deletions

View File

@@ -148,11 +148,25 @@ impl Client {
true,
));
}
let rendezvous_server = crate::get_rendezvous_server(1_000).await;
log::info!("rendezvous server: {}", rendezvous_server);
let (mut rendezvous_server, servers, contained) = crate::get_rendezvous_server(1_000).await;
let mut socket =
socket_client::connect_tcp(&*rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT).await?;
socket_client::connect_tcp(&*rendezvous_server, any_addr, RENDEZVOUS_TIMEOUT).await;
debug_assert!(!servers.contains(&rendezvous_server));
if socket.is_err() && !servers.is_empty() {
log::info!("try the other servers: {:?}", servers);
for server in servers {
socket = socket_client::connect_tcp(&*server, any_addr, RENDEZVOUS_TIMEOUT).await;
if socket.is_ok() {
rendezvous_server = server;
break;
}
}
crate::refresh_rendezvous_server();
} else if !contained {
crate::refresh_rendezvous_server();
}
log::info!("rendezvous server: {}", rendezvous_server);
let mut socket = socket?;
let my_addr = socket.local_addr();
let mut signed_id_pk = Vec::new();
let mut relay_server = "".to_owned();

View File

@@ -12,7 +12,6 @@ use hbb_common::{
rendezvous_proto::*,
sleep, socket_client, tokio, ResultType,
};
#[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))]
use hbb_common::{config::RENDEZVOUS_PORT, futures::future::join_all};
use std::sync::{Arc, Mutex};
@@ -247,7 +246,7 @@ async fn test_nat_type_() -> ResultType<bool> {
return Ok(true);
}
let start = std::time::Instant::now();
let rendezvous_server = get_rendezvous_server(1_000).await;
let (rendezvous_server, _, _) = get_rendezvous_server(1_000).await;
let server1 = rendezvous_server;
let tmp: Vec<&str> = server1.split(":").collect();
if tmp.len() != 2 {
@@ -316,31 +315,62 @@ async fn test_nat_type_() -> ResultType<bool> {
Ok(ok)
}
#[cfg(any(target_os = "android", target_os = "ios"))]
pub async fn get_rendezvous_server(_ms_timeout: u64) -> String {
Config::get_rendezvous_server()
pub async fn get_rendezvous_server(ms_timeout: u64) -> (String, Vec<String>, bool) {
#[cfg(any(target_os = "android", target_os = "ios"))]
let (mut a, mut b) = get_rendezvous_server_(ms_timeout);
#[cfg(not(any(target_os = "android", target_os = "ios")))]
let (mut a, mut b) = get_rendezvous_server_(ms_timeout).await;
let mut b: Vec<String> = b
.drain(..)
.map(|x| {
if !x.contains(":") {
format!("{}:{}", x, config::RENDEZVOUS_PORT)
} else {
x
}
})
.collect();
let c = if b.contains(&a) {
b = b.drain(..).filter(|x| x != &a).collect();
true
} else {
a = b.pop().unwrap_or(a);
false
};
(a, b, c)
}
#[inline]
#[cfg(any(target_os = "android", target_os = "ios"))]
fn get_rendezvous_server_(_ms_timeout: u64) -> (String, Vec<String>) {
(
Config::get_rendezvous_server(),
Config::get_rendezvous_servers(),
)
}
#[inline]
#[cfg(not(any(target_os = "android", target_os = "ios")))]
pub async fn get_rendezvous_server(ms_timeout: u64) -> String {
async fn get_rendezvous_server_(ms_timeout: u64) -> (String, Vec<String>) {
crate::ipc::get_rendezvous_server(ms_timeout).await
}
#[inline]
#[cfg(any(target_os = "android", target_os = "ios"))]
pub async fn get_nat_type(_ms_timeout: u64) -> i32 {
Config::get_nat_type()
}
#[inline]
#[cfg(not(any(target_os = "android", target_os = "ios")))]
pub async fn get_nat_type(ms_timeout: u64) -> i32 {
crate::ipc::get_nat_type(ms_timeout).await
}
#[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))]
#[tokio::main(flavor = "current_thread")]
async fn test_rendezvous_server_() {
let servers = Config::get_rendezvous_servers();
hbb_common::config::ONLINE.lock().unwrap().clear();
Config::reset_online();
let mut futs = Vec::new();
for host in servers {
futs.push(tokio::spawn(async move {
@@ -363,11 +393,21 @@ async fn test_rendezvous_server_() {
join_all(futs).await;
}
#[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))]
pub fn test_rendezvous_server() {
std::thread::spawn(test_rendezvous_server_);
}
pub fn refresh_rendezvous_server() {
#[cfg(any(target_os = "android", target_os = "ios", feature = "cli"))]
test_rendezvous_server();
#[cfg(not(any(target_os = "android", target_os = "ios", feature = "cli")))]
std::thread::spawn(|| {
if crate::ipc::test_rendezvous_server().is_err() {
test_rendezvous_server();
}
});
}
#[inline]
pub fn get_time() -> i64 {
std::time::SystemTime::now()
@@ -437,14 +477,15 @@ pub fn is_modifier(evt: &KeyEvent) -> bool {
}
pub fn check_software_update() {
std::thread::spawn(move || allow_err!(_check_software_update()));
std::thread::spawn(move || allow_err!(check_software_update_()));
}
#[tokio::main(flavor = "current_thread")]
async fn _check_software_update() -> hbb_common::ResultType<()> {
async fn check_software_update_() -> hbb_common::ResultType<()> {
sleep(3.).await;
let rendezvous_server = socket_client::get_target_addr(&get_rendezvous_server(1_000).await)?;
let rendezvous_server =
socket_client::get_target_addr(&format!("rs-sg.rustdesk.com:{}", config::RENDEZVOUS_PORT))?;
let mut socket =
socket_client::new_udp(Config::get_any_listen_addr(), RENDEZVOUS_TIMEOUT).await?;

View File

@@ -127,6 +127,7 @@ pub enum Data {
ClipbaordFile(ClipbaordFile),
ClipboardFileEnabled(bool),
PrivacyModeState((i32, PrivacyModeState)),
TestRendezvousServer,
}
#[tokio::main(flavor = "current_thread")]
@@ -286,7 +287,11 @@ async fn handle(data: Data, stream: &mut Connection) {
} else if name == "salt" {
value = Some(Config::get_salt());
} else if name == "rendezvous_server" {
value = Some(Config::get_rendezvous_server());
value = Some(format!(
"{},{}",
Config::get_rendezvous_server(),
Config::get_rendezvous_servers().join(",")
));
} else if name == "rendezvous_servers" {
value = Some(Config::get_rendezvous_servers().join(","));
} else {
@@ -336,7 +341,9 @@ async fn handle(data: Data, stream: &mut Connection) {
.await
);
}
Data::TestRendezvousServer => {
crate::test_rendezvous_server();
}
_ => {}
}
}
@@ -520,11 +527,17 @@ pub fn get_password() -> String {
}
}
pub async fn get_rendezvous_server(ms_timeout: u64) -> String {
pub async fn get_rendezvous_server(ms_timeout: u64) -> (String, Vec<String>) {
if let Ok(Some(v)) = get_config_async("rendezvous_server", ms_timeout).await {
v
let mut urls = v.split(",");
let a = urls.next().unwrap_or_default().to_owned();
let b: Vec<String> = urls.map(|x| x.to_owned()).collect();
(a, b)
} else {
Config::get_rendezvous_server()
(
Config::get_rendezvous_server(),
Config::get_rendezvous_servers(),
)
}
}
@@ -636,3 +649,10 @@ pub async fn set_socks(value: config::Socks5Server) -> ResultType<()> {
.await?;
Ok(())
}
#[tokio::main(flavor = "current_thread")]
pub async fn test_rendezvous_server() -> ResultType<()> {
let mut c = connect(1000, "").await?;
c.send(&Data::TestRendezvousServer).await?;
Ok(())
}

291
src/lan.rs Normal file
View File

@@ -0,0 +1,291 @@
use hbb_common::{
allow_err,
anyhow::bail,
config::{self, Config, RENDEZVOUS_PORT},
log,
protobuf::Message as _,
rendezvous_proto::*,
tokio::{
self,
sync::mpsc::{unbounded_channel, UnboundedReceiver, UnboundedSender},
},
ResultType,
};
use std::{
collections::{HashMap, HashSet},
net::{IpAddr, Ipv4Addr, SocketAddr, ToSocketAddrs, UdpSocket},
time::Instant,
};
type Message = RendezvousMessage;
pub(super) fn start_listening() -> ResultType<()> {
let addr = SocketAddr::from(([0, 0, 0, 0], get_broadcast_port()));
let socket = std::net::UdpSocket::bind(addr)?;
socket.set_read_timeout(Some(std::time::Duration::from_millis(1000)))?;
log::info!("lan discovery listener started");
loop {
let mut buf = [0; 2048];
if let Ok((len, addr)) = socket.recv_from(&mut buf) {
if let Ok(msg_in) = Message::parse_from_bytes(&buf[0..len]) {
match msg_in.union {
Some(rendezvous_message::Union::PeerDiscovery(p)) => {
if p.cmd == "ping" {
if let Some(self_addr) = get_ipaddr_by_peer(&addr) {
let mut msg_out = Message::new();
let peer = PeerDiscovery {
cmd: "pong".to_owned(),
mac: get_mac(&self_addr),
id: Config::get_id(),
hostname: whoami::hostname(),
username: crate::platform::get_active_username(),
platform: whoami::platform().to_string(),
..Default::default()
};
msg_out.set_peer_discovery(peer);
socket.send_to(&msg_out.write_to_bytes()?, addr).ok();
}
}
}
_ => {}
}
}
}
}
}
#[tokio::main(flavor = "current_thread")]
pub async fn discover() -> ResultType<()> {
let sockets = send_query()?;
let rx = spawn_wait_responses(sockets);
handle_received_peers(rx).await?;
log::info!("discover ping done");
Ok(())
}
pub fn send_wol(id: String) {
let interfaces = default_net::get_interfaces();
for peer in &config::LanPeers::load().peers {
if peer.id == id {
for (ip, mac) in peer.ip_mac.iter() {
if let Ok(mac_addr) = mac.parse() {
if let Ok(IpAddr::V4(ip)) = ip.parse() {
for interface in &interfaces {
for ipv4 in &interface.ipv4 {
if (u32::from(ipv4.addr) & u32::from(ipv4.netmask))
== (u32::from(ip) & u32::from(ipv4.netmask))
{
allow_err!(wol::send_wol(
mac_addr,
None,
Some(IpAddr::V4(ipv4.addr))
));
}
}
}
}
}
}
break;
}
}
}
#[inline]
fn get_broadcast_port() -> u16 {
(RENDEZVOUS_PORT + 3) as _
}
fn get_mac(ip: &IpAddr) -> String {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
if let Ok(mac) = get_mac_by_ip(ip) {
mac.to_string()
} else {
"".to_owned()
}
#[cfg(any(target_os = "android", target_os = "ios"))]
"".to_owned()
}
fn get_all_ipv4s() -> ResultType<Vec<Ipv4Addr>> {
let mut ipv4s = Vec::new();
for interface in default_net::get_interfaces() {
for ipv4 in &interface.ipv4 {
ipv4s.push(ipv4.addr.clone());
}
}
Ok(ipv4s)
}
fn get_mac_by_ip(ip: &IpAddr) -> ResultType<String> {
for interface in default_net::get_interfaces() {
match ip {
IpAddr::V4(local_ipv4) => {
if interface.ipv4.iter().any(|x| x.addr == *local_ipv4) {
if let Some(mac_addr) = interface.mac_addr {
return Ok(mac_addr.address());
}
}
}
IpAddr::V6(local_ipv6) => {
if interface.ipv6.iter().any(|x| x.addr == *local_ipv6) {
if let Some(mac_addr) = interface.mac_addr {
return Ok(mac_addr.address());
}
}
}
}
}
bail!("No interface found for ip: {:?}", ip);
}
// Mainly from https://github.com/shellrow/default-net/blob/cf7ca24e7e6e8e566ed32346c9cfddab3f47e2d6/src/interface/shared.rs#L4
fn get_ipaddr_by_peer<A: ToSocketAddrs>(peer: A) -> Option<IpAddr> {
let socket = match UdpSocket::bind("0.0.0.0:0") {
Ok(s) => s,
Err(_) => return None,
};
match socket.connect(peer) {
Ok(()) => (),
Err(_) => return None,
};
match socket.local_addr() {
Ok(addr) => return Some(addr.ip()),
Err(_) => return None,
};
}
fn create_broadcast_sockets() -> ResultType<Vec<UdpSocket>> {
let mut sockets = Vec::new();
for v4_addr in get_all_ipv4s()? {
if v4_addr.is_private() {
let s = UdpSocket::bind(SocketAddr::from((v4_addr, 0)))?;
s.set_broadcast(true)?;
log::debug!("Bind socket to {}", &v4_addr);
sockets.push(s)
}
}
Ok(sockets)
}
fn send_query() -> ResultType<Vec<UdpSocket>> {
let sockets = create_broadcast_sockets()?;
if sockets.is_empty() {
bail!("Found no ipv4 addresses");
}
let mut msg_out = Message::new();
let peer = PeerDiscovery {
cmd: "ping".to_owned(),
..Default::default()
};
msg_out.set_peer_discovery(peer);
let maddr = SocketAddr::from(([255, 255, 255, 255], get_broadcast_port()));
for socket in &sockets {
socket.send_to(&msg_out.write_to_bytes()?, maddr)?;
}
log::info!("discover ping sent");
Ok(sockets)
}
fn wait_response(
socket: UdpSocket,
timeout: Option<std::time::Duration>,
tx: UnboundedSender<config::DiscoveryPeer>,
) -> ResultType<()> {
let mut last_recv_time = Instant::now();
socket.set_read_timeout(timeout)?;
loop {
let mut buf = [0; 2048];
if let Ok((len, addr)) = socket.recv_from(&mut buf) {
if let Ok(msg_in) = Message::parse_from_bytes(&buf[0..len]) {
match msg_in.union {
Some(rendezvous_message::Union::PeerDiscovery(p)) => {
last_recv_time = Instant::now();
if p.cmd == "pong" {
let mac = if let Some(self_addr) = get_ipaddr_by_peer(&addr) {
get_mac(&self_addr)
} else {
"".to_owned()
};
if mac != p.mac {
allow_err!(tx.send(config::DiscoveryPeer {
id: p.id.clone(),
ip_mac: HashMap::from([
(addr.ip().to_string(), p.mac.clone(),)
]),
username: p.username.clone(),
hostname: p.hostname.clone(),
platform: p.platform.clone(),
online: true,
}));
}
}
}
_ => {}
}
}
}
if last_recv_time.elapsed().as_millis() > 3_000 {
break;
}
}
Ok(())
}
fn spawn_wait_responses(sockets: Vec<UdpSocket>) -> UnboundedReceiver<config::DiscoveryPeer> {
let (tx, rx) = unbounded_channel::<_>();
for socket in sockets {
let tx_clone = tx.clone();
std::thread::spawn(move || {
allow_err!(wait_response(
socket,
Some(std::time::Duration::from_millis(10)),
tx_clone
));
});
}
rx
}
async fn handle_received_peers(mut rx: UnboundedReceiver<config::DiscoveryPeer>) -> ResultType<()> {
let mut peers = config::LanPeers::load().peers;
peers.iter_mut().for_each(|peer| {
peer.online = false;
});
let mut response_set = HashSet::new();
let mut last_write_time = Instant::now() - std::time::Duration::from_secs(4);
loop {
tokio::select! {
data = rx.recv() => match data {
Some(mut peer) => {
let in_response_set = !response_set.insert(peer.id.clone());
if let Some(pos) = peers.iter().position(|x| x.is_same_peer(&peer) ) {
let peer1 = peers.remove(pos);
if in_response_set {
peer.ip_mac.extend(peer1.ip_mac);
peer.online = true;
}
}
peers.insert(0, peer);
if last_write_time.elapsed().as_millis() > 300 {
config::LanPeers::store(&peers);
last_write_time = Instant::now();
}
}
None => {
break
}
}
}
}
config::LanPeers::store(&peers);
Ok(())
}

View File

@@ -8,6 +8,7 @@ mod de;
mod en;
mod eo;
mod es;
mod hu;
mod fr;
mod id;
mod it;
@@ -28,6 +29,7 @@ lazy_static::lazy_static! {
("tw", "繁體中文"),
("pt", "Português"),
("es", "Español"),
("hu", "Magyar"),
("ru", "Русский"),
("sk", "Slovenčina"),
("id", "Indonesia"),
@@ -68,6 +70,7 @@ pub fn translate_locale(name: String, locale: &str) -> String {
"tw" => tw::T.deref(),
"de" => de::T.deref(),
"es" => es::T.deref(),
"hu" => hu::T.deref(),
"ru" => ru::T.deref(),
"eo" => eo::T.deref(),
"id" => id::T.deref(),

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "进入隐私模式"),
("Out privacy mode", "退出隐私模式"),
("Language", "语言"),
("Keep RustDesk background service", "保持RustDesk后台服务"),
("Ignore Battery Optimizations", "忽略电池优化"),
("android_open_battery_optimizations_tip", "如需关闭此功能请在接下来的RustDesk应用设置页面中找到并进入 [电源] 页面,取消勾选 [不受限制]"),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "v režimu soukromí"),
("Out privacy mode", "mimo režim soukromí"),
("Language", ""),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "I databeskyttelsestilstand"),
("Out privacy mode", "Databeskyttelsestilstand fra"),
("Language", ""),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "im Datenschutzmodus"),
("Out privacy mode", "Datenschutzmodus aus"),
("Language", "Sprache"),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -27,5 +27,6 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("doc_mac_permission", "https://rustdesk.com/docs/en/manual/mac/#enable-permissions"),
("doc_fix_wayland", "https://rustdesk.com/docs/en/manual/linux/#x11-required"),
("server_not_support", "Not yet supported by the server"),
("android_open_battery_optimizations_tip", "If you want to disable this feature, please go to the next RustDesk application settings page, find and enter [Battery] ,Uncheck [Unrestricted]"),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", ""),
("Out privacy mode", ""),
("Language", ""),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "En modo de privacidad"),
("Out privacy mode", "Fuera del modo de privacidad"),
("Language", ""),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "en mode privé"),
("Out privacy mode", "hors mode de confidentialité"),
("Language", "Langue"),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

291
src/lang/hu.rs Normal file
View File

@@ -0,0 +1,291 @@
lazy_static::lazy_static! {
pub static ref T: std::collections::HashMap<&'static str, &'static str> =
[
("Status", "Státusz"),
("Your Desktop", "A te asztalod"),
("desk_tip", "Az asztalod ezzel az ID-vel, és jelszóval érhető el."),
("Password", "Jelszó"),
("Ready", "Kész"),
("Established", "Létrejött"),
("connecting_status", "Kapcsolódás a RustDesk hálózatához..."),
("Enable Service", "A szolgáltatás bekapcsolása"),
("Start Service", "Szolgáltatás Elindítása"),
("Service is running", "A szolgáltatás fut"),
("Service is not running", "A szolgáltatás nem fut"),
("not_ready_status", "A RustDesk nem áll készen. Kérlek nézd meg a hálózati beállításaidat."),
("Control Remote Desktop", "Távoli Asztal Kontrollálása"),
("Transfer File", "Fájl Transzfer"),
("Connect", "Kapcsolódás"),
("Recent Sessions", "Korábbi Sessionök"),
("Address Book", "Címköny"),
("Confirmation", "Megerősít"),
("TCP Tunneling", "TCP Tunneling"),
("Remove", "Eltávolít"),
("Refresh random password", "Véletlenszerű jelszó frissítése"),
("Set your own password", "Saját jelszó beállítása"),
("Enable Keyboard/Mouse", "Billentyűzet/Egér bekapcsolása"),
("Enable Clipboard", "Megosztott vágólap bekapcsolása"),
("Enable File Transfer", "Fájl transzer bekapcsolása"),
("Enable TCP Tunneling", "TCP Tunneling bekapcsolása"),
("IP Whitelisting", "IP Fehérlista"),
("ID/Relay Server", "ID/Relay Szerver"),
("Stop service", "Szolgáltatás Kikapcsolása"),
("Change ID", "ID Megváltoztatása"),
("Website", "Weboldal"),
("About", "Rólunk: "),
("Mute", "Némítás"),
("Audio Input", "Audo Bemenet"),
("Enhancements", "Javítások"),
("Hardware Codec", "Hardware Kodek"),
("Adaptive Bitrate", "Adaptív Bitrate"),
("ID Server", "ID Szerver"),
("Relay Server", "Relay Szerver"),
("API Server", "API Szerver"),
("invalid_http", "A címnek mindenképpen http(s)://-el kell kezdődnie."),
("Invalid IP", "A megadott íp cím helytelen."),
("id_change_tip", "Csak a-z, A-Z, 0-9 csoportokba tartozó karakterek, illetve a _ karakter van engedélyezve. Az első karakternek mindenképpen a-z, A-Z csoportokba kell esnie. Az ID hosszúsága 6-tól, 16 karakter."),
("Invalid format", "Érvénytelen formátum"),
("server_not_support", "Még nem támogatott a szerver által"),
("Not available", "Nem érhető el"),
("Too frequent", "Túl gyakori"),
("Cancel", "Mégsem"),
("Skip", "Kihagy"),
("Close", "Bezár"),
("Retry", "Újrapróbálkozás"),
("OK", "OK"),
("Password Required", "A jelszó megadása kötelező"),
("Please enter your password", "Kérlek írd be a jelszavad"),
("Remember password", "Kérlek emlékezz a jelszóra"),
("Wrong Password", "Hibás jelszó"),
("Do you want to enter again?", "Újra szeretnéd próbálni?"),
("Connection Error", "Kapcsolódási Hiba"),
("Error", "Hiba"),
("Reset by the peer", "A kapcsolatot alaphelyzetbe állt"),
("Connecting...", "Kapcsolódás..."),
("Connection in progress. Please wait.", "A kapcsolódás folyamatban van. Kérlek várj."),
("Please try 1 minute later", "Kérlek próbáld újra 1 perc múlva."),
("Login Error", "Belépési Hiba"),
("Successful", "Sikeres"),
("Connected, waiting for image...", "Kapcsolódva, várakozás a képre..."),
("Name", "Név"),
("Type", "Fajta"),
("Modified", "Módosított"),
("Size", "Méret"),
("Show Hidden Files", "Rejtett Fájlok Mutatása"),
("Receive", "Kapni"),
("Send", "Küldeni"),
("Refresh File", "Fájlok Frissítése"),
("Local", "Lokális"),
("Remote", "Távoli"),
("Remote Computer", "Távoli Számítógép"),
("Local Computer", "Lokális Számítógép"),
("Confirm Delete", "Törlés Megerősítése"),
("Delete", "Törlés"),
("Properties", "Tulajdonságok"),
("Multi Select", "Több fájl kiválasztása"),
("Empty Directory", "Üres Könyvtár"),
("Not an empty directory", "Nem egy üres könyvtár"),
("Are you sure you want to delete this file?", "Biztosan törölni szeretnéd ezt a fájlt?"),
("Are you sure you want to delete this empty directory?", "Biztosan törölni szeretnéd ezt az üres könyvtárat?"),
("Are you sure you want to delete the file of this directory?", "Biztosan törölni szeretnéd a fájlokat ebben a könyvtárban?"),
("Do this for all conflicts", "Ezt tedd az összes konfliktussal"),
("This is irreversible!", "Ez a folyamat visszafordíthatatlan!"),
("Deleting", "A törlés folyamatban"),
("files", "fájlok"),
("Waiting", "Várunk"),
("Finished", "Végzett"),
("Speed", "Gyorsaság"),
("Custom Image Quality", "Egyedi Képminőség"),
("Privacy mode", "Inkognító mód"),
("Block user input", "Felhasználói input blokkokolása"),
("Unblock user input", "Felhasználói input blokkolásának feloldása"),
("Adjust Window", "Ablakméret beállítása"),
("Original", "Eredeti"),
("Shrink", "Zsugorított"),
("Stretch", "Nyújtott"),
("Good image quality", "Jó képminőség"),
("Balanced", "Balanszolt"),
("Optimize reaction time", "Válaszidő optimializálása"),
("Custom", "Egyedi"),
("Show remote cursor", "Távoli kurzor mutatása"),
("Show quality monitor", "Minőségi monitor mutatása"),
("Disable clipboard", "Vágólap Kikapcsolása"),
("Lock after session end", "Lezárás a session végén"),
("Insert", "Beszúrás"),
("Insert Lock", "Beszúrási Zároló"),
("Refresh", "Frissítés"),
("ID does not exist", "Ez az ID nem létezik"),
("Failed to connect to rendezvous server", "A randevú szerverhez való kapcsolódás sikertelen"),
("Please try later", "Kérlek próbád később"),
("Remote desktop is offline", "A távoli asztal offline"),
("Key mismatch", "Eltérés a kulcsokban"),
("Timeout", "Időtúllépés"),
("Failed to connect to relay server", "A relay szerverhez való kapcsolódás sikertelen"),
("Failed to connect via rendezvous server", "A randevú szerverrel való kapcsolódás sikertelen"),
("Failed to connect via relay server", "A relay szerverrel való kapcsolódás sikertelen"),
("Failed to make direct connection to remote desktop", "A távoli asztalhoz való direkt kapcsolódás sikertelen"),
("Set Password", "Jelszó Beállítása"),
("OS Password", "Operációs Rendszer Jelszavának Beállítása"),
("install_tip", "Az UAC (Felhasználói Fiók Felügyelet) miatt, a RustDesk nem fog rendesen funkcionálni mint távoli oldal néhány esetben. Hogy ezt kikerüld, vagy kikapcsold, kérlek nyomj rá a gombra ezalatt az üzenet alatt, hogy feltelepítsd a RustDesket a rendszerre."),
("Click to upgrade", "Kattints a frissítés telepítéséhez"),
("Click to download", "Kattints a letöltéshez"),
("Click to update", "Kattints a frissítés letöltéséhez"),
("Configure", "Beállítás"),
("config_acc", "Ahhoz hogy a RustDesket távolról irányítani tudd, \"Elérhetőségi\" jogokat kell adnod a RustDesk-nek."),
("config_screen", "Ahhoz hogy a RustDesket távolról irányítani tudd, \"Képernyőfelvételi\" jogokat kell adnod a RustDesk-nek."),
("Installing ...", "Telepítés..."),
("Install", "Telepítés"),
("Installation", "Telepítés"),
("Installation Path", "Telepítési útvonal"),
("Create start menu shortcuts", "Start menu parancsikon létrehozása"),
("Create desktop icon", "Asztali icon létrehozása"),
("agreement_tip", "Azzal hogy elindítod a telepítést, elfogadod a licenszszerződést."),
("Accept and Install", "Elfogadás és Telepítés"),
("End-user license agreement", "Felhasználói licencszerződés"),
("Generating ...", "Generálás..."),
("Your installation is lower version.", "A jelenleg feltelepített verzió régebbi."),
("not_close_tcp_tip", "Ne zárd be ezt az ablakot miközben a tunnelt használod"),
("Listening ...", "Halgazózás..."),
("Remote Host", "Távoli Host"),
("Remote Port", "Távoli Port"),
("Action", "Akció"),
("Add", "Add"),
("Local Port", "Lokális Port"),
("setup_server_tip", "Egy gyorsabb kapcsolatért, kérlek hostolj egy saját szervert"),
("Too short, at least 6 characters.", "Túl rövid, legalább 6 karakter"),
("The confirmation is not identical.", "A megerősítés nem volt azonos"),
("Permissions", "Jogok"),
("Accept", "Elfogad"),
("Dismiss", "Elutasít"),
("Disconnect", "Szétkapcsolás"),
("Allow using keyboard and mouse", "Billentyűzet és egér használatának engedélyezése"),
("Allow using clipboard", "Vágólap használatának engedélyezése"),
("Allow hearing sound", "Hang átvitelének engedélyezése"),
("Allow file copy and paste", "Fájlok másolásának és beillesztésének engedélyezése"),
("Connected", "Kapcsolódva"),
("Direct and encrypted connection", "Direkt, és titkosított kapcsolat"),
("Relayed and encrypted connection", "Relayelt, és titkosított kapcsolat"),
("Direct and unencrypted connection", "Direkt, és nem titkosított kapcsolat"),
("Relayed and unencrypted connection", "Rekayelt, és nem titkosított kapcsolat"),
("Enter Remote ID", "Kérlek írd be a távoli ID-t"),
("Enter your password", "Kérlek írd be a jelszavadat"),
("Logging in...", "A belépés folyamatban..."),
("Enable RDP session sharing", "Az RDP session megosztás engedélyezése"),
("Auto Login", "Automatikus Login"),
("Enable Direct IP Access", "Direkt IP elérés engedélyezése"),
("Rename", "Átnevezés"),
("Space", "Hely"),
("Create Desktop Shortcut", "Asztali Parancsikon Lértehozása"),
("Change Path", "Útvonal Megváltoztatása"),
("Create Folder", "Mappa Készítése"),
("Please enter the folder name", "Kérlek írd be a mappa nevét"),
("Fix it", "Kérlek javísd meg"),
("Warning", "Figyelem"),
("Login screen using Wayland is not supported", "A belépési kijelzővel a Wayland használata nem támogatott"),
("Reboot required", "Újraindítás szükséges"),
("Unsupported display server ", "Nem támogatott kijelző szerver"),
("x11 expected", "x11-re számítottt"),
("Port", "Port"),
("Settings", "Beállítások"),
("Username", "Felhasználónév"),
("Invalid port", "Érvénytelen port"),
("Closed manually by the peer", "A kapcsolat manuálisan be lett zárva a másik fél álltal"),
("Enable remote configuration modification", "Távoli konfiguráció módosítás engedélyezése"),
("Run without install", "Futtatás feltelepítés nélkül"),
("Always connected via relay", "Mindig relay által kapcsolódott"),
("Always connect via relay", "Mindig relay által kapcsolódik"),
("whitelist_tip", "Csak a fehérlistán lévő címek érhetnek el"),
("Login", "Belépés"),
("Logout", "Kilépés"),
("Tags", "Tagok"),
("Search ID", "ID keresés"),
("Current Wayland display server is not supported", "Jelenleg a Wayland display szerver nem támogatott"),
("whitelist_sep", "Ide jönnek a címek, vesző, pontosvessző, space, vagy új sorral elválasztva"),
("Add ID", "ID Hozzáadása"),
("Add Tag", "Tag Hozzáadása"),
("Unselect all tags", "Az összes tag kiválasztásának törlése"),
("Network error", "Hálózati hiba"),
("Username missed", "A felhasználónév kimaradt"),
("Password missed", "A jelszó kimaradt"),
("Wrong credentials", "Hibás felhasználónév vagy jelszó"),
("Edit Tag", "A tag(ok) szerkeztése"),
("Unremember Password", "A jelszó megjegyzésének törlése"),
("Favorites", "Kedvencek"),
("Add to Favorites", "Hozzáadás a kedvencekhez"),
("Remove from Favorites", "Eltávolítás a kedvencektől"),
("Empty", "Üres"),
("Invalid folder name", "Helytelen fájlnév"),
("Socks5 Proxy", "Socks5-ös Proxy"),
("Hostname", "Hostnév"),
("Discovered", "Felfedezés"),
("install_daemon_tip", "Ahhoz hogy a RustDesk bootkor elinduljon, telepítened kell a rendszer szolgáltatást."),
("Remote ID", "Távoli ID"),
("Paste", "Beillesztés"),
("Paste here?", "Beillesztés ide?"),
("Are you sure to close the connection?", "Biztos vagy benne hogy be szeretnéd zárni a kapcsolatot?"),
("Download new version", "Új verzó letöltése"),
("Touch mode", "Érintési mód bekapcsolása"),
("Mouse mode", "Egérhasználati mód bekapcsolása"),
("One-Finger Tap", "Egyújas érintés"),
("Left Mouse", "Baloldali Egér"),
("One-Long Tap", "Egy hosszú érintés"),
("Two-Finger Tap", "Két újas érintés"),
("Right Mouse", "Jobboldali Egér"),
("One-Finger Move", "Egyújas mozgatás"),
("Double Tap & Move", "Kétszeri érintés, és Mozgatás"),
("Mouse Drag", "Egérrel való húzás"),
("Three-Finger vertically", "Három ujj függőlegesen"),
("Mouse Wheel", "Egérgörgő"),
("Two-Finger Move", "Kátújas mozgatás"),
("Canvas Move", "Nézet Mozgatása"),
("Pinch to Zoom", "Húzd össze a nagyításhoz"),
("Canvas Zoom", "Nézet Nagyítása"),
("Reset canvas", "Nézet visszaállítása"),
("No permission of file transfer", "Nincs jogod fájl transzer indításához"),
("Note", "Megyjegyzés"),
("Connection", "Kapcsolat"),
("Share Screen", "Képernyőmegosztás"),
("CLOSE", "LETILT"),
("OPEN", "ENGEDÉLYEZ"),
("Chat", "Chat"),
("Total", "Összes"),
("items", "Tárgyak"),
("Selected", "Kiválasztott"),
("Screen Capture", "Képernyőrögzítés"),
("Input Control", "Input Kontrol"),
("Audio Capture", "Audió Rögzítés"),
("File Connection", "Fájlkapcsolat"),
("Screen Connection", "Új Vizuális Kapcsolat"),
("Do you accept?", "Elfogadod?"),
("Open System Setting", "Rendszer beállítások megnyitása"),
("How to get Android input permission?", "Hogyan állíthatok be Android input jogokat?"),
("android_input_permission_tip1", "Ahhoz hogy egy távoli eszköz kontolálhassa az Android eszközödet egérrel vagy érintéssel, jogot kell adnod a RustDesk-nek, hogy használja az \"Elérhetőségi\" szolgáltatást."),
("android_input_permission_tip2", "Kérlek navigálj a rendszer beállításaihoz, keresd meg vagy írd be hogy [Feltelepített Szolgáltatások], és kapcsold be a [RustDesk Input] szolgáltatást."),
("android_new_connection_tip", "Új kontrollálási kérés érkezett, amely irányítani szeretné az eszközöded."),
("android_service_will_start_tip", "A \"Képernyőrögzítés\" engedélyezése automatikusan elindítja majd a szolgáltatást, amely megengedi más eszközöknek hogy kérést kezdeményezzenek az eszköz felé."),
("android_stop_service_tip", "A szolgáltatás bezárása automatikusan szétkapcsol minden létező kapcsolatot."),
("android_version_audio_tip", "A jelenlegi Android verzió nem támogatja a hangrögzítést, kérlek frissíts legalább Android 10-re, vagy egy újabb verzióra."),
("android_start_service_tip", "Nyomj a [Szolgáltatás Indítása] opcióra, vagy adj [Képernyőrözítési] jogot az applikációnak hogy elindítsd a képernyőmegosztó szolgáltatást."),
("Account", "Fiók"),
("Overwrite", "Felülírás"),
("This file exists, skip or overwrite this file?", "Ez a fájl már létezik, skippeljünk, vagy felülírjuk ezt a fájlt?"),
("Quit", "Kilépés"),
("doc_mac_permission", "https://rustdesk.com/docs/hu/manual/mac/#enable-permissions"),
("Help", "Segítség"),
("Failed", "Sikertelen"),
("Succeeded", "Sikeres"),
("Someone turns on privacy mode, exit", "Valaki bekacsolta a privát módot, lépj ki"),
("Unsupported", "Nem támogatott"),
("Peer denied", "Elutasítva a távoli fél álltal"),
("Please install plugins", "Kérlek telepítsd a pluginokat"),
("Peer exit", "A távoli fél kilépett"),
("Failed to turn off", "Nem tudtuk kikapcsolni"),
("Turned off", "Kikapcsolva"),
("In privacy mode", "Belépés a privát módba"),
("Out privacy mode", "Kilépés a privát módból"),
("Language", "Nyelv"),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "Dalam mode privasi"),
("Out privacy mode", "Keluar dari mode privasi"),
("Language", ""),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "In modalità privacy"),
("Out privacy mode", "Fuori modalità privacy"),
("Language", "Linguaggio"),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "No modo de privacidade"),
("Out privacy mode", "Fora do modo de privacidade"),
("Language", ""),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "В режиме конфиденциальности"),
("Out privacy mode", "Выход из режима конфиденциальности"),
("Language", "Язык"),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "V režime súkromia"),
("Out privacy mode", "Mimo režimu súkromia"),
("Language", ""),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", ""),
("Out privacy mode", ""),
("Language", ""),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "Gizlilik modunda"),
("Out privacy mode", "Gizlilik modu dışında"),
("Language", ""),
("Keep RustDesk background service", ""),
("Ignore Battery Optimizations", ""),
("android_open_battery_optimizations_tip", ""),
].iter().cloned().collect();
}

View File

@@ -284,5 +284,8 @@ pub static ref T: std::collections::HashMap<&'static str, &'static str> =
("In privacy mode", "開啟隱私模式"),
("Out privacy mode", "退出隱私模式"),
("Language", "語言"),
("Keep RustDesk background service", "保持RustDesk後台服務"),
("Ignore Battery Optimizations", "忽略電池優化"),
("android_open_battery_optimizations_tip", "如需關閉此功能請在接下來的RustDesk應用設置頁面中找到並進入 [電源] 頁面,取消勾選 [不受限制]"),
].iter().cloned().collect();
}

View File

@@ -12,6 +12,8 @@ mod client;
#[cfg(not(any(target_os = "ios")))]
mod rendezvous_mediator;
#[cfg(not(any(target_os = "ios")))]
mod lan;
#[cfg(not(any(target_os = "ios")))]
pub use self::rendezvous_mediator::*;
/// cbindgen:ignore
pub mod common;

View File

@@ -591,7 +591,6 @@ impl Connection {
log::debug!("Exit io_loop of id={}", session.id);
}
Err(err) => {
crate::common::test_rendezvous_server();
session.msgbox("error", "Connection Error", &err.to_string());
}
}
@@ -600,7 +599,7 @@ impl Connection {
async fn handle_msg_from_peer(&mut self, data: &[u8], peer: &mut Stream) -> bool {
if let Ok(msg_in) = Message::parse_from_bytes(&data) {
match msg_in.union {
Some(message::Union::video_frame(vf)) => {
Some(message::Union::VideoFrame(vf)) => {
if !self.first_frame {
self.first_frame = true;
}
@@ -611,21 +610,21 @@ impl Connection {
s.add(ZeroCopyBuffer(self.video_handler.rgb.clone()));
}
}
Some(message::Union::hash(hash)) => {
Some(message::Union::Hash(hash)) => {
self.session.handle_hash(hash, peer).await;
}
Some(message::Union::login_response(lr)) => match lr.union {
Some(login_response::Union::error(err)) => {
Some(message::Union::LoginResponse(lr)) => match lr.union {
Some(login_response::Union::Error(err)) => {
if !self.session.handle_login_error(&err) {
return false;
}
}
Some(login_response::Union::peer_info(pi)) => {
Some(login_response::Union::PeerInfo(pi)) => {
self.session.handle_peer_info(pi);
}
_ => {}
},
Some(message::Union::clipboard(cb)) => {
Some(message::Union::Clipboard(cb)) => {
if !self.session.lc.read().unwrap().disable_clipboard {
let content = if cb.compress {
decompress(&cb.content)
@@ -638,7 +637,7 @@ impl Connection {
}
}
}
Some(message::Union::cursor_data(cd)) => {
Some(message::Union::CursorData(cd)) => {
let colors = hbb_common::compress::decompress(&cd.colors);
self.session.push_event(
"cursor_data",
@@ -655,18 +654,18 @@ impl Connection {
],
);
}
Some(message::Union::cursor_id(id)) => {
Some(message::Union::CursorId(id)) => {
self.session
.push_event("cursor_id", vec![("id", &id.to_string())]);
}
Some(message::Union::cursor_position(cp)) => {
Some(message::Union::CursorPosition(cp)) => {
self.session.push_event(
"cursor_position",
vec![("x", &cp.x.to_string()), ("y", &cp.y.to_string())],
);
}
Some(message::Union::file_response(fr)) => match fr.union {
Some(file_response::Union::dir(fd)) => {
Some(message::Union::FileResponse(fr)) => match fr.union {
Some(file_response::Union::Dir(fd)) => {
let mut entries = fd.entries.to_vec();
if self.session.peer_platform() == "Windows" {
fs::transform_windows_path(&mut entries);
@@ -680,7 +679,7 @@ impl Connection {
job.set_files(entries);
}
}
Some(file_response::Union::block(block)) => {
Some(file_response::Union::Block(block)) => {
if let Some(job) = fs::get_job(block.id, &mut self.write_jobs) {
if let Err(_err) = job.write(block, None).await {
// to-do: add "skip" for writing job
@@ -688,17 +687,17 @@ impl Connection {
self.update_jobs_status();
}
}
Some(file_response::Union::done(d)) => {
Some(file_response::Union::Done(d)) => {
if let Some(job) = fs::get_job(d.id, &mut self.write_jobs) {
job.modify_time();
fs::remove_job(d.id, &mut self.write_jobs);
}
self.handle_job_status(d.id, d.file_num, None);
}
Some(file_response::Union::error(e)) => {
Some(file_response::Union::Error(e)) => {
self.handle_job_status(e.id, e.file_num, Some(e.error));
}
Some(file_response::Union::digest(digest)) => {
Some(file_response::Union::Digest(digest)) => {
if digest.is_upload {
if let Some(job) = fs::get_job(digest.id, &mut self.read_jobs) {
if let Some(file) = job.files().get(digest.file_num as usize) {
@@ -709,9 +708,9 @@ impl Connection {
id: digest.id,
file_num: digest.file_num,
union: Some(if overwrite {
file_transfer_send_confirm_request::Union::offset_blk(0)
file_transfer_send_confirm_request::Union::OffsetBlk(0)
} else {
file_transfer_send_confirm_request::Union::skip(
file_transfer_send_confirm_request::Union::Skip(
true,
)
}),
@@ -741,7 +740,7 @@ impl Connection {
let msg= new_send_confirm(FileTransferSendConfirmRequest {
id: digest.id,
file_num: digest.file_num,
union: Some(file_transfer_send_confirm_request::Union::skip(true)),
union: Some(file_transfer_send_confirm_request::Union::Skip(true)),
..Default::default()
});
self.session.send_msg(msg);
@@ -753,9 +752,9 @@ impl Connection {
id: digest.id,
file_num: digest.file_num,
union: Some(if overwrite {
file_transfer_send_confirm_request::Union::offset_blk(0)
file_transfer_send_confirm_request::Union::OffsetBlk(0)
} else {
file_transfer_send_confirm_request::Union::skip(true)
file_transfer_send_confirm_request::Union::Skip(true)
}),
..Default::default()
},
@@ -775,7 +774,7 @@ impl Connection {
FileTransferSendConfirmRequest {
id: digest.id,
file_num: digest.file_num,
union: Some(file_transfer_send_confirm_request::Union::offset_blk(0)),
union: Some(file_transfer_send_confirm_request::Union::OffsetBlk(0)),
..Default::default()
},
);
@@ -792,15 +791,15 @@ impl Connection {
}
_ => {}
},
Some(message::Union::misc(misc)) => match misc.union {
Some(misc::Union::audio_format(f)) => {
Some(message::Union::Misc(misc)) => match misc.union {
Some(misc::Union::AudioFormat(f)) => {
self.audio_handler.handle_format(f); //
}
Some(misc::Union::chat_message(c)) => {
Some(misc::Union::ChatMessage(c)) => {
self.session
.push_event("chat_client_mode", vec![("text", &c.text)]);
}
Some(misc::Union::permission_info(p)) => {
Some(misc::Union::PermissionInfo(p)) => {
log::info!("Change permission {:?} -> {}", p.permission, p.enabled);
use permission_info::Permission;
self.session.push_event(
@@ -816,7 +815,7 @@ impl Connection {
)],
);
}
Some(misc::Union::switch_display(s)) => {
Some(misc::Union::SwitchDisplay(s)) => {
self.video_handler.reset();
self.session.push_event(
"switch_display",
@@ -829,22 +828,22 @@ impl Connection {
],
);
}
Some(misc::Union::close_reason(c)) => {
Some(misc::Union::CloseReason(c)) => {
self.session.msgbox("error", "Connection Error", &c);
return false;
}
_ => {}
},
Some(message::Union::test_delay(t)) => {
Some(message::Union::TestDelay(t)) => {
self.session.handle_test_delay(t, peer).await;
}
Some(message::Union::audio_frame(frame)) => {
Some(message::Union::AudioFrame(frame)) => {
if !self.session.lc.read().unwrap().disable_audio {
self.audio_handler.handle_frame(frame);
}
}
Some(message::Union::file_action(action)) => match action.union {
Some(file_action::Union::send_confirm(c)) => {
Some(message::Union::FileAction(action)) => match action.union {
Some(file_action::Union::SendConfirm(c)) => {
if let Some(job) = fs::get_job(c.id, &mut self.read_jobs) {
job.confirm(&c);
}
@@ -1030,9 +1029,9 @@ impl Connection {
id,
file_num,
union: if need_override {
Some(file_transfer_send_confirm_request::Union::offset_blk(0))
Some(file_transfer_send_confirm_request::Union::OffsetBlk(0))
} else {
Some(file_transfer_send_confirm_request::Union::skip(true))
Some(file_transfer_send_confirm_request::Union::Skip(true))
},
..Default::default()
});
@@ -1048,9 +1047,9 @@ impl Connection {
id,
file_num,
union: if need_override {
Some(file_transfer_send_confirm_request::Union::offset_blk(0))
Some(file_transfer_send_confirm_request::Union::OffsetBlk(0))
} else {
Some(file_transfer_send_confirm_request::Union::skip(true))
Some(file_transfer_send_confirm_request::Union::Skip(true))
},
..Default::default()
});
@@ -1452,7 +1451,7 @@ pub mod connection_manager {
let mut req = FileTransferSendConfirmRequest {
id,
file_num,
union: Some(file_transfer_send_confirm_request::Union::offset_blk(0)),
union: Some(file_transfer_send_confirm_request::Union::OffsetBlk(0)),
..Default::default()
};
let digest = FileTransferDigest {

View File

@@ -183,7 +183,7 @@ async fn run_forward(forward: Framed<TcpStream, BytesCodec>, stream: Stream) ->
},
res = stream.next() => {
if let Some(Ok(bytes)) = res {
allow_err!(forward.send(bytes.into()).await);
allow_err!(forward.send(bytes).await);
} else {
break;
}

View File

@@ -2,7 +2,7 @@ use crate::server::{check_zombie, new as new_server, ServerPtr};
use hbb_common::{
allow_err,
anyhow::bail,
config::{self, Config, REG_INTERVAL, RENDEZVOUS_PORT, RENDEZVOUS_TIMEOUT},
config::{Config, REG_INTERVAL, RENDEZVOUS_PORT, RENDEZVOUS_TIMEOUT},
futures::future::join_all,
log,
protobuf::Message as _,
@@ -51,9 +51,12 @@ impl RendezvousMediator {
check_zombie();
let server = new_server();
if Config::get_nat_type() == NatType::UNKNOWN_NAT as i32 {
crate::common::test_nat_type();
crate::test_nat_type();
nat_tested = true;
}
if !Config::get_option("stop-service").is_empty() {
crate::test_rendezvous_server();
}
let server_cloned = server.clone();
tokio::spawn(async move {
direct_server(server_cloned).await;
@@ -61,14 +64,14 @@ impl RendezvousMediator {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
if crate::platform::is_installed() {
std::thread::spawn(move || {
allow_err!(lan_discovery());
allow_err!(super::lan::start_listening());
});
}
loop {
Config::reset_online();
if Config::get_option("stop-service").is_empty() {
if !nat_tested {
crate::common::test_nat_type();
crate::test_nat_type();
nat_tested = true;
}
let mut futs = Vec::new();
@@ -537,103 +540,3 @@ async fn direct_server(server: ServerPtr) {
}
}
}
#[inline]
pub fn get_broadcast_port() -> u16 {
(RENDEZVOUS_PORT + 3) as _
}
pub fn get_mac() -> String {
#[cfg(not(any(target_os = "android", target_os = "ios")))]
if let Ok(Some(mac)) = mac_address::get_mac_address() {
mac.to_string()
} else {
"".to_owned()
}
#[cfg(any(target_os = "android", target_os = "ios"))]
"".to_owned()
}
fn lan_discovery() -> ResultType<()> {
let addr = SocketAddr::from(([0, 0, 0, 0], get_broadcast_port()));
let socket = std::net::UdpSocket::bind(addr)?;
socket.set_read_timeout(Some(std::time::Duration::from_millis(1000)))?;
log::info!("lan discovery listener started");
loop {
let mut buf = [0; 2048];
if let Ok((len, addr)) = socket.recv_from(&mut buf) {
if let Ok(msg_in) = Message::parse_from_bytes(&buf[0..len]) {
match msg_in.union {
Some(rendezvous_message::Union::PeerDiscovery(p)) => {
if p.cmd == "ping" {
let mut msg_out = Message::new();
let peer = PeerDiscovery {
cmd: "pong".to_owned(),
mac: get_mac(),
id: Config::get_id(),
hostname: whoami::hostname(),
username: crate::platform::get_active_username(),
platform: whoami::platform().to_string(),
..Default::default()
};
msg_out.set_peer_discovery(peer);
socket.send_to(&msg_out.write_to_bytes()?, addr).ok();
}
}
_ => {}
}
}
}
}
}
pub fn discover() -> ResultType<()> {
let addr = SocketAddr::from(([0, 0, 0, 0], 0));
let socket = std::net::UdpSocket::bind(addr)?;
socket.set_broadcast(true)?;
let mut msg_out = Message::new();
let peer = PeerDiscovery {
cmd: "ping".to_owned(),
..Default::default()
};
msg_out.set_peer_discovery(peer);
let maddr = SocketAddr::from(([255, 255, 255, 255], get_broadcast_port()));
socket.send_to(&msg_out.write_to_bytes()?, maddr)?;
log::info!("discover ping sent");
let mut last_recv_time = Instant::now();
let mut last_write_time = Instant::now();
let mut last_write_n = 0;
// to-do: load saved peers, and update incrementally (then we can see offline)
let mut peers = Vec::new();
let mac = get_mac();
socket.set_read_timeout(Some(std::time::Duration::from_millis(10)))?;
loop {
let mut buf = [0; 2048];
if let Ok((len, _)) = socket.recv_from(&mut buf) {
if let Ok(msg_in) = Message::parse_from_bytes(&buf[0..len]) {
match msg_in.union {
Some(rendezvous_message::Union::PeerDiscovery(p)) => {
last_recv_time = Instant::now();
if p.cmd == "pong" {
if p.mac != mac {
peers.push((p.id, p.username, p.hostname, p.platform));
}
}
}
_ => {}
}
}
}
if last_write_time.elapsed().as_millis() > 300 && last_write_n != peers.len() {
config::LanPeers::store(serde_json::to_string(&peers)?);
last_write_time = Instant::now();
last_write_n = peers.len();
}
if last_recv_time.elapsed().as_millis() > 3_000 {
break;
}
}
log::info!("discover ping done");
config::LanPeers::store(serde_json::to_string(&peers)?);
Ok(())
}

View File

@@ -492,7 +492,7 @@ impl Connection {
res = self.stream.next() => {
if let Some(res) = res {
last_recv_time = Instant::now();
timeout(SEND_TIMEOUT_OTHER, forward.send(res?.into())).await??;
timeout(SEND_TIMEOUT_OTHER, forward.send(res?)).await??;
} else {
bail!("Stream reset by the peer");
}

View File

@@ -147,7 +147,6 @@ impl VideoQoS {
// handle image_quality change from peer
pub fn update_image_quality(&mut self, image_quality: i32) {
let image_quality = Self::convert_quality(image_quality) as _;
log::debug!("VideoQoS update_image_quality: {}", image_quality);
if self.current_image_quality != image_quality {
self.current_image_quality = image_quality;
let _ = self.generate_bitrate().ok();
@@ -171,7 +170,7 @@ impl VideoQoS {
#[cfg(target_os = "android")]
{
// fix when andorid screen shrinks
let fix = Display::fix_quality() as u32;
let fix = scrap::Display::fix_quality() as u32;
log::debug!("Android screen, fix quality:{}", fix);
let base_bitrate = base_bitrate * fix;
self.target_bitrate = base_bitrate * self.current_image_quality / 100;

View File

@@ -541,6 +541,16 @@ impl UI {
PeerConfig::remove(&id);
}
fn remove_discovered(&mut self, id: String) {
let mut peers = config::LanPeers::load().peers;
peers.retain(|x| x.id != id);
config::LanPeers::store(&peers);
}
fn send_wol(&mut self, id: String) {
crate::lan::send_wol(id)
}
fn new_remote(&mut self, id: String, remote_type: String) {
let mut lock = self.0.lock().unwrap();
let args = vec![format!("--{}", remote_type), id.clone()];
@@ -685,12 +695,12 @@ impl UI {
fn discover(&self) {
std::thread::spawn(move || {
allow_err!(crate::rendezvous_mediator::discover());
allow_err!(crate::lan::discover());
});
}
fn get_lan_peers(&self) -> String {
config::LanPeers::load().peers
serde_json::to_string(&config::LanPeers::load().peers).unwrap_or_default()
}
fn get_uuid(&self) -> String {
@@ -780,7 +790,9 @@ impl sciter::EventHandler for UI {
fn closing(i32, i32, i32, i32);
fn get_size();
fn new_remote(String, bool);
fn send_wol(String);
fn remove_peer(String);
fn remove_discovered(String);
fn get_connect_status();
fn get_mouse_time();
fn check_mouse_time();

View File

@@ -318,9 +318,10 @@ class SessionList: Reactor.Component {
<li #tunnel>{translate('TCP Tunneling')}</li>
{false && !handler.using_public_server() && <li #force-always-relay><span>{svg_checkmark}</span>{translate('Always connect via relay')}</li>}
<li #rdp>RDP<EditRdpPort /></li>
<li #wol>{translate('WOL')}</li>
<div .separator />
<li #rename>{translate('Rename')}</li>
{this.type != "fav" && this.type != "lan" && <li #remove>{translate('Remove')}</li>}
{this.type != "lan" && <li #rename>{translate('Rename')}</li>}
{this.type != "fav" && <li #remove>{translate('Remove')}</li>}
{is_win && <li #shortcut>{translate('Create Desktop Shortcut')}</li>}
<li #forget-password>{translate('Unremember Password')}</li>
{(!this.type || this.type == "fav") && <li #add-fav>{translate('Add to Favorites')}</li>}
@@ -419,6 +420,8 @@ class SessionList: Reactor.Component {
createNewConnect(id, "connect");
} else if (action == "transfer") {
createNewConnect(id, "file-transfer");
} else if (action == "wol") {
handler.send_wol(id);
} else if (action == "remove") {
if (this.type == "ab") {
for (var i = 0; i < ab.peers.length; ++i) {
@@ -429,6 +432,9 @@ class SessionList: Reactor.Component {
break;
}
}
} else if (this.type == "lan") {
handler.remove_discovered(id);
app.update();
} else {
handler.remove_peer(id);
app.update();

View File

@@ -258,10 +258,10 @@ pub fn check_main_window() {
let app = format!("/Applications/{}.app", crate::get_app_name());
let my_uid = sys
.process((std::process::id() as i32).into())
.map(|x| x.uid)
.map(|x| x.user_id())
.unwrap_or_default();
for (_, p) in sys.processes().iter() {
if p.cmd().len() == 1 && p.uid == my_uid && p.cmd()[0].contains(&app) {
if p.cmd().len() == 1 && p.user_id() == my_uid && p.cmd()[0].contains(&app) {
return;
}
}