mirror of
https://github.com/rustdesk/rustdesk-server.git
synced 2025-07-01 23:35:38 +00:00
Fix: clippy warning in rust 1.66.0
This commit is contained in:
parent
d7b2060a5b
commit
60a6d672c5
@ -3,7 +3,7 @@ fn main() {
|
|||||||
protobuf_codegen::Codegen::new()
|
protobuf_codegen::Codegen::new()
|
||||||
.pure()
|
.pure()
|
||||||
.out_dir("src/protos")
|
.out_dir("src/protos")
|
||||||
.inputs(&["protos/rendezvous.proto", "protos/message.proto"])
|
.inputs(["protos/rendezvous.proto", "protos/message.proto"])
|
||||||
.include("protos")
|
.include("protos")
|
||||||
.customize(protobuf_codegen::Customize::default().tokio_bytes(true))
|
.customize(protobuf_codegen::Customize::default().tokio_bytes(true))
|
||||||
.run()
|
.run()
|
||||||
|
@ -15,6 +15,12 @@ enum DecodeState {
|
|||||||
Data(usize),
|
Data(usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for BytesCodec {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl BytesCodec {
|
impl BytesCodec {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -56,7 +62,7 @@ impl BytesCodec {
|
|||||||
}
|
}
|
||||||
src.advance(head_len);
|
src.advance(head_len);
|
||||||
src.reserve(n);
|
src.reserve(n);
|
||||||
return Ok(Some(n));
|
Ok(Some(n))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decode_data(&self, n: usize, src: &mut BytesMut) -> io::Result<Option<BytesMut>> {
|
fn decode_data(&self, n: usize, src: &mut BytesMut) -> io::Result<Option<BytesMut>> {
|
||||||
|
@ -32,12 +32,7 @@ pub fn decompress(data: &[u8]) -> Vec<u8> {
|
|||||||
const MAX: usize = 1024 * 1024 * 64;
|
const MAX: usize = 1024 * 1024 * 64;
|
||||||
const MIN: usize = 1024 * 1024;
|
const MIN: usize = 1024 * 1024;
|
||||||
let mut n = 30 * data.len();
|
let mut n = 30 * data.len();
|
||||||
if n > MAX {
|
n = n.clamp(MIN, MAX);
|
||||||
n = MAX;
|
|
||||||
}
|
|
||||||
if n < MIN {
|
|
||||||
n = MIN;
|
|
||||||
}
|
|
||||||
match d.decompress(data, n) {
|
match d.decompress(data, n) {
|
||||||
Ok(res) => out = res,
|
Ok(res) => out = res,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -29,7 +29,7 @@ pub const READ_TIMEOUT: u64 = 30_000;
|
|||||||
pub const REG_INTERVAL: i64 = 12_000;
|
pub const REG_INTERVAL: i64 = 12_000;
|
||||||
pub const COMPRESS_LEVEL: i32 = 3;
|
pub const COMPRESS_LEVEL: i32 = 3;
|
||||||
const SERIAL: i32 = 3;
|
const SERIAL: i32 = 3;
|
||||||
const PASSWORD_ENC_VERSION: &'static str = "00";
|
const PASSWORD_ENC_VERSION: &str = "00";
|
||||||
// 128x128
|
// 128x128
|
||||||
#[cfg(target_os = "macos")] // 128x128 on 160x160 canvas, then shrink to 128, mac looks better with padding
|
#[cfg(target_os = "macos")] // 128x128 on 160x160 canvas, then shrink to 128, mac looks better with padding
|
||||||
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAyVBMVEUAAAAAcf8Acf8Acf8Acv8Acf8Acf8Acf8Acf8AcP8Acf8Ab/8AcP8Acf////8AaP/z+f/o8v/k7v/5/v/T5f8AYP/u9v/X6f+hx/+Kuv95pP8Aef/B1/+TwP9xoP8BdP/g6P+Irv9ZmP8Bgf/E3f98q/9sn/+01f+Es/9nm/9Jif8hhv8off/M4P+syP+avP86iP/c7f+xy/9yqf9Om/9hk/9Rjv+60P99tv9fpf88lv8yjf8Tgf8deP+kvP8BiP8NeP8hkP80gP8oj2VLAAAADXRSTlMA7o7qLvnaxZ1FOxYPjH9HWgAABHJJREFUeNrtm+tW4jAQgBfwuu7MtIUWsOUiCCioIIgLiqvr+z/UHq/LJKVkmwTcc/r9E2nzlU4mSTP9lpGRkZGR8VX5cZjfL+yCEXYL+/nDH//U/Pd8DgyTy39Xbv7oIAcWyB0cqbW/sweW2NtRaj8H1sgpGOwUIAH7Bkd7YJW9dXFwAJY5WNP/cmCZQnJvzIN18on5LwfWySXlxEPYAIcad8D6PdiHDbCfIFCADVBIENiFDbCbIACKPPXrZ+cP8E6/0znvP4EymgIEravIRcTxu8HxNSJ60a8W0AYECKrlAN+YwAthCd9wm1Ug6wKzIn5SgRduXfwkqDasCjx0XFzi9PV6zwNcIuhcWBOg+ikySq8C9UD4dEKWBCoOcspvAuLHTo9sCDQiFPHotRM48j8G5gVur1FdAN2uaYEuiz7xFsgEJ2RUoMUakXuBTHHoGxQYOBhHjeUBAefEnMAowFhaLBOKuOemBBbxLRQrH2PBCgMvNCPQGMeevTb9zLrPxz2Mo+QbEaijzPUcOOHMQZkKGRAIPem39+bypREMPTkQW/oCfk866zAkiIFG4yIKRE/aAnfiSd0WrORY6pFdXQEqi9mvAQm0RIOSnoCcZ8vJoz3diCnjRk+g8VP4/fuQDJ2Lxr6WwG0gXs9aTpDzW0vgDBlVUpixR8gYk44AD8FrUKHr8JQJGgIDnoDqoALxmWPQSi9AVVzm8gKUuEPGr/QCvptwJkbSYT/TC4S8C96DGjTj86aHtAI0x2WaBIq0eSYYpRa4EsdWVVwWu9O0Aj6f6dyBMnwEraeOgSYu0wZlauzA47QCbT7DgAQSE+hZWoEBF/BBmWOewNMK3BsSqKUW4MGcWqCSVmDkbvkXGKQOwg6PAUO9oL3xXhA20yaiCjuwYygRVQlUOTWTCf2SuNJTxeFjgaHByGuAIvd8ItdPLTDhS7IuqEE1YSKVOgbayLhSFQhMzYh8hwfBs1r7c505YVIQYEdNoKwxK06MJiyrpUFHiF0NAfCQUVHoiRclIXJIR6C2fqG37pBHvcWpgwzvAtYwkR5UGV2e42UISdBJETl3mg8ouo54Rcnti1/vaT+iuUQBt500Cgo4U10BeHSkk57FB0JjWkKRMWgLUA0lLodtImAQdaMiiri3+gIAPZQoutHNsgKF1aaDMhMyIdBf8Th+Bh8MTjGWCpl5Wv43tDmnF+IUVMrcZgRoiAxhtrloYizNkZaAnF5leglbNhj0wYCAbCDvGb0mP4nib7O7ZlcYQ2m1gPtIZgVgGNNMeaVAaWR+57TrqgtUnm3sHQ+kYeE6fufUubG1ez50FXbPnWgBlgSABmN3TTcsRl2yWkHRrwbiunvk/W2+Mg1hPZplPDeXRbZzStFH15s1QIVd3UImP5z/bHpeeQLvRJ7XLFUffQIlCvqlXETQbgN9/rlYABGosv+Vi9m2Xs639YLGrZd0br+odetlvdsvbN56abfd4vbCzv9Q3v/ygoOV21A4OPpfXvH4Ai+5ZGRkZGRkbJA/t/I0QMzoMiEAAAAASUVORK5CYII=
|
pub const ICON: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAyVBMVEUAAAAAcf8Acf8Acf8Acv8Acf8Acf8Acf8Acf8AcP8Acf8Ab/8AcP8Acf////8AaP/z+f/o8v/k7v/5/v/T5f8AYP/u9v/X6f+hx/+Kuv95pP8Aef/B1/+TwP9xoP8BdP/g6P+Irv9ZmP8Bgf/E3f98q/9sn/+01f+Es/9nm/9Jif8hhv8off/M4P+syP+avP86iP/c7f+xy/9yqf9Om/9hk/9Rjv+60P99tv9fpf88lv8yjf8Tgf8deP+kvP8BiP8NeP8hkP80gP8oj2VLAAAADXRSTlMA7o7qLvnaxZ1FOxYPjH9HWgAABHJJREFUeNrtm+tW4jAQgBfwuu7MtIUWsOUiCCioIIgLiqvr+z/UHq/LJKVkmwTcc/r9E2nzlU4mSTP9lpGRkZGR8VX5cZjfL+yCEXYL+/nDH//U/Pd8DgyTy39Xbv7oIAcWyB0cqbW/sweW2NtRaj8H1sgpGOwUIAH7Bkd7YJW9dXFwAJY5WNP/cmCZQnJvzIN18on5LwfWySXlxEPYAIcad8D6PdiHDbCfIFCADVBIENiFDbCbIACKPPXrZ+cP8E6/0znvP4EymgIEravIRcTxu8HxNSJ60a8W0AYECKrlAN+YwAthCd9wm1Ug6wKzIn5SgRduXfwkqDasCjx0XFzi9PV6zwNcIuhcWBOg+ikySq8C9UD4dEKWBCoOcspvAuLHTo9sCDQiFPHotRM48j8G5gVur1FdAN2uaYEuiz7xFsgEJ2RUoMUakXuBTHHoGxQYOBhHjeUBAefEnMAowFhaLBOKuOemBBbxLRQrH2PBCgMvNCPQGMeevTb9zLrPxz2Mo+QbEaijzPUcOOHMQZkKGRAIPem39+bypREMPTkQW/oCfk866zAkiIFG4yIKRE/aAnfiSd0WrORY6pFdXQEqi9mvAQm0RIOSnoCcZ8vJoz3diCnjRk+g8VP4/fuQDJ2Lxr6WwG0gXs9aTpDzW0vgDBlVUpixR8gYk44AD8FrUKHr8JQJGgIDnoDqoALxmWPQSi9AVVzm8gKUuEPGr/QCvptwJkbSYT/TC4S8C96DGjTj86aHtAI0x2WaBIq0eSYYpRa4EsdWVVwWu9O0Aj6f6dyBMnwEraeOgSYu0wZlauzA47QCbT7DgAQSE+hZWoEBF/BBmWOewNMK3BsSqKUW4MGcWqCSVmDkbvkXGKQOwg6PAUO9oL3xXhA20yaiCjuwYygRVQlUOTWTCf2SuNJTxeFjgaHByGuAIvd8ItdPLTDhS7IuqEE1YSKVOgbayLhSFQhMzYh8hwfBs1r7c505YVIQYEdNoKwxK06MJiyrpUFHiF0NAfCQUVHoiRclIXJIR6C2fqG37pBHvcWpgwzvAtYwkR5UGV2e42UISdBJETl3mg8ouo54Rcnti1/vaT+iuUQBt500Cgo4U10BeHSkk57FB0JjWkKRMWgLUA0lLodtImAQdaMiiri3+gIAPZQoutHNsgKF1aaDMhMyIdBf8Th+Bh8MTjGWCpl5Wv43tDmnF+IUVMrcZgRoiAxhtrloYizNkZaAnF5leglbNhj0wYCAbCDvGb0mP4nib7O7ZlcYQ2m1gPtIZgVgGNNMeaVAaWR+57TrqgtUnm3sHQ+kYeE6fufUubG1ez50FXbPnWgBlgSABmN3TTcsRl2yWkHRrwbiunvk/W2+Mg1hPZplPDeXRbZzStFH15s1QIVd3UImP5z/bHpeeQLvRJ7XLFUffQIlCvqlXETQbgN9/rlYABGosv+Vi9m2Xs639YLGrZd0br+odetlvdsvbN56abfd4vbCzv9Q3v/ygoOV21A4OPpfXvH4Ai+5ZGRkZGRkbJA/t/I0QMzoMiEAAAAASUVORK5CYII=
|
||||||
@ -43,6 +43,7 @@ lazy_static::lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Size = (i32, i32, i32, i32);
|
type Size = (i32, i32, i32, i32);
|
||||||
|
type KeyPair = (Vec<u8>, Vec<u8>);
|
||||||
|
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load()));
|
static ref CONFIG: Arc<RwLock<Config>> = Arc::new(RwLock::new(Config::load()));
|
||||||
@ -51,7 +52,7 @@ lazy_static::lazy_static! {
|
|||||||
pub static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default();
|
pub static ref ONLINE: Arc<Mutex<HashMap<String, i64>>> = Default::default();
|
||||||
pub static ref PROD_RENDEZVOUS_SERVER: Arc<RwLock<String>> = Default::default();
|
pub static ref PROD_RENDEZVOUS_SERVER: Arc<RwLock<String>> = Default::default();
|
||||||
pub static ref APP_NAME: Arc<RwLock<String>> = Arc::new(RwLock::new("RustDesk".to_owned()));
|
pub static ref APP_NAME: Arc<RwLock<String>> = Arc::new(RwLock::new("RustDesk".to_owned()));
|
||||||
static ref KEY_PAIR: Arc<Mutex<Option<(Vec<u8>, Vec<u8>)>>> = Default::default();
|
static ref KEY_PAIR: Arc<Mutex<Option<KeyPair>>> = Default::default();
|
||||||
static ref HW_CODEC_CONFIG: Arc<RwLock<HwCodecConfig>> = Arc::new(RwLock::new(HwCodecConfig::load()));
|
static ref HW_CODEC_CONFIG: Arc<RwLock<HwCodecConfig>> = Arc::new(RwLock::new(HwCodecConfig::load()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,17 +73,17 @@ lazy_static::lazy_static! {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CHARS: &'static [char] = &[
|
const CHARS: &[char] = &[
|
||||||
'2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
|
'2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k',
|
||||||
'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
|
||||||
];
|
];
|
||||||
|
|
||||||
pub const RENDEZVOUS_SERVERS: &'static [&'static str] = &[
|
pub const RENDEZVOUS_SERVERS: &[&str] = &[
|
||||||
"rs-ny.rustdesk.com",
|
"rs-ny.rustdesk.com",
|
||||||
"rs-sg.rustdesk.com",
|
"rs-sg.rustdesk.com",
|
||||||
"rs-cn.rustdesk.com",
|
"rs-cn.rustdesk.com",
|
||||||
];
|
];
|
||||||
pub const RS_PUB_KEY: &'static str = "OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=";
|
pub const RS_PUB_KEY: &str = "OeVuKk5nlHiXp+APNn0Y3pC1Iwpwn44JGqrQCsWqmBw=";
|
||||||
pub const RENDEZVOUS_PORT: i32 = 21116;
|
pub const RENDEZVOUS_PORT: i32 = 21116;
|
||||||
pub const RELAY_PORT: i32 = 21117;
|
pub const RELAY_PORT: i32 = 21117;
|
||||||
|
|
||||||
@ -123,7 +124,7 @@ pub struct Config {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
salt: String,
|
salt: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
key_pair: (Vec<u8>, Vec<u8>), // sk, pk
|
key_pair: KeyPair, // sk, pk
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
key_confirmed: bool,
|
key_confirmed: bool,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
@ -311,7 +312,7 @@ impl Config2 {
|
|||||||
pub fn load_path<T: serde::Serialize + serde::de::DeserializeOwned + Default + std::fmt::Debug>(
|
pub fn load_path<T: serde::Serialize + serde::de::DeserializeOwned + Default + std::fmt::Debug>(
|
||||||
file: PathBuf,
|
file: PathBuf,
|
||||||
) -> T {
|
) -> T {
|
||||||
let cfg = match confy::load_path(&file) {
|
let cfg = match confy::load_path(file) {
|
||||||
Ok(config) => config,
|
Ok(config) => config,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("Failed to load config: {}", err);
|
log::error!("Failed to load config: {}", err);
|
||||||
@ -358,21 +359,17 @@ impl Config {
|
|||||||
config.id = id;
|
config.id = id;
|
||||||
id_valid = true;
|
id_valid = true;
|
||||||
store |= store2;
|
store |= store2;
|
||||||
} else {
|
} else if crate::get_modified_time(&Self::file_(""))
|
||||||
if crate::get_modified_time(&Self::file_(""))
|
|
||||||
.checked_sub(std::time::Duration::from_secs(30)) // allow modification during installation
|
.checked_sub(std::time::Duration::from_secs(30)) // allow modification during installation
|
||||||
.unwrap_or(crate::get_exe_time())
|
.unwrap_or_else(crate::get_exe_time)
|
||||||
< crate::get_exe_time()
|
< crate::get_exe_time()
|
||||||
{
|
&& !config.id.is_empty()
|
||||||
if !config.id.is_empty()
|
|
||||||
&& config.enc_id.is_empty()
|
&& config.enc_id.is_empty()
|
||||||
&& !decrypt_str_or_original(&config.id, PASSWORD_ENC_VERSION).1
|
&& !decrypt_str_or_original(&config.id, PASSWORD_ENC_VERSION).1
|
||||||
{
|
{
|
||||||
id_valid = true;
|
id_valid = true;
|
||||||
store = true;
|
store = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
if !id_valid {
|
if !id_valid {
|
||||||
for _ in 0..3 {
|
for _ in 0..3 {
|
||||||
if let Some(id) = Config::get_auto_id() {
|
if let Some(id) = Config::get_auto_id() {
|
||||||
@ -441,13 +438,13 @@ impl Config {
|
|||||||
let org = ORG.read().unwrap().clone();
|
let org = ORG.read().unwrap().clone();
|
||||||
// /var/root for root
|
// /var/root for root
|
||||||
if let Some(project) =
|
if let Some(project) =
|
||||||
directories_next::ProjectDirs::from("", &org, &*APP_NAME.read().unwrap())
|
directories_next::ProjectDirs::from("", org, &APP_NAME.read().unwrap())
|
||||||
{
|
{
|
||||||
let mut path = patch(project.config_dir().to_path_buf());
|
let mut path = patch(project.config_dir().to_path_buf());
|
||||||
path.push(p);
|
path.push(p);
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
return "".into();
|
"".into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,9 +528,9 @@ impl Config {
|
|||||||
rendezvous_server = Self::get_rendezvous_servers()
|
rendezvous_server = Self::get_rendezvous_servers()
|
||||||
.drain(..)
|
.drain(..)
|
||||||
.next()
|
.next()
|
||||||
.unwrap_or("".to_owned());
|
.unwrap_or_default();
|
||||||
}
|
}
|
||||||
if !rendezvous_server.contains(":") {
|
if !rendezvous_server.contains(':') {
|
||||||
rendezvous_server = format!("{}:{}", rendezvous_server, RENDEZVOUS_PORT);
|
rendezvous_server = format!("{}:{}", rendezvous_server, RENDEZVOUS_PORT);
|
||||||
}
|
}
|
||||||
rendezvous_server
|
rendezvous_server
|
||||||
@ -551,8 +548,8 @@ impl Config {
|
|||||||
let serial_obsolute = CONFIG2.read().unwrap().serial > SERIAL;
|
let serial_obsolute = CONFIG2.read().unwrap().serial > SERIAL;
|
||||||
if serial_obsolute {
|
if serial_obsolute {
|
||||||
let ss: Vec<String> = Self::get_option("rendezvous-servers")
|
let ss: Vec<String> = Self::get_option("rendezvous-servers")
|
||||||
.split(",")
|
.split(',')
|
||||||
.filter(|x| x.contains("."))
|
.filter(|x| x.contains('.'))
|
||||||
.map(|x| x.to_owned())
|
.map(|x| x.to_owned())
|
||||||
.collect();
|
.collect();
|
||||||
if !ss.is_empty() {
|
if !ss.is_empty() {
|
||||||
@ -572,7 +569,7 @@ impl Config {
|
|||||||
let mut delay = i64::MAX;
|
let mut delay = i64::MAX;
|
||||||
for (tmp_host, tmp_delay) in ONLINE.lock().unwrap().iter() {
|
for (tmp_host, tmp_delay) in ONLINE.lock().unwrap().iter() {
|
||||||
if tmp_delay > &0 && tmp_delay < &delay {
|
if tmp_delay > &0 && tmp_delay < &delay {
|
||||||
delay = tmp_delay.clone();
|
delay = *tmp_delay;
|
||||||
host = tmp_host.to_string();
|
host = tmp_host.to_string();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -639,7 +636,7 @@ impl Config {
|
|||||||
for x in &ma.bytes()[2..] {
|
for x in &ma.bytes()[2..] {
|
||||||
id = (id << 8) | (*x as u32);
|
id = (id << 8) | (*x as u32);
|
||||||
}
|
}
|
||||||
id = id & 0x1FFFFFFF;
|
id &= 0x1FFFFFFF;
|
||||||
Some(id.to_string())
|
Some(id.to_string())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -671,11 +668,7 @@ impl Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_host_key_confirmed(host: &str) -> bool {
|
pub fn get_host_key_confirmed(host: &str) -> bool {
|
||||||
if let Some(true) = CONFIG.read().unwrap().keys_confirmed.get(host) {
|
matches!(CONFIG.read().unwrap().keys_confirmed.get(host), Some(true))
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_host_key_confirmed(host: &str, v: bool) {
|
pub fn set_host_key_confirmed(host: &str, v: bool) {
|
||||||
@ -687,7 +680,7 @@ impl Config {
|
|||||||
config.store();
|
config.store();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_key_pair() -> (Vec<u8>, Vec<u8>) {
|
pub fn get_key_pair() -> KeyPair {
|
||||||
// lock here to make sure no gen_keypair more than once
|
// lock here to make sure no gen_keypair more than once
|
||||||
// no use of CONFIG directly here to ensure no recursive calling in Config::load because of password dec which calling this function
|
// no use of CONFIG directly here to ensure no recursive calling in Config::load because of password dec which calling this function
|
||||||
let mut lock = KEY_PAIR.lock().unwrap();
|
let mut lock = KEY_PAIR.lock().unwrap();
|
||||||
@ -706,7 +699,7 @@ impl Config {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
*lock = Some(config.key_pair.clone());
|
*lock = Some(config.key_pair.clone());
|
||||||
return config.key_pair;
|
config.key_pair
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_id() -> String {
|
pub fn get_id() -> String {
|
||||||
@ -841,7 +834,7 @@ impl Config {
|
|||||||
let ext = path.extension();
|
let ext = path.extension();
|
||||||
if let Some(ext) = ext {
|
if let Some(ext) = ext {
|
||||||
let ext = format!("{}.toml", ext.to_string_lossy());
|
let ext = format!("{}.toml", ext.to_string_lossy());
|
||||||
path.with_extension(&ext)
|
path.with_extension(ext)
|
||||||
} else {
|
} else {
|
||||||
path.with_extension("toml")
|
path.with_extension("toml")
|
||||||
}
|
}
|
||||||
@ -853,7 +846,7 @@ const PEERS: &str = "peers";
|
|||||||
impl PeerConfig {
|
impl PeerConfig {
|
||||||
pub fn load(id: &str) -> PeerConfig {
|
pub fn load(id: &str) -> PeerConfig {
|
||||||
let _lock = CONFIG.read().unwrap();
|
let _lock = CONFIG.read().unwrap();
|
||||||
match confy::load_path(&Self::path(id)) {
|
match confy::load_path(Self::path(id)) {
|
||||||
Ok(config) => {
|
Ok(config) => {
|
||||||
let mut config: PeerConfig = config;
|
let mut config: PeerConfig = config;
|
||||||
let mut store = false;
|
let mut store = false;
|
||||||
@ -861,16 +854,16 @@ impl PeerConfig {
|
|||||||
decrypt_vec_or_original(&config.password, PASSWORD_ENC_VERSION);
|
decrypt_vec_or_original(&config.password, PASSWORD_ENC_VERSION);
|
||||||
config.password = password;
|
config.password = password;
|
||||||
store = store || store2;
|
store = store || store2;
|
||||||
config.options.get_mut("rdp_password").map(|v| {
|
if let Some(v) = config.options.get_mut("rdp_password") {
|
||||||
let (password, _, store2) = decrypt_str_or_original(v, PASSWORD_ENC_VERSION);
|
let (password, _, store2) = decrypt_str_or_original(v, PASSWORD_ENC_VERSION);
|
||||||
*v = password;
|
*v = password;
|
||||||
store = store || store2;
|
store = store || store2;
|
||||||
});
|
}
|
||||||
config.options.get_mut("os-password").map(|v| {
|
if let Some(v) = config.options.get_mut("os-password") {
|
||||||
let (password, _, store2) = decrypt_str_or_original(v, PASSWORD_ENC_VERSION);
|
let (password, _, store2) = decrypt_str_or_original(v, PASSWORD_ENC_VERSION);
|
||||||
*v = password;
|
*v = password;
|
||||||
store = store || store2;
|
store = store || store2;
|
||||||
});
|
}
|
||||||
if store {
|
if store {
|
||||||
config.store(id);
|
config.store(id);
|
||||||
}
|
}
|
||||||
@ -887,34 +880,29 @@ impl PeerConfig {
|
|||||||
let _lock = CONFIG.read().unwrap();
|
let _lock = CONFIG.read().unwrap();
|
||||||
let mut config = self.clone();
|
let mut config = self.clone();
|
||||||
config.password = encrypt_vec_or_original(&config.password, PASSWORD_ENC_VERSION);
|
config.password = encrypt_vec_or_original(&config.password, PASSWORD_ENC_VERSION);
|
||||||
config
|
if let Some(v) = config.options.get_mut("rdp_password") {
|
||||||
.options
|
*v = encrypt_str_or_original(v, PASSWORD_ENC_VERSION)
|
||||||
.get_mut("rdp_password")
|
}
|
||||||
.map(|v| *v = encrypt_str_or_original(v, PASSWORD_ENC_VERSION));
|
if let Some(v) = config.options.get_mut("os-password") {
|
||||||
config
|
*v = encrypt_str_or_original(v, PASSWORD_ENC_VERSION)
|
||||||
.options
|
};
|
||||||
.get_mut("os-password")
|
|
||||||
.map(|v| *v = encrypt_str_or_original(v, PASSWORD_ENC_VERSION));
|
|
||||||
if let Err(err) = store_path(Self::path(id), config) {
|
if let Err(err) = store_path(Self::path(id), config) {
|
||||||
log::error!("Failed to store config: {}", err);
|
log::error!("Failed to store config: {}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove(id: &str) {
|
pub fn remove(id: &str) {
|
||||||
fs::remove_file(&Self::path(id)).ok();
|
fs::remove_file(Self::path(id)).ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn path(id: &str) -> PathBuf {
|
fn path(id: &str) -> PathBuf {
|
||||||
let id_encoded: String;
|
|
||||||
|
|
||||||
//If the id contains invalid chars, encode it
|
//If the id contains invalid chars, encode it
|
||||||
let forbidden_paths = Regex::new(r".*[<>:/\\|\?\*].*").unwrap();
|
let forbidden_paths = Regex::new(r".*[<>:/\\|\?\*].*").unwrap();
|
||||||
if forbidden_paths.is_match(id) {
|
let id_encoded = if forbidden_paths.is_match(id) {
|
||||||
id_encoded =
|
"base64_".to_string() + base64::encode(id, base64::Variant::Original).as_str()
|
||||||
"base64_".to_string() + base64::encode(id, base64::Variant::Original).as_str();
|
|
||||||
} else {
|
} else {
|
||||||
id_encoded = id.to_string();
|
id.to_string()
|
||||||
}
|
};
|
||||||
let path: PathBuf = [PEERS, id_encoded.as_str()].iter().collect();
|
let path: PathBuf = [PEERS, id_encoded.as_str()].iter().collect();
|
||||||
Config::with_extension(Config::path(path))
|
Config::with_extension(Config::path(path))
|
||||||
}
|
}
|
||||||
@ -932,26 +920,24 @@ impl PeerConfig {
|
|||||||
&& p.extension().map(|p| p.to_str().unwrap_or("")) == Some("toml")
|
&& p.extension().map(|p| p.to_str().unwrap_or("")) == Some("toml")
|
||||||
})
|
})
|
||||||
.map(|p| {
|
.map(|p| {
|
||||||
let t = crate::get_modified_time(&p);
|
let t = crate::get_modified_time(p);
|
||||||
let id = p
|
let id = p
|
||||||
.file_stem()
|
.file_stem()
|
||||||
.map(|p| p.to_str().unwrap_or(""))
|
.map(|p| p.to_str().unwrap_or(""))
|
||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
.to_owned();
|
.to_owned();
|
||||||
|
|
||||||
let id_decoded_string: String;
|
let id_decoded_string = if id.starts_with("base64_") && id.len() != 7 {
|
||||||
if id.starts_with("base64_") && id.len() != 7 {
|
|
||||||
let id_decoded = base64::decode(&id[7..], base64::Variant::Original)
|
let id_decoded = base64::decode(&id[7..], base64::Variant::Original)
|
||||||
.unwrap_or(Vec::new());
|
.unwrap_or_default();
|
||||||
id_decoded_string =
|
String::from_utf8_lossy(&id_decoded).as_ref().to_owned()
|
||||||
String::from_utf8_lossy(&id_decoded).as_ref().to_owned();
|
|
||||||
} else {
|
} else {
|
||||||
id_decoded_string = id;
|
id
|
||||||
}
|
};
|
||||||
|
|
||||||
let c = PeerConfig::load(&id_decoded_string);
|
let c = PeerConfig::load(&id_decoded_string);
|
||||||
if c.info.platform.is_empty() {
|
if c.info.platform.is_empty() {
|
||||||
fs::remove_file(&p).ok();
|
fs::remove_file(p).ok();
|
||||||
}
|
}
|
||||||
(id_decoded_string, t, c)
|
(id_decoded_string, t, c)
|
||||||
})
|
})
|
||||||
@ -1141,7 +1127,7 @@ pub struct LanPeers {
|
|||||||
impl LanPeers {
|
impl LanPeers {
|
||||||
pub fn load() -> LanPeers {
|
pub fn load() -> LanPeers {
|
||||||
let _lock = CONFIG.read().unwrap();
|
let _lock = CONFIG.read().unwrap();
|
||||||
match confy::load_path(&Config::file_("_lan_peers")) {
|
match confy::load_path(Config::file_("_lan_peers")) {
|
||||||
Ok(peers) => peers,
|
Ok(peers) => peers,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
log::error!("Failed to load lan peers: {}", err);
|
log::error!("Failed to load lan peers: {}", err);
|
||||||
@ -1150,9 +1136,9 @@ impl LanPeers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn store(peers: &Vec<DiscoveryPeer>) {
|
pub fn store(peers: &[DiscoveryPeer]) {
|
||||||
let f = LanPeers {
|
let f = LanPeers {
|
||||||
peers: peers.clone(),
|
peers: peers.to_owned(),
|
||||||
};
|
};
|
||||||
if let Err(err) = store_path(Config::file_("_lan_peers"), f) {
|
if let Err(err) = store_path(Config::file_("_lan_peers"), f) {
|
||||||
log::error!("Failed to store lan peers: {}", err);
|
log::error!("Failed to store lan peers: {}", err);
|
||||||
|
@ -13,13 +13,13 @@ use crate::{
|
|||||||
config::{Config, COMPRESS_LEVEL},
|
config::{Config, COMPRESS_LEVEL},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn read_dir(path: &PathBuf, include_hidden: bool) -> ResultType<FileDirectory> {
|
pub fn read_dir(path: &Path, include_hidden: bool) -> ResultType<FileDirectory> {
|
||||||
let mut dir = FileDirectory {
|
let mut dir = FileDirectory {
|
||||||
path: get_string(&path),
|
path: get_string(path),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
if "/" == &get_string(&path) {
|
if "/" == &get_string(path) {
|
||||||
let drives = unsafe { winapi::um::fileapi::GetLogicalDrives() };
|
let drives = unsafe { winapi::um::fileapi::GetLogicalDrives() };
|
||||||
for i in 0..32 {
|
for i in 0..32 {
|
||||||
if drives & (1 << i) != 0 {
|
if drives & (1 << i) != 0 {
|
||||||
@ -36,8 +36,7 @@ pub fn read_dir(path: &PathBuf, include_hidden: bool) -> ResultType<FileDirector
|
|||||||
}
|
}
|
||||||
return Ok(dir);
|
return Ok(dir);
|
||||||
}
|
}
|
||||||
for entry in path.read_dir()? {
|
for entry in path.read_dir()?.flatten() {
|
||||||
if let Ok(entry) = entry {
|
|
||||||
let p = entry.path();
|
let p = entry.path();
|
||||||
let name = p
|
let name = p
|
||||||
.file_name()
|
.file_name()
|
||||||
@ -73,13 +72,11 @@ pub fn read_dir(path: &PathBuf, include_hidden: bool) -> ResultType<FileDirector
|
|||||||
} else {
|
} else {
|
||||||
(FileType::Dir.into(), 0)
|
(FileType::Dir.into(), 0)
|
||||||
}
|
}
|
||||||
} else {
|
} else if meta.file_type().is_symlink() {
|
||||||
if meta.file_type().is_symlink() {
|
|
||||||
(FileType::FileLink.into(), 0)
|
(FileType::FileLink.into(), 0)
|
||||||
} else {
|
} else {
|
||||||
(FileType::File.into(), meta.len())
|
(FileType::File.into(), meta.len())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
let modified_time = meta
|
let modified_time = meta
|
||||||
.modified()
|
.modified()
|
||||||
@ -88,7 +85,7 @@ pub fn read_dir(path: &PathBuf, include_hidden: bool) -> ResultType<FileDirector
|
|||||||
.map(|x| x.as_secs())
|
.map(|x| x.as_secs())
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
})
|
})
|
||||||
.unwrap_or(0) as u64;
|
.unwrap_or(0);
|
||||||
dir.entries.push(FileEntry {
|
dir.entries.push(FileEntry {
|
||||||
name: get_file_name(&p),
|
name: get_file_name(&p),
|
||||||
entry_type,
|
entry_type,
|
||||||
@ -98,12 +95,11 @@ pub fn read_dir(path: &PathBuf, include_hidden: bool) -> ResultType<FileDirector
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(dir)
|
Ok(dir)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_file_name(p: &PathBuf) -> String {
|
pub fn get_file_name(p: &Path) -> String {
|
||||||
p.file_name()
|
p.file_name()
|
||||||
.map(|p| p.to_str().unwrap_or(""))
|
.map(|p| p.to_str().unwrap_or(""))
|
||||||
.unwrap_or("")
|
.unwrap_or("")
|
||||||
@ -111,7 +107,7 @@ pub fn get_file_name(p: &PathBuf) -> String {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_string(path: &PathBuf) -> String {
|
pub fn get_string(path: &Path) -> String {
|
||||||
path.to_str().unwrap_or("").to_owned()
|
path.to_str().unwrap_or("").to_owned()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,14 +123,14 @@ pub fn get_home_as_string() -> String {
|
|||||||
|
|
||||||
fn read_dir_recursive(
|
fn read_dir_recursive(
|
||||||
path: &PathBuf,
|
path: &PathBuf,
|
||||||
prefix: &PathBuf,
|
prefix: &Path,
|
||||||
include_hidden: bool,
|
include_hidden: bool,
|
||||||
) -> ResultType<Vec<FileEntry>> {
|
) -> ResultType<Vec<FileEntry>> {
|
||||||
let mut files = Vec::new();
|
let mut files = Vec::new();
|
||||||
if path.is_dir() {
|
if path.is_dir() {
|
||||||
// to-do: symbol link handling, cp the link rather than the content
|
// to-do: symbol link handling, cp the link rather than the content
|
||||||
// to-do: file mode, for unix
|
// to-do: file mode, for unix
|
||||||
let fd = read_dir(&path, include_hidden)?;
|
let fd = read_dir(path, include_hidden)?;
|
||||||
for entry in fd.entries.iter() {
|
for entry in fd.entries.iter() {
|
||||||
match entry.entry_type.enum_value() {
|
match entry.entry_type.enum_value() {
|
||||||
Ok(FileType::File) => {
|
Ok(FileType::File) => {
|
||||||
@ -158,7 +154,7 @@ fn read_dir_recursive(
|
|||||||
}
|
}
|
||||||
Ok(files)
|
Ok(files)
|
||||||
} else if path.is_file() {
|
} else if path.is_file() {
|
||||||
let (size, modified_time) = if let Ok(meta) = std::fs::metadata(&path) {
|
let (size, modified_time) = if let Ok(meta) = std::fs::metadata(path) {
|
||||||
(
|
(
|
||||||
meta.len(),
|
meta.len(),
|
||||||
meta.modified()
|
meta.modified()
|
||||||
@ -167,7 +163,7 @@ fn read_dir_recursive(
|
|||||||
.map(|x| x.as_secs())
|
.map(|x| x.as_secs())
|
||||||
.unwrap_or(0)
|
.unwrap_or(0)
|
||||||
})
|
})
|
||||||
.unwrap_or(0) as u64,
|
.unwrap_or(0),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
(0, 0)
|
(0, 0)
|
||||||
@ -249,7 +245,7 @@ pub struct RemoveJobMeta {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn get_ext(name: &str) -> &str {
|
fn get_ext(name: &str) -> &str {
|
||||||
if let Some(i) = name.rfind(".") {
|
if let Some(i) = name.rfind('.') {
|
||||||
return &name[i + 1..];
|
return &name[i + 1..];
|
||||||
}
|
}
|
||||||
""
|
""
|
||||||
@ -270,6 +266,7 @@ fn is_compressed_file(name: &str) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl TransferJob {
|
impl TransferJob {
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new_write(
|
pub fn new_write(
|
||||||
id: i32,
|
id: i32,
|
||||||
remote: String,
|
remote: String,
|
||||||
@ -281,7 +278,7 @@ impl TransferJob {
|
|||||||
enable_overwrite_detection: bool,
|
enable_overwrite_detection: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
log::info!("new write {}", path);
|
log::info!("new write {}", path);
|
||||||
let total_size = files.iter().map(|x| x.size as u64).sum();
|
let total_size = files.iter().map(|x| x.size).sum();
|
||||||
Self {
|
Self {
|
||||||
id,
|
id,
|
||||||
remote,
|
remote,
|
||||||
@ -307,7 +304,7 @@ impl TransferJob {
|
|||||||
) -> ResultType<Self> {
|
) -> ResultType<Self> {
|
||||||
log::info!("new read {}", path);
|
log::info!("new read {}", path);
|
||||||
let files = get_recursive_files(&path, show_hidden)?;
|
let files = get_recursive_files(&path, show_hidden)?;
|
||||||
let total_size = files.iter().map(|x| x.size as u64).sum();
|
let total_size = files.iter().map(|x| x.size).sum();
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
id,
|
id,
|
||||||
remote,
|
remote,
|
||||||
@ -363,7 +360,7 @@ impl TransferJob {
|
|||||||
let entry = &self.files[file_num];
|
let entry = &self.files[file_num];
|
||||||
let path = self.join(&entry.name);
|
let path = self.join(&entry.name);
|
||||||
let download_path = format!("{}.download", get_string(&path));
|
let download_path = format!("{}.download", get_string(&path));
|
||||||
std::fs::rename(&download_path, &path).ok();
|
std::fs::rename(download_path, &path).ok();
|
||||||
filetime::set_file_mtime(
|
filetime::set_file_mtime(
|
||||||
&path,
|
&path,
|
||||||
filetime::FileTime::from_unix_time(entry.modified_time as _, 0),
|
filetime::FileTime::from_unix_time(entry.modified_time as _, 0),
|
||||||
@ -378,7 +375,7 @@ impl TransferJob {
|
|||||||
let entry = &self.files[file_num];
|
let entry = &self.files[file_num];
|
||||||
let path = self.join(&entry.name);
|
let path = self.join(&entry.name);
|
||||||
let download_path = format!("{}.download", get_string(&path));
|
let download_path = format!("{}.download", get_string(&path));
|
||||||
std::fs::remove_file(&download_path).ok();
|
std::fs::remove_file(download_path).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -433,7 +430,7 @@ impl TransferJob {
|
|||||||
}
|
}
|
||||||
let name = &self.files[file_num].name;
|
let name = &self.files[file_num].name;
|
||||||
if self.file.is_none() {
|
if self.file.is_none() {
|
||||||
match File::open(self.join(&name)).await {
|
match File::open(self.join(name)).await {
|
||||||
Ok(file) => {
|
Ok(file) => {
|
||||||
self.file = Some(file);
|
self.file = Some(file);
|
||||||
self.file_confirmed = false;
|
self.file_confirmed = false;
|
||||||
@ -447,20 +444,15 @@ impl TransferJob {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if self.enable_overwrite_detection {
|
if self.enable_overwrite_detection && !self.file_confirmed() {
|
||||||
if !self.file_confirmed() {
|
|
||||||
if !self.file_is_waiting() {
|
if !self.file_is_waiting() {
|
||||||
self.send_current_digest(stream).await?;
|
self.send_current_digest(stream).await?;
|
||||||
self.set_file_is_waiting(true);
|
self.set_file_is_waiting(true);
|
||||||
}
|
}
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
const BUF_SIZE: usize = 128 * 1024;
|
const BUF_SIZE: usize = 128 * 1024;
|
||||||
let mut buf: Vec<u8> = Vec::with_capacity(BUF_SIZE);
|
let mut buf: Vec<u8> = vec![0; BUF_SIZE];
|
||||||
unsafe {
|
|
||||||
buf.set_len(BUF_SIZE);
|
|
||||||
}
|
|
||||||
let mut compressed = false;
|
let mut compressed = false;
|
||||||
let mut offset: usize = 0;
|
let mut offset: usize = 0;
|
||||||
loop {
|
loop {
|
||||||
@ -582,10 +574,7 @@ impl TransferJob {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn job_completed(&self) -> bool {
|
pub fn job_completed(&self) -> bool {
|
||||||
// has no error, Condition 2
|
// has no error, Condition 2
|
||||||
if !self.enable_overwrite_detection || (!self.file_confirmed && !self.file_is_waiting) {
|
!self.enable_overwrite_detection || (!self.file_confirmed && !self.file_is_waiting)
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get job error message, useful for getting status when job had finished
|
/// Get job error message, useful for getting status when job had finished
|
||||||
@ -660,7 +649,7 @@ pub fn new_dir(id: i32, path: String, files: Vec<FileEntry>) -> Message {
|
|||||||
resp.set_dir(FileDirectory {
|
resp.set_dir(FileDirectory {
|
||||||
id,
|
id,
|
||||||
path,
|
path,
|
||||||
entries: files.into(),
|
entries: files,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
let mut msg_out = Message::new();
|
let mut msg_out = Message::new();
|
||||||
@ -692,7 +681,7 @@ pub fn new_receive(id: i32, path: String, file_num: i32, files: Vec<FileEntry>)
|
|||||||
action.set_receive(FileTransferReceiveRequest {
|
action.set_receive(FileTransferReceiveRequest {
|
||||||
id,
|
id,
|
||||||
path,
|
path,
|
||||||
files: files.into(),
|
files,
|
||||||
file_num,
|
file_num,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
@ -736,8 +725,8 @@ pub fn remove_job(id: i32, jobs: &mut Vec<TransferJob>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_job(id: i32, jobs: &mut Vec<TransferJob>) -> Option<&mut TransferJob> {
|
pub fn get_job(id: i32, jobs: &mut [TransferJob]) -> Option<&mut TransferJob> {
|
||||||
jobs.iter_mut().filter(|x| x.id() == id).next()
|
jobs.iter_mut().find(|x| x.id() == id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn handle_read_jobs(
|
pub async fn handle_read_jobs(
|
||||||
@ -789,7 +778,7 @@ pub fn remove_all_empty_dir(path: &PathBuf) -> ResultType<()> {
|
|||||||
remove_all_empty_dir(&path.join(&entry.name)).ok();
|
remove_all_empty_dir(&path.join(&entry.name)).ok();
|
||||||
}
|
}
|
||||||
Ok(FileType::DirLink) | Ok(FileType::FileLink) => {
|
Ok(FileType::DirLink) | Ok(FileType::FileLink) => {
|
||||||
std::fs::remove_file(&path.join(&entry.name)).ok();
|
std::fs::remove_file(path.join(&entry.name)).ok();
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
@ -813,7 +802,7 @@ pub fn create_dir(dir: &str) -> ResultType<()> {
|
|||||||
#[inline]
|
#[inline]
|
||||||
pub fn transform_windows_path(entries: &mut Vec<FileEntry>) {
|
pub fn transform_windows_path(entries: &mut Vec<FileEntry>) {
|
||||||
for entry in entries {
|
for entry in entries {
|
||||||
entry.name = entry.name.replace("\\", "/");
|
entry.name = entry.name.replace('\\', "/");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,22 +128,20 @@ impl AddrMangle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode(bytes: &[u8]) -> SocketAddr {
|
pub fn decode(bytes: &[u8]) -> SocketAddr {
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
if bytes.len() > 16 {
|
if bytes.len() > 16 {
|
||||||
if bytes.len() != 18 {
|
if bytes.len() != 18 {
|
||||||
return Config::get_any_listen_addr(false);
|
return Config::get_any_listen_addr(false);
|
||||||
}
|
}
|
||||||
#[allow(invalid_value)]
|
let tmp: [u8; 2] = bytes[16..].try_into().unwrap();
|
||||||
let mut tmp: [u8; 2] = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
|
|
||||||
tmp.copy_from_slice(&bytes[16..]);
|
|
||||||
let port = u16::from_le_bytes(tmp);
|
let port = u16::from_le_bytes(tmp);
|
||||||
#[allow(invalid_value)]
|
let tmp: [u8; 16] = bytes[..16].try_into().unwrap();
|
||||||
let mut tmp: [u8; 16] = unsafe { std::mem::MaybeUninit::uninit().assume_init() };
|
|
||||||
tmp.copy_from_slice(&bytes[..16]);
|
|
||||||
let ip = std::net::Ipv6Addr::from(tmp);
|
let ip = std::net::Ipv6Addr::from(tmp);
|
||||||
return SocketAddr::new(IpAddr::V6(ip), port);
|
return SocketAddr::new(IpAddr::V6(ip), port);
|
||||||
}
|
}
|
||||||
let mut padded = [0u8; 16];
|
let mut padded = [0u8; 16];
|
||||||
padded[..bytes.len()].copy_from_slice(&bytes);
|
padded[..bytes.len()].copy_from_slice(bytes);
|
||||||
let number = u128::from_le_bytes(padded);
|
let number = u128::from_le_bytes(padded);
|
||||||
let tm = (number >> 17) & (u32::max_value() as u128);
|
let tm = (number >> 17) & (u32::max_value() as u128);
|
||||||
let ip = (((number >> 49) - tm) as u32).to_le_bytes();
|
let ip = (((number >> 49) - tm) as u32).to_le_bytes();
|
||||||
@ -157,21 +155,9 @@ impl AddrMangle {
|
|||||||
|
|
||||||
pub fn get_version_from_url(url: &str) -> String {
|
pub fn get_version_from_url(url: &str) -> String {
|
||||||
let n = url.chars().count();
|
let n = url.chars().count();
|
||||||
let a = url
|
let a = url.chars().rev().position(|x| x == '-');
|
||||||
.chars()
|
|
||||||
.rev()
|
|
||||||
.enumerate()
|
|
||||||
.filter(|(_, x)| x == &'-')
|
|
||||||
.next()
|
|
||||||
.map(|(i, _)| i);
|
|
||||||
if let Some(a) = a {
|
if let Some(a) = a {
|
||||||
let b = url
|
let b = url.chars().rev().position(|x| x == '.');
|
||||||
.chars()
|
|
||||||
.rev()
|
|
||||||
.enumerate()
|
|
||||||
.filter(|(_, x)| x == &'.')
|
|
||||||
.next()
|
|
||||||
.map(|(i, _)| i);
|
|
||||||
if let Some(b) = b {
|
if let Some(b) = b {
|
||||||
if a > b {
|
if a > b {
|
||||||
if url
|
if url
|
||||||
@ -196,19 +182,23 @@ pub fn get_version_from_url(url: &str) -> String {
|
|||||||
pub fn gen_version() {
|
pub fn gen_version() {
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
let mut file = File::create("./src/version.rs").unwrap();
|
let mut file = File::create("./src/version.rs").unwrap();
|
||||||
for line in read_lines("Cargo.toml").unwrap() {
|
for line in read_lines("Cargo.toml").unwrap().flatten() {
|
||||||
if let Ok(line) = line {
|
let ab: Vec<&str> = line.split('=').map(|x| x.trim()).collect();
|
||||||
let ab: Vec<&str> = line.split("=").map(|x| x.trim()).collect();
|
|
||||||
if ab.len() == 2 && ab[0] == "version" {
|
if ab.len() == 2 && ab[0] == "version" {
|
||||||
file.write_all(format!("pub const VERSION: &str = {};\n", ab[1]).as_bytes())
|
file.write_all(format!("pub const VERSION: &str = {};\n", ab[1]).as_bytes())
|
||||||
.ok();
|
.ok();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// generate build date
|
// generate build date
|
||||||
let build_date = format!("{}", chrono::Local::now().format("%Y-%m-%d %H:%M"));
|
let build_date = format!("{}", chrono::Local::now().format("%Y-%m-%d %H:%M"));
|
||||||
file.write_all(format!("pub const BUILD_DATE: &str = \"{}\";", build_date).as_bytes())
|
file.write_all(
|
||||||
|
format!(
|
||||||
|
"#[allow(dead_code)]\npub const BUILD_DATE: &str = \"{}\";",
|
||||||
|
build_date
|
||||||
|
)
|
||||||
|
.as_bytes(),
|
||||||
|
)
|
||||||
.ok();
|
.ok();
|
||||||
file.sync_all().ok();
|
file.sync_all().ok();
|
||||||
}
|
}
|
||||||
@ -229,20 +219,20 @@ pub fn is_valid_custom_id(id: &str) -> bool {
|
|||||||
|
|
||||||
pub fn get_version_number(v: &str) -> i64 {
|
pub fn get_version_number(v: &str) -> i64 {
|
||||||
let mut n = 0;
|
let mut n = 0;
|
||||||
for x in v.split(".") {
|
for x in v.split('.') {
|
||||||
n = n * 1000 + x.parse::<i64>().unwrap_or(0);
|
n = n * 1000 + x.parse::<i64>().unwrap_or(0);
|
||||||
}
|
}
|
||||||
n
|
n
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_modified_time(path: &std::path::Path) -> SystemTime {
|
pub fn get_modified_time(path: &std::path::Path) -> SystemTime {
|
||||||
std::fs::metadata(&path)
|
std::fs::metadata(path)
|
||||||
.map(|m| m.modified().unwrap_or(UNIX_EPOCH))
|
.map(|m| m.modified().unwrap_or(UNIX_EPOCH))
|
||||||
.unwrap_or(UNIX_EPOCH)
|
.unwrap_or(UNIX_EPOCH)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_created_time(path: &std::path::Path) -> SystemTime {
|
pub fn get_created_time(path: &std::path::Path) -> SystemTime {
|
||||||
std::fs::metadata(&path)
|
std::fs::metadata(path)
|
||||||
.map(|m| m.created().unwrap_or(UNIX_EPOCH))
|
.map(|m| m.created().unwrap_or(UNIX_EPOCH))
|
||||||
.unwrap_or(UNIX_EPOCH)
|
.unwrap_or(UNIX_EPOCH)
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ pub fn decrypt_str_or_original(s: &str, current_version: &str) -> (String, bool,
|
|||||||
if s.len() > VERSION_LEN {
|
if s.len() > VERSION_LEN {
|
||||||
let version = &s[..VERSION_LEN];
|
let version = &s[..VERSION_LEN];
|
||||||
if version == "00" {
|
if version == "00" {
|
||||||
if let Ok(v) = decrypt(&s[VERSION_LEN..].as_bytes()) {
|
if let Ok(v) = decrypt(s[VERSION_LEN..].as_bytes()) {
|
||||||
return (
|
return (
|
||||||
String::from_utf8_lossy(&v).to_string(),
|
String::from_utf8_lossy(&v).to_string(),
|
||||||
true,
|
true,
|
||||||
@ -149,7 +149,7 @@ pub fn decrypt_vec_or_original(v: &[u8], current_version: &str) -> (Vec<u8>, boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn encrypt(v: &[u8]) -> Result<String, ()> {
|
fn encrypt(v: &[u8]) -> Result<String, ()> {
|
||||||
if v.len() > 0 {
|
if !v.is_empty() {
|
||||||
symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original))
|
symmetric_crypt(v, true).map(|v| base64::encode(v, base64::Variant::Original))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
@ -157,7 +157,7 @@ fn encrypt(v: &[u8]) -> Result<String, ()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn decrypt(v: &[u8]) -> Result<Vec<u8>, ()> {
|
fn decrypt(v: &[u8]) -> Result<Vec<u8>, ()> {
|
||||||
if v.len() > 0 {
|
if !v.is_empty() {
|
||||||
base64::decode(v, base64::Variant::Original).and_then(|v| symmetric_crypt(&v, false))
|
base64::decode(v, base64::Variant::Original).and_then(|v| symmetric_crypt(&v, false))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
|
@ -32,7 +32,7 @@ pub fn get_display_server() -> String {
|
|||||||
// loginctl has not given the expected output. try something else.
|
// loginctl has not given the expected output. try something else.
|
||||||
if let Ok(sid) = std::env::var("XDG_SESSION_ID") {
|
if let Ok(sid) = std::env::var("XDG_SESSION_ID") {
|
||||||
// could also execute "cat /proc/self/sessionid"
|
// could also execute "cat /proc/self/sessionid"
|
||||||
session = sid.to_owned();
|
session = sid;
|
||||||
}
|
}
|
||||||
if session.is_empty() {
|
if session.is_empty() {
|
||||||
session = run_cmds("cat /proc/self/sessionid".to_owned()).unwrap_or_default();
|
session = run_cmds("cat /proc/self/sessionid".to_owned()).unwrap_or_default();
|
||||||
@ -63,7 +63,7 @@ fn get_display_server_of_session(session: &str) -> String {
|
|||||||
if let Ok(xorg_results) = run_cmds(format!("ps -e | grep \"{}.\\\\+Xorg\"", tty))
|
if let Ok(xorg_results) = run_cmds(format!("ps -e | grep \"{}.\\\\+Xorg\"", tty))
|
||||||
// And check if Xorg is running on that tty
|
// And check if Xorg is running on that tty
|
||||||
{
|
{
|
||||||
if xorg_results.trim_end().to_string() != "" {
|
if xorg_results.trim_end() != "" {
|
||||||
// If it is, manually return "x11", otherwise return tty
|
// If it is, manually return "x11", otherwise return tty
|
||||||
return "x11".to_owned();
|
return "x11".to_owned();
|
||||||
}
|
}
|
||||||
@ -88,7 +88,7 @@ pub fn get_values_of_seat0(indices: Vec<usize>) -> Vec<String> {
|
|||||||
if let Ok(output) = run_loginctl(None) {
|
if let Ok(output) = run_loginctl(None) {
|
||||||
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
||||||
if line.contains("seat0") {
|
if line.contains("seat0") {
|
||||||
if let Some(sid) = line.split_whitespace().nth(0) {
|
if let Some(sid) = line.split_whitespace().next() {
|
||||||
if is_active(sid) {
|
if is_active(sid) {
|
||||||
return indices
|
return indices
|
||||||
.into_iter()
|
.into_iter()
|
||||||
@ -103,7 +103,7 @@ pub fn get_values_of_seat0(indices: Vec<usize>) -> Vec<String> {
|
|||||||
// some case, there is no seat0 https://github.com/rustdesk/rustdesk/issues/73
|
// some case, there is no seat0 https://github.com/rustdesk/rustdesk/issues/73
|
||||||
if let Ok(output) = run_loginctl(None) {
|
if let Ok(output) = run_loginctl(None) {
|
||||||
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
for line in String::from_utf8_lossy(&output.stdout).lines() {
|
||||||
if let Some(sid) = line.split_whitespace().nth(0) {
|
if let Some(sid) = line.split_whitespace().next() {
|
||||||
let d = get_display_server_of_session(sid);
|
let d = get_display_server_of_session(sid);
|
||||||
if is_active(sid) && d != "tty" {
|
if is_active(sid) && d != "tty" {
|
||||||
return indices
|
return indices
|
||||||
|
@ -11,7 +11,7 @@ use tokio_socks::{IntoTargetAddr, TargetAddr};
|
|||||||
|
|
||||||
pub fn test_if_valid_server(host: &str) -> String {
|
pub fn test_if_valid_server(host: &str) -> String {
|
||||||
let mut host = host.to_owned();
|
let mut host = host.to_owned();
|
||||||
if !host.contains(":") {
|
if !host.contains(':') {
|
||||||
host = format!("{}:{}", host, 0);
|
host = format!("{}:{}", host, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -34,7 +34,7 @@ pub trait IsResolvedSocketAddr {
|
|||||||
|
|
||||||
impl IsResolvedSocketAddr for SocketAddr {
|
impl IsResolvedSocketAddr for SocketAddr {
|
||||||
fn resolve(&self) -> Option<&SocketAddr> {
|
fn resolve(&self) -> Option<&SocketAddr> {
|
||||||
Some(&self)
|
Some(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -83,12 +83,12 @@ pub async fn connect_tcp_local<
|
|||||||
if let Some(target) = target.resolve() {
|
if let Some(target) = target.resolve() {
|
||||||
if let Some(local) = local {
|
if let Some(local) = local {
|
||||||
if local.is_ipv6() && target.is_ipv4() {
|
if local.is_ipv6() && target.is_ipv4() {
|
||||||
let target = query_nip_io(&target).await?;
|
let target = query_nip_io(target).await?;
|
||||||
return Ok(FramedStream::new(target, Some(local), ms_timeout).await?);
|
return FramedStream::new(target, Some(local), ms_timeout).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(FramedStream::new(target, local, ms_timeout).await?)
|
FramedStream::new(target, local, ms_timeout).await
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
@ -103,15 +103,14 @@ pub fn is_ipv4(target: &TargetAddr<'_>) -> bool {
|
|||||||
pub async fn query_nip_io(addr: &SocketAddr) -> ResultType<SocketAddr> {
|
pub async fn query_nip_io(addr: &SocketAddr) -> ResultType<SocketAddr> {
|
||||||
tokio::net::lookup_host(format!("{}.nip.io:{}", addr.ip(), addr.port()))
|
tokio::net::lookup_host(format!("{}.nip.io:{}", addr.ip(), addr.port()))
|
||||||
.await?
|
.await?
|
||||||
.filter(|x| x.is_ipv6())
|
.find(|x| x.is_ipv6())
|
||||||
.next()
|
|
||||||
.context("Failed to get ipv6 from nip.io")
|
.context("Failed to get ipv6 from nip.io")
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn ipv4_to_ipv6(addr: String, ipv4: bool) -> String {
|
pub fn ipv4_to_ipv6(addr: String, ipv4: bool) -> String {
|
||||||
if !ipv4 && crate::is_ipv4_str(&addr) {
|
if !ipv4 && crate::is_ipv4_str(&addr) {
|
||||||
if let Some(ip) = addr.split(":").next() {
|
if let Some(ip) = addr.split(':').next() {
|
||||||
return addr.replace(ip, &format!("{}.nip.io", ip));
|
return addr.replace(ip, &format!("{}.nip.io", ip));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{bail, bytes_codec::BytesCodec, ResultType};
|
use crate::{bail, bytes_codec::BytesCodec, ResultType};
|
||||||
|
use anyhow::Context as AnyhowCtx;
|
||||||
use bytes::{BufMut, Bytes, BytesMut};
|
use bytes::{BufMut, Bytes, BytesMut};
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use protobuf::Message;
|
use protobuf::Message;
|
||||||
@ -209,7 +210,7 @@ impl FramedStream {
|
|||||||
if let Some(Ok(bytes)) = res.as_mut() {
|
if let Some(Ok(bytes)) = res.as_mut() {
|
||||||
key.2 += 1;
|
key.2 += 1;
|
||||||
let nonce = Self::get_nonce(key.2);
|
let nonce = Self::get_nonce(key.2);
|
||||||
match secretbox::open(&bytes, &nonce, &key.0) {
|
match secretbox::open(bytes, &nonce, &key.0) {
|
||||||
Ok(res) => {
|
Ok(res) => {
|
||||||
bytes.clear();
|
bytes.clear();
|
||||||
bytes.put_slice(&res);
|
bytes.put_slice(&res);
|
||||||
@ -245,16 +246,17 @@ impl FramedStream {
|
|||||||
|
|
||||||
const DEFAULT_BACKLOG: u32 = 128;
|
const DEFAULT_BACKLOG: u32 = 128;
|
||||||
|
|
||||||
#[allow(clippy::never_loop)]
|
|
||||||
pub async fn new_listener<T: ToSocketAddrs>(addr: T, reuse: bool) -> ResultType<TcpListener> {
|
pub async fn new_listener<T: ToSocketAddrs>(addr: T, reuse: bool) -> ResultType<TcpListener> {
|
||||||
if !reuse {
|
if !reuse {
|
||||||
Ok(TcpListener::bind(addr).await?)
|
Ok(TcpListener::bind(addr).await?)
|
||||||
} else {
|
} else {
|
||||||
for addr in lookup_host(&addr).await? {
|
let addr = lookup_host(&addr)
|
||||||
let socket = new_socket(addr, true)?;
|
.await?
|
||||||
return Ok(socket.listen(DEFAULT_BACKLOG)?);
|
.next()
|
||||||
}
|
.context("could not resolve to any address")?;
|
||||||
bail!("could not resolve to any address");
|
new_socket(addr, true)?
|
||||||
|
.listen(DEFAULT_BACKLOG)
|
||||||
|
.map_err(anyhow::Error::msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{bail, ResultType};
|
use crate::ResultType;
|
||||||
use anyhow::anyhow;
|
use anyhow::{anyhow, Context};
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use futures::{SinkExt, StreamExt};
|
use futures::{SinkExt, StreamExt};
|
||||||
use protobuf::Message;
|
use protobuf::Message;
|
||||||
@ -47,29 +47,30 @@ impl FramedSocket {
|
|||||||
Ok(Self::Direct(UdpFramed::new(socket, BytesCodec::new())))
|
Ok(Self::Direct(UdpFramed::new(socket, BytesCodec::new())))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::never_loop)]
|
|
||||||
pub async fn new_reuse<T: std::net::ToSocketAddrs>(addr: T) -> ResultType<Self> {
|
pub async fn new_reuse<T: std::net::ToSocketAddrs>(addr: T) -> ResultType<Self> {
|
||||||
for addr in addr.to_socket_addrs()? {
|
let addr = addr
|
||||||
|
.to_socket_addrs()?
|
||||||
|
.next()
|
||||||
|
.context("could not resolve to any address")?;
|
||||||
let socket = new_socket(addr, true, 0)?.into_udp_socket();
|
let socket = new_socket(addr, true, 0)?.into_udp_socket();
|
||||||
return Ok(Self::Direct(UdpFramed::new(
|
Ok(Self::Direct(UdpFramed::new(
|
||||||
UdpSocket::from_std(socket)?,
|
UdpSocket::from_std(socket)?,
|
||||||
BytesCodec::new(),
|
BytesCodec::new(),
|
||||||
)));
|
)))
|
||||||
}
|
|
||||||
bail!("could not resolve to any address");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new_with_buf_size<T: std::net::ToSocketAddrs>(
|
pub async fn new_with_buf_size<T: std::net::ToSocketAddrs>(
|
||||||
addr: T,
|
addr: T,
|
||||||
buf_size: usize,
|
buf_size: usize,
|
||||||
) -> ResultType<Self> {
|
) -> ResultType<Self> {
|
||||||
for addr in addr.to_socket_addrs()? {
|
let addr = addr
|
||||||
return Ok(Self::Direct(UdpFramed::new(
|
.to_socket_addrs()?
|
||||||
|
.next()
|
||||||
|
.context("could not resolve to any address")?;
|
||||||
|
Ok(Self::Direct(UdpFramed::new(
|
||||||
UdpSocket::from_std(new_socket(addr, false, buf_size)?.into_udp_socket())?,
|
UdpSocket::from_std(new_socket(addr, false, buf_size)?.into_udp_socket())?,
|
||||||
BytesCodec::new(),
|
BytesCodec::new(),
|
||||||
)));
|
)))
|
||||||
}
|
|
||||||
bail!("could not resolve to any address");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn new_proxy<'a, 't, P: ToProxyAddrs, T: ToSocketAddrs>(
|
pub async fn new_proxy<'a, 't, P: ToProxyAddrs, T: ToSocketAddrs>(
|
||||||
@ -104,11 +105,12 @@ impl FramedSocket {
|
|||||||
) -> ResultType<()> {
|
) -> ResultType<()> {
|
||||||
let addr = addr.into_target_addr()?.to_owned();
|
let addr = addr.into_target_addr()?.to_owned();
|
||||||
let send_data = Bytes::from(msg.write_to_bytes()?);
|
let send_data = Bytes::from(msg.write_to_bytes()?);
|
||||||
let _ = match self {
|
match self {
|
||||||
Self::Direct(f) => match addr {
|
Self::Direct(f) => {
|
||||||
TargetAddr::Ip(addr) => f.send((send_data, addr)).await?,
|
if let TargetAddr::Ip(addr) = addr {
|
||||||
_ => {}
|
f.send((send_data, addr)).await?
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Self::ProxySocks(f) => f.send((send_data, addr)).await?,
|
Self::ProxySocks(f) => f.send((send_data, addr)).await?,
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -123,11 +125,12 @@ impl FramedSocket {
|
|||||||
) -> ResultType<()> {
|
) -> ResultType<()> {
|
||||||
let addr = addr.into_target_addr()?.to_owned();
|
let addr = addr.into_target_addr()?.to_owned();
|
||||||
|
|
||||||
let _ = match self {
|
match self {
|
||||||
Self::Direct(f) => match addr {
|
Self::Direct(f) => {
|
||||||
TargetAddr::Ip(addr) => f.send((Bytes::from(msg), addr)).await?,
|
if let TargetAddr::Ip(addr) = addr {
|
||||||
_ => {}
|
f.send((Bytes::from(msg), addr)).await?
|
||||||
},
|
}
|
||||||
|
}
|
||||||
Self::ProxySocks(f) => f.send((Bytes::from(msg), addr)).await?,
|
Self::ProxySocks(f) => f.send((Bytes::from(msg), addr)).await?,
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -12,15 +12,17 @@ use std::{
|
|||||||
time::{Instant, SystemTime},
|
time::{Instant, SystemTime},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(crate) fn get_expired_time() -> Instant {
|
pub(crate) fn get_expired_time() -> Instant {
|
||||||
let now = Instant::now();
|
let now = Instant::now();
|
||||||
now.checked_sub(std::time::Duration::from_secs(3600))
|
now.checked_sub(std::time::Duration::from_secs(3600))
|
||||||
.unwrap_or(now)
|
.unwrap_or(now)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(crate) fn test_if_valid_server(host: &str, name: &str) -> ResultType<SocketAddr> {
|
pub(crate) fn test_if_valid_server(host: &str, name: &str) -> ResultType<SocketAddr> {
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
let res = if host.contains(":") {
|
let res = if host.contains(':') {
|
||||||
host.to_socket_addrs()?.next().context("")
|
host.to_socket_addrs()?.next().context("")
|
||||||
} else {
|
} else {
|
||||||
format!("{}:{}", host, 0)
|
format!("{}:{}", host, 0)
|
||||||
@ -34,9 +36,10 @@ pub(crate) fn test_if_valid_server(host: &str, name: &str) -> ResultType<SocketA
|
|||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub(crate) fn get_servers(s: &str, tag: &str) -> Vec<String> {
|
pub(crate) fn get_servers(s: &str, tag: &str) -> Vec<String> {
|
||||||
let servers: Vec<String> = s
|
let servers: Vec<String> = s
|
||||||
.split(",")
|
.split(',')
|
||||||
.filter(|x| !x.is_empty() && test_if_valid_server(x, tag).is_ok())
|
.filter(|x| !x.is_empty() && test_if_valid_server(x, tag).is_ok())
|
||||||
.map(|x| x.to_owned())
|
.map(|x| x.to_owned())
|
||||||
.collect();
|
.collect();
|
||||||
@ -44,17 +47,19 @@ pub(crate) fn get_servers(s: &str, tag: &str) -> Vec<String> {
|
|||||||
servers
|
servers
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[inline]
|
#[inline]
|
||||||
fn arg_name(name: &str) -> String {
|
fn arg_name(name: &str) -> String {
|
||||||
name.to_uppercase().replace("_", "-")
|
name.to_uppercase().replace('_', "-")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn init_args(args: &str, name: &str, about: &str) {
|
pub fn init_args(args: &str, name: &str, about: &str) {
|
||||||
let matches = App::new(name)
|
let matches = App::new(name)
|
||||||
.version(crate::version::VERSION)
|
.version(crate::version::VERSION)
|
||||||
.author("Purslane Ltd. <info@rustdesk.com>")
|
.author("Purslane Ltd. <info@rustdesk.com>")
|
||||||
.about(about)
|
.about(about)
|
||||||
.args_from_usage(&args)
|
.args_from_usage(args)
|
||||||
.get_matches();
|
.get_matches();
|
||||||
if let Ok(v) = Ini::load_from_file(".env") {
|
if let Ok(v) = Ini::load_from_file(".env") {
|
||||||
if let Some(section) = v.section(None::<String>) {
|
if let Some(section) = v.section(None::<String>) {
|
||||||
@ -79,16 +84,19 @@ pub fn init_args(args: &str, name: &str, about: &str) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_arg(name: &str) -> String {
|
pub fn get_arg(name: &str) -> String {
|
||||||
get_arg_or(name, "".to_owned())
|
get_arg_or(name, "".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn get_arg_or(name: &str, default: String) -> String {
|
pub fn get_arg_or(name: &str, default: String) -> String {
|
||||||
std::env::var(arg_name(name)).unwrap_or(default)
|
std::env::var(arg_name(name)).unwrap_or(default)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn now() -> u64 {
|
pub fn now() -> u64 {
|
||||||
SystemTime::now()
|
SystemTime::now()
|
||||||
@ -121,7 +129,7 @@ pub fn gen_sk(wait: u64) -> (String, Option<sign::SecretKey>) {
|
|||||||
};
|
};
|
||||||
let (mut pk, mut sk) = gen_func();
|
let (mut pk, mut sk) = gen_func();
|
||||||
for _ in 0..300 {
|
for _ in 0..300 {
|
||||||
if !pk.contains("/") && !pk.contains(":") {
|
if !pk.contains('/') && !pk.contains(':') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
(pk, sk) = gen_func();
|
(pk, sk) = gen_func();
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use hbb_common::{log, ResultType};
|
use hbb_common::{log, ResultType};
|
||||||
use serde_json::value::Value;
|
|
||||||
use sqlx::{
|
use sqlx::{
|
||||||
sqlite::SqliteConnectOptions, ConnectOptions, Connection, Error as SqlxError, SqliteConnection,
|
sqlite::SqliteConnectOptions, ConnectOptions, Connection, Error as SqlxError, SqliteConnection,
|
||||||
};
|
};
|
||||||
@ -8,7 +7,6 @@ use std::{ops::DerefMut, str::FromStr};
|
|||||||
//use sqlx::postgres::PgPoolOptions;
|
//use sqlx::postgres::PgPoolOptions;
|
||||||
//use sqlx::mysql::MySqlPoolOptions;
|
//use sqlx::mysql::MySqlPoolOptions;
|
||||||
|
|
||||||
pub(crate) type MapValue = serde_json::map::Map<String, Value>;
|
|
||||||
type Pool = deadpool::managed::Pool<DbPool>;
|
type Pool = deadpool::managed::Pool<DbPool>;
|
||||||
|
|
||||||
pub struct DbPool {
|
pub struct DbPool {
|
||||||
@ -54,7 +52,7 @@ impl Database {
|
|||||||
std::fs::File::create(url).ok();
|
std::fs::File::create(url).ok();
|
||||||
}
|
}
|
||||||
let n: usize = std::env::var("MAX_DATABASE_CONNECTIONS")
|
let n: usize = std::env::var("MAX_DATABASE_CONNECTIONS")
|
||||||
.unwrap_or("1".to_owned())
|
.unwrap_or_else(|_| "1".to_owned())
|
||||||
.parse()
|
.parse()
|
||||||
.unwrap_or(1);
|
.unwrap_or(1);
|
||||||
log::debug!("MAX_DATABASE_CONNECTIONS={}", n);
|
log::debug!("MAX_DATABASE_CONNECTIONS={}", n);
|
||||||
@ -105,24 +103,6 @@ impl Database {
|
|||||||
.await?)
|
.await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub async fn get_conn(&self) -> ResultType<deadpool::managed::Object<DbPool>> {
|
|
||||||
Ok(self.pool.get().await?)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn update_peer(&self, payload: MapValue, guid: &[u8]) -> ResultType<()> {
|
|
||||||
let mut conn = self.get_conn().await?;
|
|
||||||
let mut tx = conn.begin().await?;
|
|
||||||
if let Some(v) = payload.get("note") {
|
|
||||||
let v = get_str(v);
|
|
||||||
sqlx::query!("update peer set note = ? where guid = ?", v, guid)
|
|
||||||
.execute(&mut tx)
|
|
||||||
.await?;
|
|
||||||
}
|
|
||||||
tx.commit().await?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn insert_peer(
|
pub async fn insert_peer(
|
||||||
&self,
|
&self,
|
||||||
id: &str,
|
id: &str,
|
||||||
@ -199,17 +179,3 @@ mod tests {
|
|||||||
hbb_common::futures::future::join_all(jobs).await;
|
hbb_common::futures::future::join_all(jobs).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_str(v: &Value) -> Option<&str> {
|
|
||||||
match v {
|
|
||||||
Value::String(v) => {
|
|
||||||
let v = v.trim();
|
|
||||||
if v.is_empty() {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
30
src/peer.rs
30
src/peer.rs
@ -10,10 +10,13 @@ use hbb_common::{
|
|||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use std::{collections::HashMap, collections::HashSet, net::SocketAddr, sync::Arc, time::Instant};
|
use std::{collections::HashMap, collections::HashSet, net::SocketAddr, sync::Arc, time::Instant};
|
||||||
|
|
||||||
|
type IpBlockMap = HashMap<String, ((u32, Instant), (HashSet<String>, Instant))>;
|
||||||
|
type UserStatusMap = HashMap<Vec<u8>, Arc<(Option<Vec<u8>>, bool)>>;
|
||||||
|
type IpChangesMap = HashMap<String, (Instant, HashMap<String, i32>)>;
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
pub(crate) static ref IP_BLOCKER: Mutex<HashMap<String, ((u32, Instant), (HashSet<String>, Instant))>> = Default::default();
|
pub(crate) static ref IP_BLOCKER: Mutex<IpBlockMap> = Default::default();
|
||||||
pub(crate) static ref USER_STATUS: RwLock<HashMap<Vec<u8>, Arc<(Option<Vec<u8>>, bool)>>> = Default::default();
|
pub(crate) static ref USER_STATUS: RwLock<UserStatusMap> = Default::default();
|
||||||
pub(crate) static ref IP_CHANGES: Mutex<HashMap<String, (Instant, HashMap<String, i32>)>> = Default::default();
|
pub(crate) static ref IP_CHANGES: Mutex<IpChangesMap> = Default::default();
|
||||||
}
|
}
|
||||||
pub static IP_CHANGE_DUR: u64 = 180;
|
pub static IP_CHANGE_DUR: u64 = 180;
|
||||||
pub static IP_CHANGE_DUR_X2: u64 = IP_CHANGE_DUR * 2;
|
pub static IP_CHANGE_DUR_X2: u64 = IP_CHANGE_DUR * 2;
|
||||||
@ -32,9 +35,9 @@ pub(crate) struct Peer {
|
|||||||
pub(crate) guid: Vec<u8>,
|
pub(crate) guid: Vec<u8>,
|
||||||
pub(crate) uuid: Bytes,
|
pub(crate) uuid: Bytes,
|
||||||
pub(crate) pk: Bytes,
|
pub(crate) pk: Bytes,
|
||||||
pub(crate) user: Option<Vec<u8>>,
|
// pub(crate) user: Option<Vec<u8>>,
|
||||||
pub(crate) info: PeerInfo,
|
pub(crate) info: PeerInfo,
|
||||||
pub(crate) disabled: bool,
|
// pub(crate) disabled: bool,
|
||||||
pub(crate) reg_pk: (u32, Instant), // how often register_pk
|
pub(crate) reg_pk: (u32, Instant), // how often register_pk
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -47,8 +50,8 @@ impl Default for Peer {
|
|||||||
uuid: Bytes::new(),
|
uuid: Bytes::new(),
|
||||||
pk: Bytes::new(),
|
pk: Bytes::new(),
|
||||||
info: Default::default(),
|
info: Default::default(),
|
||||||
user: None,
|
// user: None,
|
||||||
disabled: false,
|
// disabled: false,
|
||||||
reg_pk: (0, get_expired_time()),
|
reg_pk: (0, get_expired_time()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,7 +68,6 @@ pub(crate) struct PeerMap {
|
|||||||
impl PeerMap {
|
impl PeerMap {
|
||||||
pub(crate) async fn new() -> ResultType<Self> {
|
pub(crate) async fn new() -> ResultType<Self> {
|
||||||
let db = std::env::var("DB_URL").unwrap_or({
|
let db = std::env::var("DB_URL").unwrap_or({
|
||||||
#[allow(unused_mut)]
|
|
||||||
let mut db = "db_v2.sqlite3".to_owned();
|
let mut db = "db_v2.sqlite3".to_owned();
|
||||||
#[cfg(all(windows, not(debug_assertions)))]
|
#[cfg(all(windows, not(debug_assertions)))]
|
||||||
{
|
{
|
||||||
@ -132,25 +134,23 @@ impl PeerMap {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) async fn get(&self, id: &str) -> Option<LockPeer> {
|
pub(crate) async fn get(&self, id: &str) -> Option<LockPeer> {
|
||||||
let p = self.map.read().await.get(id).map(|x| x.clone());
|
let p = self.map.read().await.get(id).cloned();
|
||||||
if p.is_some() {
|
if p.is_some() {
|
||||||
return p;
|
return p;
|
||||||
} else {
|
} else if let Ok(Some(v)) = self.db.get_peer(id).await {
|
||||||
if let Ok(Some(v)) = self.db.get_peer(id).await {
|
|
||||||
let peer = Peer {
|
let peer = Peer {
|
||||||
guid: v.guid,
|
guid: v.guid,
|
||||||
uuid: v.uuid.into(),
|
uuid: v.uuid.into(),
|
||||||
pk: v.pk.into(),
|
pk: v.pk.into(),
|
||||||
user: v.user,
|
// user: v.user,
|
||||||
info: serde_json::from_str::<PeerInfo>(&v.info).unwrap_or_default(),
|
info: serde_json::from_str::<PeerInfo>(&v.info).unwrap_or_default(),
|
||||||
disabled: v.status == Some(0),
|
// disabled: v.status == Some(0),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
let peer = Arc::new(RwLock::new(peer));
|
let peer = Arc::new(RwLock::new(peer));
|
||||||
self.map.write().await.insert(id.to_owned(), peer.clone());
|
self.map.write().await.insert(id.to_owned(), peer.clone());
|
||||||
return Some(peer);
|
return Some(peer);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +170,7 @@ impl PeerMap {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub(crate) async fn get_in_memory(&self, id: &str) -> Option<LockPeer> {
|
pub(crate) async fn get_in_memory(&self, id: &str) -> Option<LockPeer> {
|
||||||
self.map.read().await.get(id).map(|x| x.clone())
|
self.map.read().await.get(id).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
@ -37,12 +37,12 @@ lazy_static::lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static mut DOWNGRADE_THRESHOLD: f64 = 0.66;
|
static mut DOWNGRADE_THRESHOLD: f64 = 0.66;
|
||||||
static mut DOWNGRADE_START_CHECK: usize = 1800_000; // in ms
|
static mut DOWNGRADE_START_CHECK: usize = 1_800_000; // in ms
|
||||||
static mut LIMIT_SPEED: usize = 4 * 1024 * 1024; // in bit/s
|
static mut LIMIT_SPEED: usize = 4 * 1024 * 1024; // in bit/s
|
||||||
static mut TOTAL_BANDWIDTH: usize = 1024 * 1024 * 1024; // in bit/s
|
static mut TOTAL_BANDWIDTH: usize = 1024 * 1024 * 1024; // in bit/s
|
||||||
static mut SINGLE_BANDWIDTH: usize = 16 * 1024 * 1024; // in bit/s
|
static mut SINGLE_BANDWIDTH: usize = 16 * 1024 * 1024; // in bit/s
|
||||||
const BLACKLIST_FILE: &'static str = "blacklist.txt";
|
const BLACKLIST_FILE: &str = "blacklist.txt";
|
||||||
const BLOCKLIST_FILE: &'static str = "blocklist.txt";
|
const BLOCKLIST_FILE: &str = "blocklist.txt";
|
||||||
|
|
||||||
#[tokio::main(flavor = "multi_thread")]
|
#[tokio::main(flavor = "multi_thread")]
|
||||||
pub async fn start(port: &str, key: &str) -> ResultType<()> {
|
pub async fn start(port: &str, key: &str) -> ResultType<()> {
|
||||||
@ -50,8 +50,8 @@ pub async fn start(port: &str, key: &str) -> ResultType<()> {
|
|||||||
if let Ok(mut file) = std::fs::File::open(BLACKLIST_FILE) {
|
if let Ok(mut file) = std::fs::File::open(BLACKLIST_FILE) {
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
if file.read_to_string(&mut contents).is_ok() {
|
if file.read_to_string(&mut contents).is_ok() {
|
||||||
for x in contents.split("\n") {
|
for x in contents.split('\n') {
|
||||||
if let Some(ip) = x.trim().split(' ').nth(0) {
|
if let Some(ip) = x.trim().split(' ').next() {
|
||||||
BLACKLIST.write().await.insert(ip.to_owned());
|
BLACKLIST.write().await.insert(ip.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -65,8 +65,8 @@ pub async fn start(port: &str, key: &str) -> ResultType<()> {
|
|||||||
if let Ok(mut file) = std::fs::File::open(BLOCKLIST_FILE) {
|
if let Ok(mut file) = std::fs::File::open(BLOCKLIST_FILE) {
|
||||||
let mut contents = String::new();
|
let mut contents = String::new();
|
||||||
if file.read_to_string(&mut contents).is_ok() {
|
if file.read_to_string(&mut contents).is_ok() {
|
||||||
for x in contents.split("\n") {
|
for x in contents.split('\n') {
|
||||||
if let Some(ip) = x.trim().split(' ').nth(0) {
|
if let Some(ip) = x.trim().split(' ').next() {
|
||||||
BLOCKLIST.write().await.insert(ip.to_owned());
|
BLOCKLIST.write().await.insert(ip.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -158,8 +158,10 @@ fn check_params() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn check_cmd(cmd: &str, limiter: Limiter) -> String {
|
async fn check_cmd(cmd: &str, limiter: Limiter) -> String {
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
let mut res = "".to_owned();
|
let mut res = "".to_owned();
|
||||||
let mut fds = cmd.trim().split(" ");
|
let mut fds = cmd.trim().split(' ');
|
||||||
match fds.next() {
|
match fds.next() {
|
||||||
Some("h") => {
|
Some("h") => {
|
||||||
res = format!(
|
res = format!(
|
||||||
@ -180,7 +182,7 @@ async fn check_cmd(cmd: &str, limiter: Limiter) -> String {
|
|||||||
}
|
}
|
||||||
Some("blacklist-add" | "ba") => {
|
Some("blacklist-add" | "ba") => {
|
||||||
if let Some(ip) = fds.next() {
|
if let Some(ip) = fds.next() {
|
||||||
for ip in ip.split("|") {
|
for ip in ip.split('|') {
|
||||||
BLACKLIST.write().await.insert(ip.to_owned());
|
BLACKLIST.write().await.insert(ip.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -190,7 +192,7 @@ async fn check_cmd(cmd: &str, limiter: Limiter) -> String {
|
|||||||
if ip == "all" {
|
if ip == "all" {
|
||||||
BLACKLIST.write().await.clear();
|
BLACKLIST.write().await.clear();
|
||||||
} else {
|
} else {
|
||||||
for ip in ip.split("|") {
|
for ip in ip.split('|') {
|
||||||
BLACKLIST.write().await.remove(ip);
|
BLACKLIST.write().await.remove(ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,13 +203,13 @@ async fn check_cmd(cmd: &str, limiter: Limiter) -> String {
|
|||||||
res = format!("{}\n", BLACKLIST.read().await.get(ip).is_some());
|
res = format!("{}\n", BLACKLIST.read().await.get(ip).is_some());
|
||||||
} else {
|
} else {
|
||||||
for ip in BLACKLIST.read().await.clone().into_iter() {
|
for ip in BLACKLIST.read().await.clone().into_iter() {
|
||||||
res += &format!("{}\n", ip);
|
let _ = writeln!(res, "{ip}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some("blocklist-add" | "Ba") => {
|
Some("blocklist-add" | "Ba") => {
|
||||||
if let Some(ip) = fds.next() {
|
if let Some(ip) = fds.next() {
|
||||||
for ip in ip.split("|") {
|
for ip in ip.split('|') {
|
||||||
BLOCKLIST.write().await.insert(ip.to_owned());
|
BLOCKLIST.write().await.insert(ip.to_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -217,7 +219,7 @@ async fn check_cmd(cmd: &str, limiter: Limiter) -> String {
|
|||||||
if ip == "all" {
|
if ip == "all" {
|
||||||
BLOCKLIST.write().await.clear();
|
BLOCKLIST.write().await.clear();
|
||||||
} else {
|
} else {
|
||||||
for ip in ip.split("|") {
|
for ip in ip.split('|') {
|
||||||
BLOCKLIST.write().await.remove(ip);
|
BLOCKLIST.write().await.remove(ip);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -228,7 +230,7 @@ async fn check_cmd(cmd: &str, limiter: Limiter) -> String {
|
|||||||
res = format!("{}\n", BLOCKLIST.read().await.get(ip).is_some());
|
res = format!("{}\n", BLOCKLIST.read().await.get(ip).is_some());
|
||||||
} else {
|
} else {
|
||||||
for ip in BLOCKLIST.read().await.clone().into_iter() {
|
for ip in BLOCKLIST.read().await.clone().into_iter() {
|
||||||
res += &format!("{}\n", ip);
|
let _ = writeln!(res, "{ip}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -313,15 +315,16 @@ async fn check_cmd(cmd: &str, limiter: Limiter) -> String {
|
|||||||
.read()
|
.read()
|
||||||
.await
|
.await
|
||||||
.iter()
|
.iter()
|
||||||
.map(|x| (x.0.clone(), x.1.clone()))
|
.map(|x| (x.0.clone(), *x.1))
|
||||||
.collect();
|
.collect();
|
||||||
tmp.sort_by(|a, b| ((b.1).1).partial_cmp(&(a.1).1).unwrap());
|
tmp.sort_by(|a, b| ((b.1).1).partial_cmp(&(a.1).1).unwrap());
|
||||||
for (ip, (elapsed, total, highest, speed)) in tmp {
|
for (ip, (elapsed, total, highest, speed)) in tmp {
|
||||||
if elapsed <= 0 {
|
if elapsed == 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
res += &format!(
|
let _ = writeln!(
|
||||||
"{}: {}s {:.2}MB {}kb/s {}kb/s {}kb/s\n",
|
res,
|
||||||
|
"{}: {}s {:.2}MB {}kb/s {}kb/s {}kb/s",
|
||||||
ip,
|
ip,
|
||||||
elapsed / 1000,
|
elapsed / 1000,
|
||||||
total as f64 / 1024. / 1024. / 8.,
|
total as f64 / 1024. / 1024. / 8.,
|
||||||
@ -496,7 +499,7 @@ async fn relay(
|
|||||||
total_limiter.consume(nb).await;
|
total_limiter.consume(nb).await;
|
||||||
total += nb;
|
total += nb;
|
||||||
total_s += nb;
|
total_s += nb;
|
||||||
if bytes.len() > 0 {
|
if !bytes.is_empty() {
|
||||||
stream.send_raw(bytes.into()).await?;
|
stream.send_raw(bytes.into()).await?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -515,7 +518,7 @@ async fn relay(
|
|||||||
total_limiter.consume(nb).await;
|
total_limiter.consume(nb).await;
|
||||||
total += nb;
|
total += nb;
|
||||||
total_s += nb;
|
total_s += nb;
|
||||||
if bytes.len() > 0 {
|
if !bytes.is_empty() {
|
||||||
peer.send_raw(bytes.into()).await?;
|
peer.send_raw(bytes.into()).await?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -537,7 +540,7 @@ async fn relay(
|
|||||||
}
|
}
|
||||||
blacked = BLACKLIST.read().await.get(&ip).is_some();
|
blacked = BLACKLIST.read().await.get(&ip).is_some();
|
||||||
tm = std::time::Instant::now();
|
tm = std::time::Instant::now();
|
||||||
let speed = total_s / (n as usize);
|
let speed = total_s / n;
|
||||||
if speed > highest_s {
|
if speed > highest_s {
|
||||||
highest_s = speed;
|
highest_s = speed;
|
||||||
}
|
}
|
||||||
@ -547,8 +550,10 @@ async fn relay(
|
|||||||
(elapsed as _, total as _, highest_s as _, speed as _),
|
(elapsed as _, total as _, highest_s as _, speed as _),
|
||||||
);
|
);
|
||||||
total_s = 0;
|
total_s = 0;
|
||||||
if elapsed > unsafe { DOWNGRADE_START_CHECK } && !downgrade {
|
if elapsed > unsafe { DOWNGRADE_START_CHECK }
|
||||||
if total > elapsed * downgrade_threshold {
|
&& !downgrade
|
||||||
|
&& total > elapsed * downgrade_threshold
|
||||||
|
{
|
||||||
downgrade = true;
|
downgrade = true;
|
||||||
log::info!(
|
log::info!(
|
||||||
"Downgrade {}, exceed downgrade threshold {}bit/ms in {}ms",
|
"Downgrade {}, exceed downgrade threshold {}bit/ms in {}ms",
|
||||||
@ -559,7 +564,6 @@ async fn relay(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ const ADDR_127: IpAddr = IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1));
|
|||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum Data {
|
enum Data {
|
||||||
Msg(RendezvousMessage, SocketAddr),
|
Msg(Box<RendezvousMessage>, SocketAddr),
|
||||||
RelayServers0(String),
|
RelayServers0(String),
|
||||||
RelayServers(RelayServers),
|
RelayServers(RelayServers),
|
||||||
}
|
}
|
||||||
@ -233,7 +233,7 @@ impl RendezvousServer {
|
|||||||
}
|
}
|
||||||
Some(data) = rx.recv() => {
|
Some(data) = rx.recv() => {
|
||||||
match data {
|
match data {
|
||||||
Data::Msg(msg, addr) => { allow_err!(socket.send(&msg, addr).await); }
|
Data::Msg(msg, addr) => { allow_err!(socket.send(msg.as_ref(), addr).await); }
|
||||||
Data::RelayServers0(rs) => { self.parse_relay_servers(&rs); }
|
Data::RelayServers0(rs) => { self.parse_relay_servers(&rs); }
|
||||||
Data::RelayServers(rs) => { self.relay_servers = Arc::new(rs); }
|
Data::RelayServers(rs) => { self.relay_servers = Arc::new(rs); }
|
||||||
}
|
}
|
||||||
@ -303,11 +303,11 @@ impl RendezvousServer {
|
|||||||
socket: &mut FramedSocket,
|
socket: &mut FramedSocket,
|
||||||
key: &str,
|
key: &str,
|
||||||
) -> ResultType<()> {
|
) -> ResultType<()> {
|
||||||
if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) {
|
if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(bytes) {
|
||||||
match msg_in.union {
|
match msg_in.union {
|
||||||
Some(rendezvous_message::Union::RegisterPeer(rp)) => {
|
Some(rendezvous_message::Union::RegisterPeer(rp)) => {
|
||||||
// B registered
|
// B registered
|
||||||
if rp.id.len() > 0 {
|
if !rp.id.is_empty() {
|
||||||
log::trace!("New peer registered: {:?} {:?}", &rp.id, &addr);
|
log::trace!("New peer registered: {:?} {:?}", &rp.id, &addr);
|
||||||
self.update_addr(rp.id, addr, socket).await?;
|
self.update_addr(rp.id, addr, socket).await?;
|
||||||
if self.inner.serial > rp.serial {
|
if self.inner.serial > rp.serial {
|
||||||
@ -384,13 +384,11 @@ impl RendezvousServer {
|
|||||||
*tm = Instant::now();
|
*tm = Instant::now();
|
||||||
ips.clear();
|
ips.clear();
|
||||||
ips.insert(ip.clone(), 1);
|
ips.insert(ip.clone(), 1);
|
||||||
} else {
|
} else if let Some(v) = ips.get_mut(&ip) {
|
||||||
if let Some(v) = ips.get_mut(&ip) {
|
|
||||||
*v += 1;
|
*v += 1;
|
||||||
} else {
|
} else {
|
||||||
ips.insert(ip.clone(), 1);
|
ips.insert(ip.clone(), 1);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
lock.insert(
|
lock.insert(
|
||||||
id.clone(),
|
id.clone(),
|
||||||
@ -472,14 +470,14 @@ impl RendezvousServer {
|
|||||||
key: &str,
|
key: &str,
|
||||||
ws: bool,
|
ws: bool,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(&bytes) {
|
if let Ok(msg_in) = RendezvousMessage::parse_from_bytes(bytes) {
|
||||||
match msg_in.union {
|
match msg_in.union {
|
||||||
Some(rendezvous_message::Union::PunchHoleRequest(ph)) => {
|
Some(rendezvous_message::Union::PunchHoleRequest(ph)) => {
|
||||||
// there maybe several attempt, so sink can be none
|
// there maybe several attempt, so sink can be none
|
||||||
if let Some(sink) = sink.take() {
|
if let Some(sink) = sink.take() {
|
||||||
self.tcp_punch.lock().await.insert(addr, sink);
|
self.tcp_punch.lock().await.insert(addr, sink);
|
||||||
}
|
}
|
||||||
allow_err!(self.handle_tcp_punch_hole_request(addr, ph, &key, ws).await);
|
allow_err!(self.handle_tcp_punch_hole_request(addr, ph, key, ws).await);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
Some(rendezvous_message::Union::RequestRelay(mut rf)) => {
|
Some(rendezvous_message::Union::RequestRelay(mut rf)) => {
|
||||||
@ -492,7 +490,7 @@ impl RendezvousServer {
|
|||||||
rf.socket_addr = AddrMangle::encode(addr).into();
|
rf.socket_addr = AddrMangle::encode(addr).into();
|
||||||
msg_out.set_request_relay(rf);
|
msg_out.set_request_relay(rf);
|
||||||
let peer_addr = peer.read().await.socket_addr;
|
let peer_addr = peer.read().await.socket_addr;
|
||||||
self.tx.send(Data::Msg(msg_out, peer_addr)).ok();
|
self.tx.send(Data::Msg(msg_out.into(), peer_addr)).ok();
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -747,14 +745,14 @@ impl RendezvousServer {
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
return Ok((msg_out, Some(peer_addr)));
|
Ok((msg_out, Some(peer_addr)))
|
||||||
} else {
|
} else {
|
||||||
let mut msg_out = RendezvousMessage::new();
|
let mut msg_out = RendezvousMessage::new();
|
||||||
msg_out.set_punch_hole_response(PunchHoleResponse {
|
msg_out.set_punch_hole_response(PunchHoleResponse {
|
||||||
failure: punch_hole_response::Failure::ID_NOT_EXIST.into(),
|
failure: punch_hole_response::Failure::ID_NOT_EXIST.into(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
return Ok((msg_out, None));
|
Ok((msg_out, None))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -765,8 +763,8 @@ impl RendezvousServer {
|
|||||||
peers: Vec<String>,
|
peers: Vec<String>,
|
||||||
) -> ResultType<()> {
|
) -> ResultType<()> {
|
||||||
let mut states = BytesMut::zeroed((peers.len() + 7) / 8);
|
let mut states = BytesMut::zeroed((peers.len() + 7) / 8);
|
||||||
for i in 0..peers.len() {
|
for (i, peer_id) in peers.iter().enumerate() {
|
||||||
if let Some(peer) = self.pm.get_in_memory(&peers[i]).await {
|
if let Some(peer) = self.pm.get_in_memory(peer_id).await {
|
||||||
let elapsed = peer.read().await.last_reg_time.elapsed().as_millis() as i32;
|
let elapsed = peer.read().await.last_reg_time.elapsed().as_millis() as i32;
|
||||||
// bytes index from left to right
|
// bytes index from left to right
|
||||||
let states_idx = i / 8;
|
let states_idx = i / 8;
|
||||||
@ -832,7 +830,7 @@ impl RendezvousServer {
|
|||||||
) -> ResultType<()> {
|
) -> ResultType<()> {
|
||||||
let (msg, to_addr) = self.handle_punch_hole_request(addr, ph, key, ws).await?;
|
let (msg, to_addr) = self.handle_punch_hole_request(addr, ph, key, ws).await?;
|
||||||
if let Some(addr) = to_addr {
|
if let Some(addr) = to_addr {
|
||||||
self.tx.send(Data::Msg(msg, addr))?;
|
self.tx.send(Data::Msg(msg.into(), addr))?;
|
||||||
} else {
|
} else {
|
||||||
self.send_to_tcp_sync(msg, addr).await?;
|
self.send_to_tcp_sync(msg, addr).await?;
|
||||||
}
|
}
|
||||||
@ -848,7 +846,7 @@ impl RendezvousServer {
|
|||||||
) -> ResultType<()> {
|
) -> ResultType<()> {
|
||||||
let (msg, to_addr) = self.handle_punch_hole_request(addr, ph, key, false).await?;
|
let (msg, to_addr) = self.handle_punch_hole_request(addr, ph, key, false).await?;
|
||||||
self.tx.send(Data::Msg(
|
self.tx.send(Data::Msg(
|
||||||
msg,
|
msg.into(),
|
||||||
match to_addr {
|
match to_addr {
|
||||||
Some(addr) => addr,
|
Some(addr) => addr,
|
||||||
None => addr,
|
None => addr,
|
||||||
@ -907,8 +905,10 @@ impl RendezvousServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async fn check_cmd(&self, cmd: &str) -> String {
|
async fn check_cmd(&self, cmd: &str) -> String {
|
||||||
|
use std::fmt::Write as _;
|
||||||
|
|
||||||
let mut res = "".to_owned();
|
let mut res = "".to_owned();
|
||||||
let mut fds = cmd.trim().split(" ");
|
let mut fds = cmd.trim().split(' ');
|
||||||
match fds.next() {
|
match fds.next() {
|
||||||
Some("h") => {
|
Some("h") => {
|
||||||
res = format!(
|
res = format!(
|
||||||
@ -926,7 +926,7 @@ impl RendezvousServer {
|
|||||||
self.tx.send(Data::RelayServers0(rs.to_owned())).ok();
|
self.tx.send(Data::RelayServers0(rs.to_owned())).ok();
|
||||||
} else {
|
} else {
|
||||||
for ip in self.relay_servers.iter() {
|
for ip in self.relay_servers.iter() {
|
||||||
res += &format!("{}\n", ip);
|
let _ = writeln!(res, "{ip}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -942,8 +942,9 @@ impl RendezvousServer {
|
|||||||
if start < 0 {
|
if start < 0 {
|
||||||
if let Some(ip) = ip {
|
if let Some(ip) = ip {
|
||||||
if let Some((a, b)) = lock.get(ip) {
|
if let Some((a, b)) = lock.get(ip) {
|
||||||
res += &format!(
|
let _ = writeln!(
|
||||||
"{}/{}s {}/{}s\n",
|
res,
|
||||||
|
"{}/{}s {}/{}s",
|
||||||
a.0,
|
a.0,
|
||||||
a.1.elapsed().as_secs(),
|
a.1.elapsed().as_secs(),
|
||||||
b.0.len(),
|
b.0.len(),
|
||||||
@ -968,8 +969,9 @@ impl RendezvousServer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some((ip, (a, b))) = x {
|
if let Some((ip, (a, b))) = x {
|
||||||
res += &format!(
|
let _ = writeln!(
|
||||||
"{}: {}/{}s {}/{}s\n",
|
res,
|
||||||
|
"{}: {}/{}s {}/{}s",
|
||||||
ip,
|
ip,
|
||||||
a.0,
|
a.0,
|
||||||
a.1.elapsed().as_secs(),
|
a.1.elapsed().as_secs(),
|
||||||
@ -986,10 +988,10 @@ impl RendezvousServer {
|
|||||||
res = format!("{}\n", lock.len());
|
res = format!("{}\n", lock.len());
|
||||||
let id = fds.next();
|
let id = fds.next();
|
||||||
let mut start = id.map(|x| x.parse::<i32>().unwrap_or(-1)).unwrap_or(-1);
|
let mut start = id.map(|x| x.parse::<i32>().unwrap_or(-1)).unwrap_or(-1);
|
||||||
if start < 0 || start > 10_000_000 {
|
if !(0..=10_000_000).contains(&start) {
|
||||||
if let Some(id) = id {
|
if let Some(id) = id {
|
||||||
if let Some((tm, ips)) = lock.get(id) {
|
if let Some((tm, ips)) = lock.get(id) {
|
||||||
res += &format!("{}s {:?}\n", tm.elapsed().as_secs(), ips);
|
let _ = writeln!(res, "{}s {:?}", tm.elapsed().as_secs(), ips);
|
||||||
}
|
}
|
||||||
if fds.next() == Some("-") {
|
if fds.next() == Some("-") {
|
||||||
lock.remove(id);
|
lock.remove(id);
|
||||||
@ -1009,7 +1011,7 @@ impl RendezvousServer {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some((id, (tm, ips))) = x {
|
if let Some((id, (tm, ips))) = x {
|
||||||
res += &format!("{}: {}s {:?}\n", id, tm.elapsed().as_secs(), ips,);
|
let _ = writeln!(res, "{}: {}s {:?}", id, tm.elapsed().as_secs(), ips,);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1023,7 +1025,7 @@ impl RendezvousServer {
|
|||||||
}
|
}
|
||||||
self.tx.send(Data::RelayServers0(rs.to_owned())).ok();
|
self.tx.send(Data::RelayServers0(rs.to_owned())).ok();
|
||||||
} else {
|
} else {
|
||||||
res += &format!("ALWAYS_USE_RELAY: {:?}\n", unsafe { ALWAYS_USE_RELAY });
|
let _ = writeln!(res, "ALWAYS_USE_RELAY: {:?}", unsafe { ALWAYS_USE_RELAY });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some("test-geo" | "tg") => {
|
Some("test-geo" | "tg") => {
|
||||||
@ -1106,14 +1108,11 @@ impl RendezvousServer {
|
|||||||
let (a, mut b) = ws_stream.split();
|
let (a, mut b) = ws_stream.split();
|
||||||
sink = Some(Sink::Ws(a));
|
sink = Some(Sink::Ws(a));
|
||||||
while let Ok(Some(Ok(msg))) = timeout(30_000, b.next()).await {
|
while let Ok(Some(Ok(msg))) = timeout(30_000, b.next()).await {
|
||||||
match msg {
|
if let tungstenite::Message::Binary(bytes) = msg {
|
||||||
tungstenite::Message::Binary(bytes) => {
|
|
||||||
if !self.handle_tcp(&bytes, &mut sink, addr, key, ws).await {
|
if !self.handle_tcp(&bytes, &mut sink, addr, key, ws).await {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let (a, mut b) = Framed::new(stream, BytesCodec::new()).split();
|
let (a, mut b) = Framed::new(stream, BytesCodec::new()).split();
|
||||||
@ -1138,7 +1137,7 @@ impl RendezvousServer {
|
|||||||
} else {
|
} else {
|
||||||
match self.pm.get(&id).await {
|
match self.pm.get(&id).await {
|
||||||
Some(peer) => {
|
Some(peer) => {
|
||||||
let pk = peer.read().await.pk.clone().into();
|
let pk = peer.read().await.pk.clone();
|
||||||
sign::sign(
|
sign::sign(
|
||||||
&hbb_common::message_proto::IdPk {
|
&hbb_common::message_proto::IdPk {
|
||||||
id,
|
id,
|
||||||
@ -1147,7 +1146,7 @@ impl RendezvousServer {
|
|||||||
}
|
}
|
||||||
.write_to_bytes()
|
.write_to_bytes()
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
&self.inner.sk.as_ref().unwrap(),
|
self.inner.sk.as_ref().unwrap(),
|
||||||
)
|
)
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
@ -1203,7 +1202,7 @@ async fn check_relay_servers(rs0: Arc<RelayServers>, tx: Sender) {
|
|||||||
let rs = Arc::new(Mutex::new(Vec::new()));
|
let rs = Arc::new(Mutex::new(Vec::new()));
|
||||||
for x in rs0.iter() {
|
for x in rs0.iter() {
|
||||||
let mut host = x.to_owned();
|
let mut host = x.to_owned();
|
||||||
if !host.contains(":") {
|
if !host.contains(':') {
|
||||||
host = format!("{}:{}", host, hbb_common::config::RELAY_PORT);
|
host = format!("{}:{}", host, hbb_common::config::RELAY_PORT);
|
||||||
}
|
}
|
||||||
let rs = rs.clone();
|
let rs = rs.clone();
|
||||||
@ -1219,7 +1218,7 @@ async fn check_relay_servers(rs0: Arc<RelayServers>, tx: Sender) {
|
|||||||
}
|
}
|
||||||
join_all(futs).await;
|
join_all(futs).await;
|
||||||
log::debug!("check_relay_servers");
|
log::debug!("check_relay_servers");
|
||||||
let rs = std::mem::replace(&mut *rs.lock().await, Default::default());
|
let rs = std::mem::take(&mut *rs.lock().await);
|
||||||
if !rs.is_empty() {
|
if !rs.is_empty() {
|
||||||
tx.send(Data::RelayServers(rs)).ok();
|
tx.send(Data::RelayServers(rs)).ok();
|
||||||
}
|
}
|
||||||
|
26
src/utils.rs
26
src/utils.rs
@ -33,7 +33,7 @@ fn gen_keypair() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn validate_keypair(pk: &str, sk: &str) -> ResultType<()> {
|
fn validate_keypair(pk: &str, sk: &str) -> ResultType<()> {
|
||||||
let sk1 = base64::decode(&sk);
|
let sk1 = base64::decode(sk);
|
||||||
if sk1.is_err() {
|
if sk1.is_err() {
|
||||||
bail!("Invalid secret key");
|
bail!("Invalid secret key");
|
||||||
}
|
}
|
||||||
@ -45,7 +45,7 @@ fn validate_keypair(pk: &str, sk: &str) -> ResultType<()> {
|
|||||||
}
|
}
|
||||||
let secret_key = secret_key.unwrap();
|
let secret_key = secret_key.unwrap();
|
||||||
|
|
||||||
let pk1 = base64::decode(&pk);
|
let pk1 = base64::decode(pk);
|
||||||
if pk1.is_err() {
|
if pk1.is_err() {
|
||||||
bail!("Invalid public key");
|
bail!("Invalid public key");
|
||||||
}
|
}
|
||||||
@ -96,14 +96,13 @@ fn doctor_ip(server_ip_address: std::net::IpAddr, server_address: Option<&str>)
|
|||||||
// reverse dns lookup
|
// reverse dns lookup
|
||||||
// TODO: (check) doesn't seem to do reverse lookup on OSX...
|
// TODO: (check) doesn't seem to do reverse lookup on OSX...
|
||||||
let reverse = lookup_addr(&server_ip_address).unwrap();
|
let reverse = lookup_addr(&server_ip_address).unwrap();
|
||||||
if server_address.is_some() {
|
if let Some(server_address) = server_address {
|
||||||
if reverse == server_address.unwrap() {
|
if reverse == server_address {
|
||||||
println!("Reverse DNS lookup: '{}' MATCHES server address", reverse);
|
println!("Reverse DNS lookup: '{}' MATCHES server address", reverse);
|
||||||
} else {
|
} else {
|
||||||
println!(
|
println!(
|
||||||
"Reverse DNS lookup: '{}' DOESN'T MATCH server address '{}'",
|
"Reverse DNS lookup: '{}' DOESN'T MATCH server address '{}'",
|
||||||
reverse,
|
reverse, server_address
|
||||||
server_address.unwrap()
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -126,19 +125,18 @@ fn doctor(server_address_unclean: &str) {
|
|||||||
let server_address2 = server_address3.to_lowercase();
|
let server_address2 = server_address3.to_lowercase();
|
||||||
let server_address = server_address2.as_str();
|
let server_address = server_address2.as_str();
|
||||||
println!("Checking server: {}\n", server_address);
|
println!("Checking server: {}\n", server_address);
|
||||||
let server_ipaddr = server_address.parse::<IpAddr>();
|
if let Ok(server_ipaddr) = server_address.parse::<IpAddr>() {
|
||||||
if server_ipaddr.is_err() {
|
// user requested an ip address
|
||||||
|
doctor_ip(server_ipaddr, None);
|
||||||
|
} else {
|
||||||
// the passed string is not an ip address
|
// the passed string is not an ip address
|
||||||
let ips: Vec<std::net::IpAddr> = lookup_host(server_address).unwrap();
|
let ips: Vec<std::net::IpAddr> = lookup_host(server_address).unwrap();
|
||||||
println!("Found {} IP addresses: ", ips.iter().count());
|
println!("Found {} IP addresses: ", ips.len());
|
||||||
|
|
||||||
ips.iter().for_each(|ip| println!(" - {ip}"));
|
ips.iter().for_each(|ip| println!(" - {ip}"));
|
||||||
|
|
||||||
ips.iter().for_each(|ip| doctor_ip(*ip, Some(server_address)));
|
ips.iter()
|
||||||
|
.for_each(|ip| doctor_ip(*ip, Some(server_address)));
|
||||||
} else {
|
|
||||||
// user requested an ip address
|
|
||||||
doctor_ip(server_ipaddr.unwrap(), None);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,2 +1,3 @@
|
|||||||
pub const VERSION: &str = "1.1.6";
|
pub const VERSION: &str = "1.1.6";
|
||||||
pub const BUILD_DATE: &str = "2023-01-06 11:03";
|
#[allow(dead_code)]
|
||||||
|
pub const BUILD_DATE: &str = "2023-01-06 18:48";
|
Loading…
x
Reference in New Issue
Block a user