switch to invokes instead of emits

This commit is contained in:
Joseph Montanaro
2022-12-13 16:50:44 -08:00
parent 48269855e5
commit 9055fa41aa
11 changed files with 91 additions and 40 deletions

View File

@ -2,6 +2,7 @@ use netstat2::{AddressFamilyFlags, ProtocolFlags, ProtocolSocketInfo};
use sysinfo::{System, SystemExt, Pid, ProcessExt};
use crate::errors::*;
use crate::ipc::Client;
fn get_associated_pids(local_port: u16) -> Result<Vec<u32>, netstat2::error::Error> {
@ -22,8 +23,6 @@ fn get_associated_pids(local_port: u16) -> Result<Vec<u32>, netstat2::error::Err
&& proto_info.local_addr == std::net::Ipv4Addr::LOCALHOST
&& proto_info.remote_addr == std::net::Ipv4Addr::LOCALHOST
{
println!("PIDs associated with socket: {:?}", &sock_info.associated_pids);
println!("Scanned {i} sockets");
return Ok(sock_info.associated_pids)
}
}
@ -31,16 +30,22 @@ fn get_associated_pids(local_port: u16) -> Result<Vec<u32>, netstat2::error::Err
}
pub fn get_client_info(local_port: u16) -> Result<(), ClientInfoError> {
// Theoretically, on some systems, multiple processes can share a socket. We have to
// account for this even though 99% of the time there will be only one.
pub fn get_clients(local_port: u16) -> Result<Vec<Client>, ClientInfoError> {
let mut clients = Vec::new();
let mut sys = System::new();
for p in get_associated_pids(local_port)? {
let pid = Pid::from(p as i32);
sys.refresh_process(pid);
let proc = sys.process(pid)
.ok_or(ClientInfoError::PidNotFound)?;
let path = proc.exe().to_string_lossy();
println!("exe for requesting process: {path}");
}
Ok(())
let client = Client {
pid: p,
exe: proc.exe().to_string_lossy().into_owned(),
};
clients.push(client);
}
Ok(clients)
}

View File

@ -57,6 +57,7 @@ pub enum RequestError {
MalformedHttpRequest,
RequestTooLarge,
NoCredentials(GetCredentialsError),
ClientInfo(ClientInfoError),
}
impl From<tokio::io::Error> for RequestError {
fn from(e: std::io::Error) -> RequestError {
@ -73,6 +74,11 @@ impl From<GetCredentialsError> for RequestError {
RequestError::NoCredentials(e)
}
}
impl From<ClientInfoError> for RequestError {
fn from(e: ClientInfoError) -> RequestError {
RequestError::ClientInfo(e)
}
}
impl Display for RequestError {
fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
@ -84,6 +90,8 @@ impl Display for RequestError {
RequestTooLarge => write!(f, "HTTP request too large"),
NoCredentials(GetCredentialsError::Locked) => write!(f, "Recieved go-ahead but app is locked"),
NoCredentials(GetCredentialsError::Empty) => write!(f, "Received go-ahead but no credentials are known"),
ClientInfo(ClientInfoError::PidNotFound) => write!(f, "Could not resolve PID of client process."),
ClientInfo(ClientInfoError::NetstatError(e)) => write!(f, "Error getting client socket details: {e}"),
}
}
}

View File

@ -4,9 +4,17 @@ use tauri::State;
use crate::state::{AppState, Session};
#[derive(Copy, Clone, Serialize, Deserialize)]
#[derive(Clone, Serialize, Deserialize)]
pub struct Client {
pub pid: u32,
pub exe: String,
}
#[derive(Clone, Serialize, Deserialize)]
pub struct Request {
pub id: u64,
pub clients: Vec<Client>,
}
@ -41,7 +49,7 @@ pub async fn unlock(passphrase: String, app_state: State<'_, AppState>) -> Resul
#[tauri::command]
pub fn session_status(app_state: State<'_, AppState>) -> String {
pub fn get_session_status(app_state: State<'_, AppState>) -> String {
let session = app_state.session.read().unwrap();
match *session {
Session::Locked(_) => "locked".into(),

View File

@ -21,7 +21,11 @@ fn main() {
tauri::Builder::default()
.manage(initial_state)
.invoke_handler(tauri::generate_handler![ipc::unlock, ipc::respond])
.invoke_handler(tauri::generate_handler![
ipc::unlock,
ipc::respond,
ipc::get_session_status,
])
.setup(|app| {
let addr = std::net::SocketAddrV4::from_str("127.0.0.1:12345").unwrap();
tauri::async_runtime::spawn(server::serve(addr, app.handle()));

View File

@ -6,6 +6,7 @@ use tokio::sync::oneshot;
use tauri::{AppHandle, Manager};
use crate::clientinfo;
use crate::errors::RequestError;
use crate::ipc::{Request, Approval};
@ -46,12 +47,15 @@ async fn handle(mut stream: TcpStream, app_handle: AppHandle) -> Result<(), Requ
let app_state = app_handle.state::<crate::state::AppState>();
let request_id = app_state.register_request(chan_send);
if let std::net::SocketAddr::V4(addr) = stream.peer_addr()? {
crate::clientinfo::get_client_info(addr.port());
}
let peer_addr = match stream.peer_addr()? {
std::net::SocketAddr::V4(addr) => addr,
_ => unreachable!(), // we only listen on IPv4
};
let clients = clientinfo::get_clients(peer_addr.port())?;
// Do we want to panic if this fails? Does that mean the frontend is dead?
app_handle.emit_all("credentials-request", Request {id: request_id}).unwrap();
let req = Request {id: request_id, clients};
app_handle.emit_all("credentials-request", req).unwrap();
let mut buf = [0; 8192]; // it's what tokio's BufReader uses
let mut n = 0;