2022-08-14 20:27:41 +00:00
|
|
|
use std::io;
|
|
|
|
use std::net::SocketAddrV4;
|
|
|
|
use tokio::net::{TcpListener, TcpStream};
|
|
|
|
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
|
|
|
|
|
|
|
use tauri::{AppHandle, Manager};
|
|
|
|
|
|
|
|
mod errors;
|
|
|
|
use errors::RequestError;
|
|
|
|
|
|
|
|
|
|
|
|
pub async fn serve(addr: SocketAddrV4, app_handle: AppHandle) -> io::Result<()> {
|
|
|
|
let listener = TcpListener::bind(&addr).await?;
|
|
|
|
println!("Listening on {addr}");
|
|
|
|
loop {
|
|
|
|
let new_handle = app_handle.app_handle();
|
|
|
|
match listener.accept().await {
|
|
|
|
Ok((stream, _)) => {
|
|
|
|
tokio::spawn(async {
|
|
|
|
if let Err(e) = handle(stream, new_handle).await {
|
|
|
|
eprintln!("{e}");
|
|
|
|
}
|
|
|
|
});
|
|
|
|
},
|
|
|
|
Err(e) => {
|
2022-11-28 06:03:15 +00:00
|
|
|
eprintln!("Error accepting connection: {e}");
|
2022-08-14 20:27:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// it doesn't really return a String, we just need to placate the compiler
|
|
|
|
async fn stall(stream: &mut TcpStream) -> Result<String, tokio::io::Error> {
|
|
|
|
let delay = std::time::Duration::from_secs(1);
|
|
|
|
loop {
|
|
|
|
tokio::time::sleep(delay).await;
|
|
|
|
stream.write(b"x").await?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
async fn handle(mut stream: TcpStream, app_handle: AppHandle) -> Result<(), RequestError> {
|
|
|
|
let mut buf = [0; 8192]; // it's what tokio's BufReader uses
|
|
|
|
let mut n = 0;
|
|
|
|
loop {
|
|
|
|
n += stream.read(&mut buf[n..]).await?;
|
|
|
|
if &buf[(n - 4)..n] == b"\r\n\r\n" {break;}
|
|
|
|
if n == buf.len() {return Err(RequestError::RequestTooLarge);}
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("{}", std::str::from_utf8(&buf).unwrap());
|
|
|
|
|
|
|
|
stream.write(b"HTTP/1.0 200 OK\r\n").await?;
|
|
|
|
stream.write(b"Content-Type: application/json\r\n").await?;
|
|
|
|
stream.write(b"X-Creddy-delaying-tactic: ").await?;
|
|
|
|
|
|
|
|
let creds = tokio::select!{
|
|
|
|
r = stall(&mut stream) => r?, // this will never return Ok, just Err if it can't write to the stream
|
|
|
|
c = get_creds(&app_handle) => c?,
|
|
|
|
};
|
|
|
|
|
|
|
|
stream.write(b"\r\nContent-Length: ").await?;
|
|
|
|
stream.write(creds.as_bytes().len().to_string().as_bytes()).await?;
|
|
|
|
stream.write(b"\r\n\r\n").await?;
|
|
|
|
stream.write(creds.as_bytes()).await?;
|
|
|
|
stream.write(b"\r\n\r\n").await?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
use tokio::io::{stdin, stdout, BufReader, AsyncBufReadExt};
|
|
|
|
use crate::storage;
|
|
|
|
|
|
|
|
use tokio::sync::oneshot;
|
2022-11-28 06:03:15 +00:00
|
|
|
use std::sync::Mutex;
|
2022-08-14 20:27:41 +00:00
|
|
|
|
|
|
|
async fn get_creds(app_handle: &AppHandle) -> io::Result<String> {
|
2022-11-28 06:03:15 +00:00
|
|
|
{
|
|
|
|
let state_guard = app_handle.state::<Mutex<crate::AppState>>();
|
|
|
|
let mut state = state_guard.lock().unwrap();
|
|
|
|
state.num_requests += 1;
|
|
|
|
let req = crate::CredentialsRequest {
|
|
|
|
request_id: state.num_requests
|
|
|
|
};
|
|
|
|
app_handle.emit_all("credentials-request", req).unwrap();
|
|
|
|
// lock gets released here in case somebody else needs app state while we're waiting
|
|
|
|
}
|
2022-08-14 20:27:41 +00:00
|
|
|
|
|
|
|
let (tx, rx) = oneshot::channel();
|
2022-11-28 06:03:15 +00:00
|
|
|
app_handle.once_global("request-response", |event| {
|
|
|
|
let response = event.payload().unwrap_or("").to_string();
|
|
|
|
tx.send(response).unwrap();
|
2022-08-14 20:27:41 +00:00
|
|
|
});
|
|
|
|
// Error is only returned if the rx is closed/dropped before receiving, which should never happen
|
2022-11-28 06:03:15 +00:00
|
|
|
// LOL who am I kidding this happens all the time
|
|
|
|
// fix it later
|
|
|
|
|
|
|
|
// todo: handle "denied" response
|
|
|
|
let _response = rx.await.unwrap();
|
|
|
|
let state_guard = app_handle.state::<Mutex<crate::AppState>>();
|
|
|
|
let state = state_guard.lock().unwrap();
|
|
|
|
|
|
|
|
Ok(state.current_session.clone().unwrap())
|
2022-08-14 20:27:41 +00:00
|
|
|
}
|