use std::fs; use std::io::Error; use std::net::IpAddr; use std::process::{Command, Output}; use serde::{Deserialize, Serialize}; use serde::de::DeserializeOwned; #[derive(Debug, Serialize, Deserialize)] pub struct IPAddressList { pub ip_address: Vec, } // Maps p2prc --ls output to the following // data structure #[derive(Debug, Serialize, Deserialize)] pub struct IPAddressEntry { pub Name: String, pub MachineUsername: String, pub IPV4: String, pub IPV6: String, pub Latency: u64, pub Download: u64, pub Upload: u64, pub ServerPort: String, pub BareMetalSSHPort: String, pub NAT: bool, pub EscapeImplementation: String, pub ProxyServer: bool, pub UnSafeMode: bool, pub PublicKey: String, pub CustomInformation: String, } #[derive(Serialize, Deserialize, Debug)] pub struct Config { #[serde(rename = "MachineName")] pub machine_name: String, #[serde(rename = "IPTable")] pub iptable: String, #[serde(rename = "DockerContainers")] pub docker_containers: String, #[serde(rename = "DefaultDockerFile")] pub default_docker_file: String, #[serde(rename = "DockerRunLogs")] pub docker_run_logs: String, #[serde(rename = "SpeedTestFile")] pub speed_test_file: String, #[serde(rename = "IPV6Address")] pub ipv6address: String, #[serde(rename = "PluginPath")] pub plugin_path: String, #[serde(rename = "TrackContainersPath")] pub track_containers_path: String, #[serde(rename = "ServerPort")] pub server_port: String, #[serde(rename = "ProxyPort")] pub proxy_port: String, #[serde(rename = "GroupTrackContainersPath")] pub group_track_containers_path: String, #[serde(rename = "FRPServerPort")] pub frpserver_port: bool, #[serde(rename = "BehindNAT")] pub behind_nat: bool, #[serde(rename = "IPTableKey")] pub iptable_key: String, #[serde(rename = "PublicKeyFile")] pub public_key_file: String, #[serde(rename = "PrivateKeyFile")] pub private_key_file: String, #[serde(rename = "PemFile")] pub pem_file: String, #[serde(rename = "KeyFile")] pub key_file: String, #[serde(rename = "BareMetal")] pub bare_metal: bool, #[serde(rename = "UnsafeMode")] pub unsafe_mode: bool, #[serde(rename = "Test")] pub test: bool, #[serde(rename = "ConfigPath")] pub config_path: String } #[derive(Serialize, Deserialize, Debug)] pub struct MapPort { #[serde(rename = "IPAddress")] pub ipaddress: String, #[serde(rename = "PortNo")] pub port_no: String, #[serde(rename = "EntireAddress")] pub entire_address: String, } #[derive(Serialize, Deserialize, Debug)] pub struct Specs { #[serde(rename = "Hostname")] pub hostname: String, #[serde(rename = "Platform")] pub platform: String, #[serde(rename = "CPU")] pub cpu: String, #[serde(rename = "RAM")] pub ram: i64, #[serde(rename = "Disk")] pub disk: i64, } // Runs p2prc with custom arguments called. // Function implemented as an identity function pub fn run_p2prc_command(arguments: &str) -> T where T: DeserializeOwned, { let command_str = format!("p2prc {}", arguments); let output = Command::new("sh") .arg("-c") .arg(&command_str) .output() .expect("Failed to execute command"); let stdout = String::from_utf8_lossy(&output.stdout); serde_json::from_str(&stdout).expect("Failed to deserialize JSON output") } // Runs p2prc map port command pub fn p2prc_map_port_command(local_port_no: &str, domain_name: &str,remote_server: &str) -> MapPort{ // Needs a reviews for a better representation let mut command = vec!["".to_string()]; match !local_port_no.is_empty() { true => command.push(format!("--mp {}", local_port_no)), false => (), } match !domain_name.is_empty() { true => command.push(format!("--dn {}", domain_name)), false => (), } match !remote_server.is_empty() { true => command.push(format!("--ra {}", remote_server)), false => (), } let command = command.join(" "); println!("{:#?}", command); let map_port: MapPort = run_p2prc_command(&*command); map_port } // Runs p2prc list server command pub fn p2prc_list_server_command() -> IPAddressList { let servers: IPAddressList = run_p2prc_command(&*"--ls".to_string()); servers } // Starts p2prc server in the background pub async fn p2prc_start_server() { let run_server: Option = run_p2prc_command(&*"-s".to_string()); } // Read P2PRC config file pub fn p2prc_read_config() -> Config { let config: Config = run_p2prc_command(&*"--vc".to_string()); config } // Writes changes to the config file // write to the config path provided in the config type // unoptimised but reduces code complexity pub fn p2prc_write_config(config: Config) { // Convert config type to a string let json:String = serde_json::to_string(&config).unwrap().to_string(); fs::write(config.config_path, json).expect("Panic message: "); } // Set default config (--dc command) pub fn p2prc_default_config() { let _: Option = run_p2prc_command(&*"--dc".to_string()); } // Get hardware information of a remote server pub fn p2prc_get_specs(ip_addr: String) -> Specs { let command: String = format!("--specs {}", ip_addr); let specs: Specs = run_p2prc_command(&*command); specs }