creddy/src-tauri/src/clientinfo.rs

123 lines
3.5 KiB
Rust
Raw Normal View History

use std::path::{Path, PathBuf};
2022-12-20 13:01:44 -08:00
use sysinfo::{System, SystemExt, Pid, PidExt, ProcessExt};
2022-12-19 16:20:46 -08:00
use serde::{Serialize, Deserialize};
use std::os::windows::io::AsRawHandle;
2022-12-03 21:47:09 -08:00
#[cfg(windows)]
use {
tokio::net::windows::named_pipe::NamedPipeServer,
windows::Win32::{
Foundation::HANDLE,
System::Pipes::GetNamedPipeClientProcessId,
},
2023-05-02 15:24:35 -07:00
};
2022-12-19 16:20:46 -08:00
#[cfg(unix)]
use tokio::net::UnixStream;
use crate::errors::*;
2022-12-19 16:20:46 -08:00
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq, Hash)]
2022-12-19 16:20:46 -08:00
pub struct Client {
pub pid: u32,
pub exe: Option<PathBuf>,
2022-12-19 16:20:46 -08:00
}
2022-12-03 21:47:09 -08:00
#[cfg(unix)]
pub fn get_client_parent(stream: &UnixStream) -> Result<Client, ClientInfoError> {
let pid = stream.peer_cred()?;
get_process_parent_info(pid)?
2022-12-03 21:47:09 -08:00
}
#[cfg(windows)]
pub fn get_client_parent(stream: &NamedPipeServer) -> Result<Client, ClientInfoError> {
let raw_handle = stream.as_raw_handle();
let mut pid = 0u32;
let handle = HANDLE(raw_handle as _);
unsafe { GetNamedPipeClientProcessId(handle, &mut pid as *mut u32)? };
get_process_parent_info(pid)
}
fn get_process_parent_info(pid: u32) -> Result<Client, ClientInfoError> {
let sys_pid = Pid::from_u32(pid);
let mut sys = System::new();
sys.refresh_process(sys_pid);
let proc = sys.process(sys_pid)
.ok_or(ClientInfoError::ProcessNotFound)?;
let parent_pid_sys = proc.parent()
.ok_or(ClientInfoError::ParentPidNotFound)?;
sys.refresh_process(parent_pid_sys);
let parent = sys.process(parent_pid_sys)
.ok_or(ClientInfoError::ParentProcessNotFound)?;
let exe = match parent.exe() {
p if p == Path::new("") => None,
p => Some(PathBuf::from(p)),
};
Ok(Client { pid: parent_pid_sys.as_u32(), exe })
2022-12-03 21:47:09 -08:00
}
// async fn get_associated_pids(local_port: u16) -> Result<Vec<u32>, netstat2::error::Error> {
// let state = APP.get().unwrap().state::<AppState>();
// let AppConfig {
// listen_addr: app_listen_addr,
// listen_port: app_listen_port,
// ..
// } = *state.config.read().await;
// let sockets_iter = netstat2::iterate_sockets_info(
// AddressFamilyFlags::IPV4,
// ProtocolFlags::TCP
// )?;
// for item in sockets_iter {
// let sock_info = item?;
// let proto_info = match sock_info.protocol_socket_info {
// ProtocolSocketInfo::Tcp(tcp_info) => tcp_info,
// ProtocolSocketInfo::Udp(_) => {continue;}
// };
// if proto_info.local_port == local_port
// && proto_info.remote_port == app_listen_port
// && proto_info.local_addr == app_listen_addr
// && proto_info.remote_addr == app_listen_addr
// {
// return Ok(sock_info.associated_pids)
// }
// }
// Ok(vec![])
// }
// Theoretically, on some systems, multiple processes can share a socket
// pub async fn get_clients(local_port: u16) -> Result<Vec<Option<Client>>, ClientInfoError> {
// let mut clients = Vec::new();
// let mut sys = System::new();
// for p in get_associated_pids(local_port).await? {
// let pid = Pid::from_u32(p);
// sys.refresh_process(pid);
// let proc = sys.process(pid)
// .ok_or(ClientInfoError::ProcessNotFound)?;
// let client = Client {
// pid: p,
// exe: proc.exe().to_path_buf(),
// };
// clients.push(Some(client));
// }
// if clients.is_empty() {
// clients.push(None);
// }
// Ok(clients)
// }