| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- use clap::App;
- use hbb_common::{
- anyhow::{Context, Result},
- log, ResultType,
- };
- use ini::Ini;
- use sodiumoxide::crypto::sign;
- use std::{
- io::prelude::*,
- io::Read,
- net::SocketAddr,
- time::{Instant, SystemTime},
- };
- #[allow(dead_code)]
- pub(crate) fn get_expired_time() -> Instant {
- let now = Instant::now();
- now.checked_sub(std::time::Duration::from_secs(3600))
- .unwrap_or(now)
- }
- #[allow(dead_code)]
- pub(crate) fn test_if_valid_server(host: &str, name: &str) -> ResultType<SocketAddr> {
- use std::net::ToSocketAddrs;
- let res = if host.contains(':') {
- host.to_socket_addrs()?.next().context("")
- } else {
- format!("{}:{}", host, 0)
- .to_socket_addrs()?
- .next()
- .context("")
- };
- if res.is_err() {
- log::error!("Invalid {} {}: {:?}", name, host, res);
- }
- res
- }
- #[allow(dead_code)]
- pub(crate) fn get_servers(s: &str, tag: &str) -> Vec<String> {
- let servers: Vec<String> = s
- .split(',')
- .filter(|x| !x.is_empty() && test_if_valid_server(x, tag).is_ok())
- .map(|x| x.to_owned())
- .collect();
- log::info!("{}={:?}", tag, servers);
- servers
- }
- #[allow(dead_code)]
- #[inline]
- fn arg_name(name: &str) -> String {
- name.to_uppercase().replace('_', "-")
- }
- #[allow(dead_code)]
- pub fn init_args(args: &str, name: &str, about: &str) {
- let matches = App::new(name)
- .version(crate::version::VERSION)
- .author("Purslane Ltd. <info@rustdesk.com>")
- .about(about)
- .args_from_usage(args)
- .get_matches();
- if let Ok(v) = Ini::load_from_file(".env") {
- if let Some(section) = v.section(None::<String>) {
- section
- .iter()
- .for_each(|(k, v)| std::env::set_var(arg_name(k), v));
- }
- }
- if let Some(config) = matches.value_of("config") {
- if let Ok(v) = Ini::load_from_file(config) {
- if let Some(section) = v.section(None::<String>) {
- section
- .iter()
- .for_each(|(k, v)| std::env::set_var(arg_name(k), v));
- }
- }
- }
- for (k, v) in matches.args {
- if let Some(v) = v.vals.get(0) {
- std::env::set_var(arg_name(k), v.to_string_lossy().to_string());
- }
- }
- }
- #[allow(dead_code)]
- #[inline]
- pub fn get_arg(name: &str) -> String {
- get_arg_or(name, "".to_owned())
- }
- #[allow(dead_code)]
- #[inline]
- pub fn get_arg_or(name: &str, default: String) -> String {
- std::env::var(arg_name(name)).unwrap_or(default)
- }
- #[allow(dead_code)]
- #[inline]
- pub fn now() -> u64 {
- SystemTime::now()
- .duration_since(SystemTime::UNIX_EPOCH)
- .map(|x| x.as_secs())
- .unwrap_or_default()
- }
- pub fn gen_sk(wait: u64) -> (String, Option<sign::SecretKey>) {
- let sk_file = "id_ed25519";
- if wait > 0 && !std::path::Path::new(sk_file).exists() {
- std::thread::sleep(std::time::Duration::from_millis(wait));
- }
- if let Ok(mut file) = std::fs::File::open(sk_file) {
- let mut contents = String::new();
- if file.read_to_string(&mut contents).is_ok() {
- let sk = base64::decode(&contents).unwrap_or_default();
- if sk.len() == sign::SECRETKEYBYTES {
- let mut tmp = [0u8; sign::SECRETKEYBYTES];
- tmp[..].copy_from_slice(&sk);
- let pk = base64::encode(&tmp[sign::SECRETKEYBYTES / 2..]);
- log::info!("Private key comes from {}", sk_file);
- return (pk, Some(sign::SecretKey(tmp)));
- }
- }
- } else {
- let gen_func = || {
- let (tmp, sk) = sign::gen_keypair();
- (base64::encode(tmp), sk)
- };
- let (mut pk, mut sk) = gen_func();
- for _ in 0..300 {
- if !pk.contains('/') && !pk.contains(':') {
- break;
- }
- (pk, sk) = gen_func();
- }
- let pub_file = format!("{}.pub", sk_file);
- if let Ok(mut f) = std::fs::File::create(&pub_file) {
- f.write_all(pk.as_bytes()).ok();
- if let Ok(mut f) = std::fs::File::create(sk_file) {
- let s = base64::encode(&sk);
- if f.write_all(s.as_bytes()).is_ok() {
- log::info!("Private/public key written to {}/{}", sk_file, pub_file);
- log::debug!("Public key: {}", pk);
- return (pk, Some(sk));
- }
- }
- }
- }
- ("".to_owned(), None)
- }
- #[cfg(unix)]
- pub async fn listen_signal() -> Result<()> {
- use hbb_common::tokio;
- use hbb_common::tokio::signal::unix::{signal, SignalKind};
- tokio::spawn(async {
- let mut s = signal(SignalKind::hangup())?;
- let hangup = s.recv();
- let mut s = signal(SignalKind::terminate())?;
- let terminate = s.recv();
- let mut s = signal(SignalKind::interrupt())?;
- let interrupt = s.recv();
- let mut s = signal(SignalKind::quit())?;
- let quit = s.recv();
- tokio::select! {
- _ = hangup => {
- log::info!("signal hangup");
- }
- _ = terminate => {
- log::info!("signal terminate");
- }
- _ = interrupt => {
- log::info!("signal interrupt");
- }
- _ = quit => {
- log::info!("signal quit");
- }
- }
- Ok(())
- })
- .await?
- }
- #[cfg(not(unix))]
- pub async fn listen_signal() -> Result<()> {
- let () = std::future::pending().await;
- unreachable!();
- }
|