mirror of
https://github.com/redstrate/Kawari.git
synced 2025-04-19 22:36:49 +00:00
Add configurable boot patch location, fix verifying boot components
And more, this is mostly laying the groundwork for serving patch files.
This commit is contained in:
parent
91e80a36f8
commit
c1ad0c023c
4 changed files with 76 additions and 4 deletions
|
@ -24,7 +24,7 @@ async fn root() -> Html<String> {
|
||||||
|
|
||||||
let environment = setup_default_environment();
|
let environment = setup_default_environment();
|
||||||
let template = environment.get_template("admin.html").unwrap();
|
let template = environment.get_template("admin.html").unwrap();
|
||||||
Html(template.render(context! { worlds_open => config.worlds_open, login_open => config.login_open }).unwrap())
|
Html(template.render(context! { worlds_open => config.worlds_open, login_open => config.login_open, boot_patch_location => config.boot_patches_location }).unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
|
@ -32,6 +32,7 @@ async fn root() -> Html<String> {
|
||||||
struct Input {
|
struct Input {
|
||||||
worlds_open: Option<String>,
|
worlds_open: Option<String>,
|
||||||
login_open: Option<String>,
|
login_open: Option<String>,
|
||||||
|
boot_patch_location: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn apply(Form(input): Form<Input>) -> Redirect {
|
async fn apply(Form(input): Form<Input>) -> Redirect {
|
||||||
|
@ -51,6 +52,10 @@ async fn apply(Form(input): Form<Input>) -> Redirect {
|
||||||
config.login_open = false;
|
config.login_open = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(boot_patch_location) = input.boot_patch_location {
|
||||||
|
config.boot_patches_location = boot_patch_location;
|
||||||
|
}
|
||||||
|
|
||||||
serde_json::to_writer(
|
serde_json::to_writer(
|
||||||
&std::fs::File::create("config.json").unwrap(),
|
&std::fs::File::create("config.json").unwrap(),
|
||||||
&config,
|
&config,
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::cmp::Ordering;
|
||||||
|
use std::fs::read_dir;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
use axum::{Form, Json, Router, routing::get};
|
use axum::{Form, Json, Router, routing::get};
|
||||||
|
@ -9,6 +11,40 @@ use kawari::config::{Config, get_config};
|
||||||
use axum::extract::Path;
|
use axum::extract::Path;
|
||||||
use axum::response::IntoResponse;
|
use axum::response::IntoResponse;
|
||||||
use axum::http::{HeaderMap, StatusCode};
|
use axum::http::{HeaderMap, StatusCode};
|
||||||
|
use minijinja::filters::list;
|
||||||
|
|
||||||
|
fn list_patch_files(dir_path: &str) -> Vec<String> {
|
||||||
|
let mut entries: Vec<_> = read_dir(dir_path).unwrap().flatten().collect();
|
||||||
|
entries.sort_by_key(|dir| dir.path());
|
||||||
|
let mut game_patches: Vec<_> = entries
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(|entry| {
|
||||||
|
let Ok(meta) = entry.metadata() else {
|
||||||
|
return vec![];
|
||||||
|
};
|
||||||
|
if meta.is_dir() {
|
||||||
|
return vec![];
|
||||||
|
}
|
||||||
|
if meta.is_file() && entry.file_name().to_str().unwrap().contains(".patch") {
|
||||||
|
return vec![entry.path()];
|
||||||
|
}
|
||||||
|
vec![]
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
game_patches.sort_by(|a, b| {
|
||||||
|
// Ignore H/D in front of filenames
|
||||||
|
let mut a_path = a.as_path().file_name().unwrap().to_str().unwrap().to_string();
|
||||||
|
if a_path.starts_with("H") {
|
||||||
|
return Ordering::Less;
|
||||||
|
}
|
||||||
|
let mut b_path = b.as_path().file_name().unwrap().to_str().unwrap().to_string();
|
||||||
|
/*if b_path.starts_with("H") {
|
||||||
|
return Ordering::Greater;
|
||||||
|
}*/
|
||||||
|
a_path.partial_cmp(&b_path).unwrap()
|
||||||
|
}); // ensure we're actually installing them in the correct order
|
||||||
|
game_patches.iter().map(|x| x.file_stem().unwrap().to_str().unwrap().to_string() ).collect()
|
||||||
|
}
|
||||||
|
|
||||||
async fn verify_session(Path((platform, game_version, sid)): Path<(String, String, String)>) -> impl IntoResponse {
|
async fn verify_session(Path((platform, game_version, sid)): Path<(String, String, String)>) -> impl IntoResponse {
|
||||||
let config = get_config();
|
let config = get_config();
|
||||||
|
@ -22,12 +58,28 @@ async fn verify_session(Path((platform, game_version, sid)): Path<(String, Strin
|
||||||
(headers).into_response()
|
(headers).into_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn verify_boot(Path((platform, boot_version)): Path<(String, String)>) -> impl IntoResponse {
|
async fn verify_boot(Path((platform, boot_version)): Path<(String, String)>) -> impl IntoResponse {
|
||||||
|
tracing::info!("Verifying boot components...");
|
||||||
|
|
||||||
let config = get_config();
|
let config = get_config();
|
||||||
if !config.supports_platform(&platform) {
|
if !config.supports_platform(&platform) {
|
||||||
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
|
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Turns 2019.03.12.0000.0001/?time=2024-06-29-18-30 into just 2019.03.12.0000.0001
|
||||||
|
let actual_boot_version = boot_version.split("?time").collect::<Vec<&str>>()[0];
|
||||||
|
|
||||||
|
// check if we need any patching
|
||||||
|
let patches = list_patch_files(&config.boot_patches_location);
|
||||||
|
for patch in patches {
|
||||||
|
let patch_str: &str = &patch;
|
||||||
|
if actual_boot_version.partial_cmp(patch_str).unwrap() == Ordering::Less {
|
||||||
|
// not up to date!
|
||||||
|
// TODO: serve patchlist
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let mut headers = HeaderMap::new();
|
let mut headers = HeaderMap::new();
|
||||||
(headers).into_response()
|
(headers).into_response()
|
||||||
}
|
}
|
||||||
|
@ -38,7 +90,7 @@ async fn main() {
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
.route("/http/:platform/ffxivneo_release_game/:game_version/:sid", post(verify_session))
|
.route("/http/:platform/ffxivneo_release_game/:game_version/:sid", post(verify_session))
|
||||||
.route("/http/:platform/ffxivneo_release_boot/:boot_version", get(verify_boot));
|
.route("/http/:platform/ffxivneo_release_boot/*boot_version", get(verify_boot)); // NOTE: for future programmers, this is a wildcard because axum hates the /version/?time=blah format.
|
||||||
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 6900));
|
let addr = SocketAddr::from(([127, 0, 0, 1], 6900));
|
||||||
tracing::info!("Patch server started on {}", addr);
|
tracing::info!("Patch server started on {}", addr);
|
||||||
|
|
|
@ -10,6 +10,9 @@ pub struct Config {
|
||||||
|
|
||||||
#[serde(default = "default_supported_platforms")]
|
#[serde(default = "default_supported_platforms")]
|
||||||
pub supported_platforms: Vec<String>,
|
pub supported_platforms: Vec<String>,
|
||||||
|
|
||||||
|
#[serde(default)]
|
||||||
|
pub boot_patches_location: String
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Config {
|
impl Default for Config {
|
||||||
|
@ -17,6 +20,7 @@ impl Default for Config {
|
||||||
Self {
|
Self {
|
||||||
worlds_open: false,
|
worlds_open: false,
|
||||||
login_open: false,
|
login_open: false,
|
||||||
|
boot_patches_location: String::new(),
|
||||||
supported_platforms: default_supported_platforms()
|
supported_platforms: default_supported_platforms()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
<p>Gate open:{{ worlds_open }}</p>
|
<p>Gate open:{{ worlds_open }}</p>
|
||||||
<p>Gate open:{{ login_open }}</p>
|
<p>Gate open:{{ login_open }}</p>
|
||||||
|
<p>Boot patch location:{{ boot_patch_location }}</p>
|
||||||
<form action='apply' method='post'>
|
<form action='apply' method='post'>
|
||||||
<input type='checkbox' id='worlds_open' name='worlds_open' checked/>
|
<label>
|
||||||
<input type='checkbox' id='login_open' name='login_open' checked/>
|
Worlds Open:
|
||||||
|
<input type='checkbox' id='worlds_open' name='worlds_open' checked/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Login Open:
|
||||||
|
<input type='checkbox' id='login_open' name='login_open' checked/>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Boot Patch Location:
|
||||||
|
<input type='text' id='boot_patch_location' name='boot_patch_location'/>
|
||||||
|
</label>
|
||||||
<button type='submit'>Apply</button>
|
<button type='submit'>Apply</button>
|
||||||
</form>
|
</form>
|
Loading…
Add table
Reference in a new issue