SDKServer: config & entry structures

This commit is contained in:
xeon 2024-05-26 22:08:56 +03:00
parent 650dab7606
commit eead7e1573
12 changed files with 156 additions and 56 deletions

View file

@ -21,6 +21,7 @@ lazy_static = "1.4.0"
leb128 = "0.2.5" leb128 = "0.2.5"
paste = "1.0.14" paste = "1.0.14"
sysinfo = "0.30.7" sysinfo = "0.30.7"
rand = "0.8.5"
csv = "1.3.0" csv = "1.3.0"
serde = { version = "1.0.197", features = ["derive"] } serde = { version = "1.0.197", features = ["derive"] }

View file

@ -0,0 +1,15 @@
{
"InfoGroups": {
"StandaloneWindows64": {
"VersionInfoGroups": {
"0.1.0": {
"MinVersion": "0.1.0",
"LatestVersion": "0.1.18",
"GameResUrl": "http://127.0.0.1:21000/game_res/NAP_Publish/output_147608_1361f678bc/client/",
"DesignDataUrl": "http://127.0.0.1:21000/",
"ServerListUrl": "http://127.0.0.1:21000/design_data/NAP_Publish_AppStore_0.1.0/oversea/serverlist.bin"
}
}
}
}
}

View file

@ -0,0 +1,11 @@
[
{
"sid": 142,
"serverName": "HollowPS",
"ip": "127.0.0.1",
"port": "21000",
"noticeRegion": "nap_glb_cbus01",
"protocol": "http",
"$Type": "MoleMole.ServerListInfo"
}
]

View file

@ -17,6 +17,8 @@ serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
tokio-util.workspace = true tokio-util.workspace = true
ansi_term.workspace = true ansi_term.workspace = true
lazy_static.workspace = true
rand.workspace = true
[[bin]] [[bin]]
name = "nap-sdkserver" name = "nap-sdkserver"

View file

@ -15,7 +15,7 @@ pub fn encrypt_config(content: &str, key: &str) -> Vec<u8> {
leb128::write::unsigned(&mut out, u64::try_from(k.len()).unwrap()).unwrap(); leb128::write::unsigned(&mut out, u64::try_from(k.len()).unwrap()).unwrap();
out.extend_from_slice(k); out.extend_from_slice(k);
out.extend(0_u32.to_le_bytes()); out.extend([0u8; 4]);
out.extend(u32::try_from(content_bytes.len()).unwrap().to_le_bytes()); out.extend(u32::try_from(content_bytes.len()).unwrap().to_le_bytes());
out.extend(content_bytes); out.extend(content_bytes);

View file

@ -0,0 +1,38 @@
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct ConfigInfo {
pub min_version: String,
pub latest_version: String,
pub game_res_url: String,
pub design_data_url: String,
pub server_list_url: String,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct ConfigInfoGroup {
pub version_info_groups: HashMap<String, ConfigInfo>,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct AppConfig {
pub info_groups: HashMap<String, ConfigInfoGroup>,
}
#[derive(Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ServerListInfo {
pub sid: i32,
pub server_name: String,
pub ip: String,
pub port: String,
pub notice_region: String,
pub protocol: String,
#[serde(rename = "$Type")]
ty: String,
}

View file

@ -0,0 +1,23 @@
use serde::Serialize;
#[derive(Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct HttpRet<Ext> {
pub error_code: i32,
pub error_msg: Option<String>,
pub ext: Ext,
}
#[derive(Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct EntryTokenRet {
pub birthday: String,
pub country: String,
pub token: String,
}
#[derive(Serialize)]
#[serde(rename_all = "PascalCase")]
pub struct EntryAccountServerRet {
pub address: String,
}

View file

@ -0,0 +1,2 @@
pub mod config;
pub mod entry;

View file

@ -7,6 +7,7 @@ use axum::{
}; };
mod crypto; mod crypto;
mod data;
mod services; mod services;
use services::{auth, config, entry, errors}; use services::{auth, config, entry, errors};

View file

