diff --git a/Cargo.toml b/Cargo.toml index 82b82f9..790213f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,55 +1,24 @@ -[workspace] -members = [ "common","gameserver", "protocol", "qwer", "qwer/qwer-derive", "sdkserver"] -resolver = "2" +[package] +name = "sdkserver" +edition = "2021" +version.workspace = true -[workspace.package] -version = "0.1.0" +[dependencies] +axum.workspace = true +axum-server.workspace = true +encoding.workspace = true +leb128.workspace = true +anyhow.workspace = true +env_logger.workspace = true +tokio.workspace = true +tracing.workspace = true +tracing-subscriber.workspace = true +serde.workspace = true +serde_json.workspace = true +tokio-util.workspace = true +ansi_term.workspace = true +rand.workspace = true -[workspace.dependencies] -ansi_term = "0.12.1" -anyhow = "1.0.81" -axum = "0.7.4" -axum-server = "0.6.0" -byteorder = "1.5.0" -dirs = "5.0.1" -encoding = "0.2.33" -env_logger = "0.11.3" -heck = "0.5.0" -hex = "0.4.3" -leb128 = "0.2.5" -paste = "1.0.14" -sysinfo = "0.30.7" -rand = "0.8.5" -parking_lot = "0.12.3" - -csv = "1.3.0" -serde = { version = "1.0.197", features = ["derive"] } -serde_json = "1.0.114" - -tokio = { version = "1.36.0", features = ["full"] } -tokio-util = { version = "0.7.10", features = ["io"] } - -tracing = "0.1.40" -tracing-futures = "0.2.5" -tracing-log = { version = "0.2.0", features = ["std", "log-tracer"] } -tracing-subscriber = { version = "0.3.18", features = [ - "env-filter", - "registry", - "std", - "tracing", - "tracing-log", -] } -tracing-bunyan-formatter = "0.3.9" - -itertools = "0.13.0" - -common = { version = "0.1.0", path = "common" } -protocol = { version = "0.1.0", path = "protocol" } -qwer = { version = "0.1.0", path = "qwer", features = ["full"] } -qwer-derive = { version = "0.1.0", path = "qwer/qwer-derive" } - -[profile.release] -strip = true # Automatically strip symbols from the binary. -lto = true # Link-time optimization. -opt-level = 3 # Optimize for speed. -codegen-units = 1 # Maximum size reduction optimizations. +[[bin]] +name = "nap-sdkserver" +path = "src/main.rs" diff --git a/config.rs b/config.rs new file mode 100644 index 0000000..2c45105 --- /dev/null +++ b/config.rs @@ -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, +} + +#[derive(Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct AppConfig { + pub info_groups: HashMap, +} + +#[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, +} diff --git a/crypto.rs b/crypto.rs new file mode 100644 index 0000000..eef6817 --- /dev/null +++ b/crypto.rs @@ -0,0 +1,23 @@ +use encoding::all::UTF_16LE; +use encoding::{EncoderTrap, Encoding}; + +pub fn encrypt_config(content: &str, key: &str) -> Vec { + let mut content_bytes = UTF_16LE.encode(content, EncoderTrap::Strict).unwrap(); + let key_bytes = UTF_16LE.encode(key, EncoderTrap::Strict).unwrap(); + + for i in 0..content_bytes.len() { + content_bytes[i] ^= key_bytes[i % key_bytes.len()]; + } + + let k = key.as_bytes(); + + let mut out = Vec::with_capacity(4 + k.len() + 8 + content_bytes.len()); + + leb128::write::unsigned(&mut out, u64::try_from(k.len()).unwrap()).unwrap(); + out.extend_from_slice(k); + out.extend([0u8; 4]); + out.extend(u32::try_from(content_bytes.len()).unwrap().to_le_bytes()); + out.extend(content_bytes); + + out +} diff --git a/entry.rs b/entry.rs new file mode 100644 index 0000000..83b96c1 --- /dev/null +++ b/entry.rs @@ -0,0 +1,23 @@ +use serde::Serialize; + +#[derive(Serialize)] +#[serde(rename_all = "PascalCase")] +pub struct HttpRet { + pub error_code: i32, + pub error_msg: Option, + 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, +} diff --git a/main.rs b/main.rs new file mode 100644 index 0000000..3a5dc91 --- /dev/null +++ b/main.rs @@ -0,0 +1,71 @@ +use anyhow::Result; +use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Registry}; + +use axum::{ + routing::{get, post}, + Router, +}; + +mod crypto; +mod data; +mod services; + +use services::{auth, config, entry, errors}; + +const HOST: &str = "0.0.0.0"; +const PORT: u16 = 21000; + +#[tokio::main] +async fn main() -> Result<()> { + init_tracing()?; + + let router = Router::new() + .route(auth::RISKY_API_CHECK_ENDPOINT, post(auth::risky_api_check)) + .route( + auth::LOGIN_WITH_PASSWORD_ENDPOINT, + post(auth::login_with_password), + ) + .route( + auth::LOGIN_WITH_SESSION_TOKEN_ENDPOINT, + post(auth::login_with_session_token), + ) + .route( + auth::GRANTER_LOGIN_VERIFICATION_ENDPOINT, + post(auth::granter_login_verification), + ) + .route(config::APP_CONFIG_ENDPOINT, get(config::application)) + .route(config::SERVER_LIST_ENDPOINT, get(config::server_list)) + .route( + config::VERSIONS_BUNDLE_ENDPOINT, + get(config::versions_bundle), + ) + .route(entry::ACCOUNT_TOKEN_ENDPOINT, post(entry::account_token)) + .route(entry::ACCOUNT_SERVER_ENDPOINT, post(entry::account_server)) + .fallback(errors::not_found); + + let bind_url = format!("{HOST}:{PORT}"); + let http_server = axum_server::bind(bind_url.parse()?); + tracing::info!("SDK Server is listening at {bind_url}"); + + http_server.serve(router.into_make_service()).await?; + Ok(()) +} + +fn init_tracing() -> Result<()> { + #[cfg(target_os = "windows")] + ansi_term::enable_ansi_support().unwrap(); + + env_logger::init_from_env(env_logger::Env::new().default_filter_or("info")); + + let log_filter = EnvFilter::try_from_default_env() + .unwrap_or_else(|_| EnvFilter::try_new("info").unwrap()) + .add_directive("sdkserver=debug".parse().unwrap()); + + tracing::subscriber::set_global_default( + Registry::default() + .with(log_filter) + .with(tracing_subscriber::fmt::Layer::default()), + )?; + + Ok(()) +}