1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-07-09 15:37:45 +00:00

Unify version and file checking behind one config parameter

And make it affect the patch server as well, if you really want to
use an unsupported version.
This commit is contained in:
Joshua Goins 2025-07-04 11:56:12 -04:00
parent 70c423e48f
commit 7ccd132129
3 changed files with 108 additions and 84 deletions

View file

@ -224,7 +224,7 @@ async fn main() {
let config = get_config();
// The lobby server does its own version check as well, but it can be turned off if desired.
if config.lobby.do_version_checks
if config.enforce_validity_checks
&& !do_game_version_check(version_info)
{
// "A version update is required."

View file

@ -88,48 +88,56 @@ async fn verify_session(
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
tracing::info!("Verifying game components for {platform} {channel} {game_version} {body}...");
if config.enforce_validity_checks {
tracing::info!(
"Verifying game components for {platform} {channel} {game_version} {body}..."
);
let body_parts: Vec<&str> = body.split('\n').collect();
let body_parts: Vec<&str> = body.split('\n').collect();
let _hashes = body_parts[0];
let expansion_versions = &body_parts[1..body_parts.len() - 1]; // last part is empty
let _hashes = body_parts[0];
let expansion_versions = &body_parts[1..body_parts.len() - 1]; // last part is empty
let game_version = Version(&game_version);
let game_version = Version(&game_version);
let supported_expac_versions = get_supported_expac_versions();
let supported_expac_versions = get_supported_expac_versions();
for expansion_version in expansion_versions {
let expac_version_parts: Vec<&str> = expansion_version.split('\t').collect();
let expansion_name = expac_version_parts[0]; // e.g. ex1
let expansion_version = expac_version_parts[1];
for expansion_version in expansion_versions {
let expac_version_parts: Vec<&str> = expansion_version.split('\t').collect();
let expansion_name = expac_version_parts[0]; // e.g. ex1
let expansion_version = expac_version_parts[1];
if Version(expansion_version) > supported_expac_versions[expansion_name] {
if Version(expansion_version) > supported_expac_versions[expansion_name] {
tracing::warn!(
"{expansion_name} {expansion_version} is above supported version {}!",
supported_expac_versions[expansion_name]
);
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
}
// Their version is too new
if game_version > SUPPORTED_GAME_VERSION {
tracing::warn!(
"{expansion_name} {expansion_version} is above supported version {}!",
supported_expac_versions[expansion_name]
"{game_version} is above supported game version {SUPPORTED_GAME_VERSION}!"
);
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
}
// Their version is too new
if game_version > SUPPORTED_GAME_VERSION {
tracing::warn!("{game_version} is above supported game version {SUPPORTED_GAME_VERSION}!");
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
if game_version < SUPPORTED_GAME_VERSION {
tracing::warn!(
"{game_version} is below supported game version {SUPPORTED_GAME_VERSION}!"
);
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
if game_version < SUPPORTED_GAME_VERSION {
tracing::warn!("{game_version} is below supported game version {SUPPORTED_GAME_VERSION}!");
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
// If we are up to date, yay!
if game_version == SUPPORTED_GAME_VERSION {
let mut headers = HeaderMap::new();
headers.insert("X-Patch-Unique-Id", sid.parse().unwrap());
// If we are up to date, yay!
if game_version == SUPPORTED_GAME_VERSION {
let mut headers = HeaderMap::new();
headers.insert("X-Patch-Unique-Id", sid.parse().unwrap());
return (headers).into_response();
return (headers).into_response();
}
}
let mut headers = HeaderMap::new();
@ -147,66 +155,75 @@ async fn verify_boot(
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
tracing::info!("Verifying boot components for {platform} {channel} {boot_version}...");
let config = get_config();
if !config.supports_platform(&platform) {
tracing::warn!("Invalid platform! {platform}");
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
let actual_boot_version = boot_version.split("?time").collect::<Vec<&str>>()[0];
let boot_version = Version(actual_boot_version);
if config.enforce_validity_checks {
tracing::info!("Verifying boot components for {platform} {channel} {boot_version}...");
// If we are up to date, yay!
if boot_version == SUPPORTED_BOOT_VERSION {
let headers = HeaderMap::new();
return (headers).into_response();
}
// Their version is too new
if boot_version > SUPPORTED_BOOT_VERSION {
tracing::warn!("{boot_version} is above supported boot version {SUPPORTED_BOOT_VERSION}!");
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
// check if we need any patching
let mut send_patches = Vec::new();
let patches = list_patch_files(&format!("{}/boot", &config.patch.patches_location));
for patch in patches {
let patch_str: &str = &patch;
if actual_boot_version.partial_cmp(patch_str).unwrap() == Ordering::Less {
let file = std::fs::File::open(&*format!(
"{}/boot/{}.patch",
&config.patch.patches_location, patch_str
))
.unwrap();
let metadata = file.metadata().unwrap();
send_patches.push(PatchEntry {
url: format!("http://{}/boot/{}.patch", config.patch.patch_dl_url, patch)
.to_string(),
version: patch_str.to_string(),
hash_block_size: 50000000,
length: metadata.len() as i64,
size_on_disk: metadata.len() as i64, // NOTE: wrong but it should be fine to lie
hashes: vec![],
unknown_a: 0,
unknown_b: 0,
});
let config = get_config();
if !config.supports_platform(&platform) {
tracing::warn!("Invalid platform! {platform}");
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
}
if !send_patches.is_empty() {
let patch_list = PatchList {
id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(),
requested_version: boot_version.to_string().clone(),
content_location: format!("ffxivpatch/boot/metainfo/{}.http", boot_version.0), // FIXME: i think this is actually supposed to be the target version
patch_length: 0,
patches: send_patches,
};
let patch_list_str = patch_list.to_string(PatchListType::Boot);
return patch_list_str.into_response();
let actual_boot_version = boot_version.split("?time").collect::<Vec<&str>>()[0];
let boot_version = Version(actual_boot_version);
// If we are up to date, yay!
if boot_version == SUPPORTED_BOOT_VERSION {
let headers = HeaderMap::new();
return (headers).into_response();
}
// Their version is too new
if boot_version > SUPPORTED_BOOT_VERSION {
tracing::warn!(
"{boot_version} is above supported boot version {SUPPORTED_BOOT_VERSION}!"
);
return StatusCode::INTERNAL_SERVER_ERROR.into_response();
}
// check if we need any patching
let mut send_patches = Vec::new();
let patches = list_patch_files(&format!("{}/boot", &config.patch.patches_location));
for patch in patches {
let patch_str: &str = &patch;
if actual_boot_version.partial_cmp(patch_str).unwrap() == Ordering::Less {
let file = std::fs::File::open(&*format!(
"{}/boot/{}.patch",
&config.patch.patches_location, patch_str
))
.unwrap();
let metadata = file.metadata().unwrap();
send_patches.push(PatchEntry {
url: format!("http://{}/boot/{}.patch", config.patch.patch_dl_url, patch)
.to_string(),
version: patch_str.to_string(),
hash_block_size: 50000000,
length: metadata.len() as i64,
size_on_disk: metadata.len() as i64, // NOTE: wrong but it should be fine to lie
hashes: vec![],
unknown_a: 0,
unknown_b: 0,
});
}
}
if !send_patches.is_empty() {
let patch_list = PatchList {
id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(),
requested_version: boot_version.to_string().clone(),
content_location: format!("ffxivpatch/boot/metainfo/{}.http", boot_version.0), // FIXME: i think this is actually supposed to be the target version
patch_length: 0,
patches: send_patches,
};
let patch_list_str = patch_list.to_string(PatchListType::Boot);
return patch_list_str.into_response();
}
}
let headers = HeaderMap::new();

View file

@ -66,7 +66,6 @@ impl FrontierConfig {
pub struct LobbyConfig {
pub port: u16,
pub listen_address: String,
pub do_version_checks: bool,
}
impl Default for LobbyConfig {
@ -74,7 +73,6 @@ impl Default for LobbyConfig {
Self {
port: 7000,
listen_address: "0.0.0.0".to_string(),
do_version_checks: true,
}
}
}
@ -401,6 +399,10 @@ pub struct Config {
/// Enable various packet debug functions. This will clutter your working directory!
#[serde(default)]
pub packet_debugging: bool,
/// Enable various validity checks for version and file hashes that emulate retail.
#[serde(default = "Config::default_enforce_validity_checks")]
pub enforce_validity_checks: bool,
}
impl Default for Config {
@ -418,6 +420,7 @@ impl Default for Config {
launcher: LauncherConfig::default(),
save_data_bank: SaveDataBankConfig::default(),
packet_debugging: false,
enforce_validity_checks: Self::default_enforce_validity_checks(),
}
}
}
@ -426,6 +429,10 @@ impl Config {
pub fn supports_platform(&self, platform: &String) -> bool {
self.supported_platforms.contains(platform)
}
fn default_enforce_validity_checks() -> bool {
true
}
}
fn default_supported_platforms() -> Vec<String> {