@ -1,57 +1,62 @@
use axum::{body::Body, response::IntoResponse}; use axum::{body::Body, response::IntoResponse};
use serde_json::json; use lazy_static::lazy_static;
use rand::Rng;
use serde::de::DeserializeOwned;
use crate::crypto; use crate::crypto;
use crate::data::config::*;
pub const APP_CONFIG_ENDPOINT: &str = "/design_data/NAP_Publish_AppStore_0.1.0/oversea/config.bin"; pub const APP_CONFIG_ENDPOINT: &str = "/design_data/NAP_Publish_AppStore_0.1.0/oversea/config.bin";
pub const SERVER_LIST_ENDPOINT: &str = pub const SERVER_LIST_ENDPOINT: &str =
"/design_data/NAP_Publish_AppStore_0.1.0/oversea/serverlist.bin"; "/design_data/NAP_Publish_AppStore_0.1.0/oversea/serverlist.bin";
pub const VERSIONS_BUNDLE_ENDPOINT: &str = "/game_res/NAP_Publish/output_147608_1361f678bc/client/StandaloneWindows64/oversea/versions.bundle"; pub const VERSIONS_BUNDLE_ENDPOINT: &str = "/game_res/NAP_Publish/output_147608_1361f678bc/client/StandaloneWindows64/oversea/versions.bundle";
lazy_static! {
static ref APP_CONFIG: AppConfig = read_config("config.json");
static ref SERVER_LIST: Vec<ServerListInfo> = read_config("serverlist.json");
static ref VERSIONS_BUNDLE: Box<[u8]> = read_binary_data("versions.bundle");
}
pub async fn application() -> Vec<u8> { pub async fn application() -> Vec<u8> {
crypto::encrypt_config( crypto::encrypt_config(
json!({ serde_json::to_string(&*APP_CONFIG).unwrap().as_str(),
"InfoGroups": { &random_xorpad(16),
"StandaloneWindows64": {
"VersionInfoGroups": {
"0.1.0": {
"MinVersion": "0.1.0",
"LatestVersion": "0.1.0",
"GameResUrl": "http://127.0.0.1:21000/game_res/NAP_Publish/output_147608_1361f678bc/client/",
"DesignDataUrl": "http://127.0.0.1:21000/",
"ServerListUrl": "http://127.0.0.1:21000/design_data/NAP_Publish_AppStore_0.1.0/oversea/serverlist.bin",
"$Type": "Foundation.ConfigurationInfo"
},
},
"$Type": "Foundation.ConfigurationInfoGroup"
},
},
})
.to_string()
.as_str(),
"MostSecureKey",
) )
} }
pub async fn server_list() -> Vec<u8> { pub async fn server_list() -> Vec<u8> {
crypto::encrypt_config( crypto::encrypt_config(
json!([{ serde_json::to_string(&*SERVER_LIST).unwrap().as_str(),
"sid": 142, &random_xorpad(16),
"serverName": "HollowPS",
"ip": "127.0.0.1",
"port": "21000",
"noticeRegion": "nap_glb_cbus01",
"protocol": "http",
"$Type": "MoleMole.ServerListInfo"
}])
.to_string()
.as_str(),
"MostSecureKey",
) )
} }
pub const VERSION_BUNDLE: &[u8] = include_bytes!("../../versions.bundle");
pub async fn versions_bundle() -> impl IntoResponse { pub async fn versions_bundle() -> impl IntoResponse {
Body::from(VERSION_BUNDLE) Body::from(&**VERSIONS_BUNDLE)
}
fn read_config<T>(file: &str) -> T
where
T: DeserializeOwned,
{
let data = std::fs::read_to_string(format!("assets/Application/{file}")).unwrap();
serde_json::from_str::<T>(&data).unwrap()
}
fn read_binary_data(file: &str) -> Box<[u8]> {
std::fs::read(format!("assets/Application/{file}"))
.unwrap()
.into()
}
fn random_xorpad(len: usize) -> String {
const CHARSET: &[u8] = b"0123456789";
let mut rng = rand::thread_rng();
(0..len)
.map(|_| {
let idx = rng.gen_range(0..CHARSET.len());
CHARSET[idx] as char
})
.collect()
} }

View file

@ -1,31 +1,33 @@
use crate::data::entry::*;
use axum::Json; use axum::Json;
use serde_json::json;
pub const ACCOUNT_TOKEN_ENDPOINT: &str = "/account/token"; pub const ACCOUNT_TOKEN_ENDPOINT: &str = "/account/token";
pub const ACCOUNT_SERVER_ENDPOINT: &str = "/account/account_server"; pub const ACCOUNT_SERVER_ENDPOINT: &str = "/account/account_server";
#[tracing::instrument] #[tracing::instrument]
pub async fn account_token() -> Json<serde_json::Value> { pub async fn account_token() -> Json<HttpRet<EntryTokenRet>> {
tracing::info!("account_token"); tracing::info!("account_token");
Json(json!({
"ErrorCode": 0, Json(HttpRet {
"ErrorMsg": null, error_code: 0,
"Ext": { error_msg: None,
"Birthday": "01.01", ext: EntryTokenRet {
"Country": "RU", birthday: String::from("01.01"),
"Token": "MostSecureTokenEver" country: String::from("RU"),
} token: String::from("MostSecureTokenEver"),
})) },
})
} }
#[tracing::instrument] #[tracing::instrument]
pub async fn account_server() -> Json<serde_json::Value> { pub async fn account_server() -> Json<HttpRet<EntryAccountServerRet>> {
tracing::info!("account_server"); tracing::info!("account_server");
Json(json!({
"ErrorCode": 0, Json(HttpRet {
"ErrorMsg": null, error_code: 0,
"Ext": { error_msg: None,
"Address": "127.0.0.1:10301/0" ext: EntryAccountServerRet {
} address: String::from("127.0.0.1:10301/0"),
})) },
})
} }