extern crate warp; use super::resolve; use crate::{ config::{Config, IVerge, DEFAULT_PAC}, logging_error, utils::logging::Type, }; use anyhow::{bail, Result}; use port_scanner::local_port_available; use std::convert::Infallible; use warp::Filter; #[derive(serde::Deserialize, Debug)] struct QueryParam { param: String, } /// check whether there is already exists pub async fn check_singleton() -> Result<()> { let port = IVerge::get_singleton_port(); if !local_port_available(port) { let argvs: Vec = std::env::args().collect(); if argvs.len() > 1 { #[cfg(not(target_os = "macos"))] { let param = argvs[1].as_str(); if param.starts_with("clash:") { let _ = reqwest::get(format!( "http://127.0.0.1:{port}/commands/scheme?param={param}" )) .await; } } } else { let _ = reqwest::get(format!("http://127.0.0.1:{port}/commands/visible")).await; } log::error!("failed to setup singleton listen server"); bail!("app exists"); } else { Ok(()) } } /// The embed server only be used to implement singleton process /// maybe it can be used as pac server later pub fn embed_server() { let port = IVerge::get_singleton_port(); tauri::async_runtime::spawn(async move { let visible = warp::path!("commands" / "visible").map(move || { resolve::create_window(false); "ok" }); let pac = warp::path!("commands" / "pac").map(move || { let content = Config::verge() .latest() .pac_file_content .clone() .unwrap_or(DEFAULT_PAC.to_string()); let port = Config::verge() .latest() .verge_mixed_port .unwrap_or(Config::clash().data().get_mixed_port()); let content = content.replace("%mixed-port%", &format!("{}", port)); warp::http::Response::builder() .header("Content-Type", "application/x-ns-proxy-autoconfig") .body(content) .unwrap_or_default() }); async fn scheme_handler(query: QueryParam) -> Result { logging_error!( Type::Setup, true, resolve::resolve_scheme(query.param).await ); Ok("ok") } let scheme = warp::path!("commands" / "scheme") .and(warp::query::()) .and_then(scheme_handler); let commands = visible.or(scheme).or(pac); warp::serve(commands).run(([127, 0, 0, 1], port)).await; }); }