#![feature(proc_macro_hygiene, decl_macro)] #[macro_use] extern crate rocket; use rocket::State; use rocket::response::status::NotFound; use rocket::Data; use rocket_contrib::json::Json; use serde_json::Value; use serde_json::json; use rocket_contrib::uuid::Uuid; use rocket_contrib::serve::StaticFiles; use std::sync::Mutex; use std::collections::HashMap; use std::path::Path; mod workunit; use workunit::WUnit; use workunit::EStatus; const VERSION: &str = "0.5.0"; #[derive(Default, Debug)] struct SharedState { jobs: Mutex> } #[get("/")] fn index() -> String { format!("Wecome to the AV1Master Server version {version}\n This currently requires a distro with CAP_SYS_USER_NS enabled and correct permissions curl -L {baseurl}/client.sh > client.sh && chmod +x ./av1client && ./av1client {baseurl}", version=VERSION, baseurl="https://av1.dodsorf.as") } #[get("/version")] fn version() -> &'static str { VERSION } #[get("/get_jobs")] fn get_jobs(shared: State) -> Json { let list = shared.jobs.lock().unwrap().clone(); Json(serde_json::to_value(&list).unwrap()) } #[get("/request_job")] fn request_job(shared: State) -> Result, NotFound> { let mut list: Vec = shared.jobs.lock().unwrap() .values() .filter(|x| x.status == EStatus::Queued).cloned() .collect(); list.sort_by(|a, b| b.description.length.cmp(&a.description.length)); let job = list.get(0); Ok(Json(serde_json::to_value(&job).unwrap())) } #[get("/get_job/")] fn get_job(id: Uuid, shared: State) -> Result, NotFound> { let list = shared.jobs.lock().unwrap(); let job = list.get(&id).ok_or(NotFound(format!("Job not Found: {id}", id = id))); match job { Ok(j) => Ok(Json(serde_json::to_value(&j).unwrap())), Err(e) => Err(e) } } pub struct RealIP(std::net::IpAddr); impl<'a, 'r> rocket::request::FromRequest<'a, 'r> for RealIP { type Error = (); fn from_request(request: &'a rocket::Request<'r>) -> rocket::request::Outcome { match request.client_ip() { Some(ip) => rocket::Outcome::Success(RealIP(ip)), None => rocket::Outcome::Failure((rocket::http::Status::from_code(401).unwrap(), ())) } } } #[get("/edit_status//")] fn edit_status(id: Uuid, status: String, shared: State, remote_addr: RealIP) -> Result> { let mut list = shared.jobs.lock().unwrap(); let job = list.get_mut(&id).ok_or("what")?; let status = match status.as_str() { "queued" => Ok(EStatus::Queued), "reserved" => Ok(EStatus::Reserved(remote_addr.0.to_string())), "completed" => Ok(EStatus::Completed(remote_addr.0.to_string())), "error" => Ok(EStatus::Error(remote_addr.0.to_string())), _ => Err("Not a valid status, valid statuses are queued, reserved, completed, and error") }?; job.status = status; Ok("Status changed".to_string()) } #[post("/upload/", data = "