common.rs 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. use clap::App;
  2. use hbb_common::{anyhow::Context, log, ResultType};
  3. use ini::Ini;
  4. use sodiumoxide::crypto::sign;
  5. use std::{
  6. io::prelude::*,
  7. io::Read,
  8. net::SocketAddr,
  9. time::{Instant, SystemTime},
  10. };
  11. pub(crate) fn get_expired_time() -> Instant {
  12. let now = Instant::now();
  13. now.checked_sub(std::time::Duration::from_secs(3600))
  14. .unwrap_or(now)
  15. }
  16. pub(crate) fn test_if_valid_server(host: &str, name: &str) -> ResultType<SocketAddr> {
  17. use std::net::ToSocketAddrs;
  18. let res = if host.contains(":") {
  19. host.to_socket_addrs()?.next().context("")
  20. } else {
  21. format!("{}:{}", host, 0)
  22. .to_socket_addrs()?
  23. .next()
  24. .context("")
  25. };
  26. if res.is_err() {
  27. log::error!("Invalid {} {}: {:?}", name, host, res);
  28. }
  29. res
  30. }
  31. pub(crate) fn get_servers(s: &str, tag: &str) -> Vec<String> {
  32. let servers: Vec<String> = s
  33. .split(",")
  34. .filter(|x| !x.is_empty() && test_if_valid_server(x, tag).is_ok())
  35. .map(|x| x.to_owned())
  36. .collect();
  37. log::info!("{}={:?}", tag, servers);
  38. servers
  39. }
  40. #[inline]
  41. fn arg_name(name: &str) -> String {
  42. name.to_uppercase().replace("_", "-")
  43. }
  44. pub fn init_args(args: &str, name: &str, about: &str) {
  45. let matches = App::new(name)
  46. .version(crate::version::VERSION)
  47. .author("Purslane Ltd. <info@rustdesk.com>")
  48. .about(about)
  49. .args_from_usage(&args)
  50. .get_matches();
  51. if let Ok(v) = Ini::load_from_file(".env") {
  52. if let Some(section) = v.section(None::<String>) {
  53. section
  54. .iter()
  55. .for_each(|(k, v)| std::env::set_var(arg_name(k), v));
  56. }
  57. }
  58. if let Some(config) = matches.value_of("config") {
  59. if let Ok(v) = Ini::load_from_file(config) {
  60. if let Some(section) = v.section(None::<String>) {
  61. section
  62. .iter()
  63. .for_each(|(k, v)| std::env::set_var(arg_name(k), v));
  64. }
  65. }
  66. }
  67. for (k, v) in matches.args {
  68. if let Some(v) = v.vals.get(0) {
  69. std::env::set_var(arg_name(k), v.to_string_lossy().to_string());
  70. }
  71. }
  72. }
  73. #[inline]
  74. pub fn get_arg(name: &str) -> String {
  75. get_arg_or(name, "".to_owned())
  76. }
  77. #[inline]
  78. pub fn get_arg_or(name: &str, default: String) -> String {
  79. std::env::var(arg_name(name)).unwrap_or(default)
  80. }
  81. #[inline]
  82. pub fn now() -> u64 {
  83. SystemTime::now()
  84. .duration_since(SystemTime::UNIX_EPOCH)
  85. .map(|x| x.as_secs())
  86. .unwrap_or_default()
  87. }
  88. pub fn gen_sk(wait: u64) -> (String, Option<sign::SecretKey>) {
  89. let sk_file = "id_ed25519";
  90. if wait > 0 && !std::path::Path::new(sk_file).exists() {
  91. std::thread::sleep(std::time::Duration::from_millis(wait));
  92. }
  93. if let Ok(mut file) = std::fs::File::open(sk_file) {
  94. let mut contents = String::new();
  95. if file.read_to_string(&mut contents).is_ok() {
  96. let sk = base64::decode(&contents).unwrap_or_default();
  97. if sk.len() == sign::SECRETKEYBYTES {
  98. let mut tmp = [0u8; sign::SECRETKEYBYTES];
  99. tmp[..].copy_from_slice(&sk);
  100. let pk = base64::encode(&tmp[sign::SECRETKEYBYTES / 2..]);
  101. log::info!("Private key comes from {}", sk_file);
  102. return (pk, Some(sign::SecretKey(tmp)));
  103. }
  104. }
  105. } else {
  106. let gen_func = || {
  107. let (tmp, sk) = sign::gen_keypair();
  108. (base64::encode(tmp), sk)
  109. };
  110. let (mut pk, mut sk) = gen_func();
  111. for _ in 0..300 {
  112. if !pk.contains("/") && !pk.contains(":") {
  113. break;
  114. }
  115. (pk, sk) = gen_func();
  116. }
  117. let pub_file = format!("{}.pub", sk_file);
  118. if let Ok(mut f) = std::fs::File::create(&pub_file) {
  119. f.write_all(pk.as_bytes()).ok();
  120. if let Ok(mut f) = std::fs::File::create(sk_file) {
  121. let s = base64::encode(&sk);
  122. if f.write_all(s.as_bytes()).is_ok() {
  123. log::info!("Private/public key written to {}/{}", sk_file, pub_file);
  124. log::debug!("Public key: {}", pk);
  125. return (pk, Some(sk));
  126. }
  127. }
  128. }
  129. }
  130. ("".to_owned(), None)
  131. }