Split SDK and Dispatch into different servers
This commit is contained in:
parent
9624a07ad2
commit
da466f961b
26 changed files with 363 additions and 191 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1,3 +1,4 @@
|
||||||
target/
|
target/
|
||||||
Cargo.lock
|
Cargo.lock
|
||||||
proto/StarRail.proto
|
proto/StarRail.proto
|
||||||
|
/*.json
|
|
@ -1,5 +1,5 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = ["common", "gameserver", "proto", "sdkserver", "xtask"]
|
members = ["common", "dispatch", "gameserver", "proto", "sdkserver", "xtask"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
|
@ -15,6 +15,8 @@ axum = "0.7.4"
|
||||||
axum-server = "0.6.0"
|
axum-server = "0.6.0"
|
||||||
tower = "0.4.13"
|
tower = "0.4.13"
|
||||||
tower-http = { version = "0.5.2", features = ["normalize-path"] }
|
tower-http = { version = "0.5.2", features = ["normalize-path"] }
|
||||||
|
hyper = { version = "1.3.0", features = [ "client" ] }
|
||||||
|
hyper-util = { version = "0.1.3", features = [ "client-legacy" ] }
|
||||||
|
|
||||||
dirs = "5.0.1"
|
dirs = "5.0.1"
|
||||||
dotenv = "0.15.0"
|
dotenv = "0.15.0"
|
||||||
|
|
16
README.md
16
README.md
|
@ -18,8 +18,9 @@ A Server emulator for the game [`Honkai: Star Rail`](https://hsr.hoyoverse.com/e
|
||||||
```sh
|
```sh
|
||||||
git clone https://git.xeondev.com/reversedrooms/AcheronSR.git
|
git clone https://git.xeondev.com/reversedrooms/AcheronSR.git
|
||||||
cd AcheronSR
|
cd AcheronSR
|
||||||
cargo install --path gameserver
|
cargo build --bin gameserver
|
||||||
cargo install --path sdkserver
|
cargo build --bin dispatch
|
||||||
|
cargo build --bin sdkserver
|
||||||
```
|
```
|
||||||
|
|
||||||
##### Using xtasks (use this if stupid)
|
##### Using xtasks (use this if stupid)
|
||||||
|
@ -43,23 +44,18 @@ page and download the latest release for your platform.
|
||||||
|
|
||||||
To begin using the server, you need to run both the SDK server and the game server.
|
To begin using the server, you need to run both the SDK server and the game server.
|
||||||
|
|
||||||
If you installed from source, Rust's installer should have added .cargo/bin to your
|
|
||||||
path, so simply run the following:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
gameserver
|
|
||||||
sdkserver
|
|
||||||
```
|
|
||||||
|
|
||||||
If you installed from pre-built binaries, navigate to the directory where you downloaded
|
If you installed from pre-built binaries, navigate to the directory where you downloaded
|
||||||
the binaries and either a) double-click on the following executable names or b)
|
the binaries and either a) double-click on the following executable names or b)
|
||||||
run the following in a terminal:
|
run the following in a terminal:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./gameserver
|
./gameserver
|
||||||
|
./dispatch
|
||||||
./sdkserver
|
./sdkserver
|
||||||
```
|
```
|
||||||
|
|
||||||
|
##### Note: the `assets` folder should be in the same directory with the `gameserver`, otherwise it will panic.
|
||||||
|
|
||||||
## Connecting
|
## Connecting
|
||||||
|
|
||||||
[Get 2.2 beta client](https://bhrpg-prod.oss-accelerate.aliyuncs.com/client/beta/20240322124944_scfGE0xJXlWtoJ1r/StarRail_2.1.51.zip),
|
[Get 2.2 beta client](https://bhrpg-prod.oss-accelerate.aliyuncs.com/client/beta/20240322124944_scfGE0xJXlWtoJ1r/StarRail_2.1.51.zip),
|
||||||
|
|
|
@ -4,6 +4,9 @@ edition = "2021"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
ansi_term.workspace = true
|
||||||
|
env_logger.workspace = true
|
||||||
tracing.workspace = true
|
tracing.workspace = true
|
||||||
lazy_static.workspace = true
|
lazy_static.workspace = true
|
||||||
serde.workspace = true
|
serde.workspace = true
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
pub mod data;
|
pub mod data;
|
||||||
|
pub mod logging;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
pub fn load_or_create_config(path: &str, defaults: &str) -> String {
|
pub fn load_or_create_config(path: &str, defaults: &str) -> String {
|
||||||
if let Ok(data) = std::fs::read_to_string(path) {
|
std::fs::read_to_string(path).map_or_else(
|
||||||
data
|
|_| {
|
||||||
} else {
|
std::fs::write(path, defaults).unwrap();
|
||||||
std::fs::write(path, defaults).unwrap();
|
defaults.to_string()
|
||||||
defaults.to_string()
|
},
|
||||||
}
|
|data| data,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
34
dispatch/Cargo.toml
Normal file
34
dispatch/Cargo.toml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
[package]
|
||||||
|
name = "dispatch"
|
||||||
|
edition = "2021"
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
common.workspace = true
|
||||||
|
|
||||||
|
anyhow.workspace = true
|
||||||
|
env_logger.workspace = true
|
||||||
|
|
||||||
|
axum.workspace = true
|
||||||
|
axum-server.workspace = true
|
||||||
|
|
||||||
|
lazy_static.workspace = true
|
||||||
|
|
||||||
|
serde.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
|
||||||
|
tokio.workspace = true
|
||||||
|
tokio-util.workspace = true
|
||||||
|
|
||||||
|
tracing.workspace = true
|
||||||
|
tracing-futures.workspace = true
|
||||||
|
tracing-log.workspace = true
|
||||||
|
tracing-subscriber.workspace = true
|
||||||
|
tracing-bunyan-formatter.workspace = true
|
||||||
|
ansi_term.workspace = true
|
||||||
|
|
||||||
|
prost.workspace = true
|
||||||
|
rbase64.workspace = true
|
||||||
|
proto.workspace = true
|
||||||
|
tower.workspace = true
|
||||||
|
tower-http.workspace = true
|
34
dispatch/dispatch.json
Normal file
34
dispatch/dispatch.json
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
{
|
||||||
|
"http_port": 21041,
|
||||||
|
"game_servers": {
|
||||||
|
"acheron_sr": {
|
||||||
|
"name": "AcheronSR",
|
||||||
|
"title": "AcheronSR",
|
||||||
|
"dispatch_url": "http://127.0.0.1:21041/query_gateway/acheron_sr",
|
||||||
|
"env_type": "2",
|
||||||
|
"gateserver_ip": "127.0.0.1",
|
||||||
|
"gateserver_port": 23301,
|
||||||
|
"gateserver_protocol": "Tcp"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"versions": {
|
||||||
|
"CNBETAWin2.1.51": {
|
||||||
|
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_6744505_89b2f5dc973e",
|
||||||
|
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_6759713_b4e0e740f0da",
|
||||||
|
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_6755976_3c46d7c46e2c",
|
||||||
|
"lua_version": "6755976"
|
||||||
|
},
|
||||||
|
"CNBETAWin2.1.52": {
|
||||||
|
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_6785106_15237df2ef89",
|
||||||
|
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_6787319_5f3f1dae4769",
|
||||||
|
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_6785460_26c4b6c61a8b",
|
||||||
|
"lua_version": "6785460"
|
||||||
|
},
|
||||||
|
"CNBETAWin2.1.53": {
|
||||||
|
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_6828321_72f2df86102b",
|
||||||
|
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_6834225_44836493b261",
|
||||||
|
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_6828764_f749b48347fd",
|
||||||
|
"lua_version": "6828764"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
51
dispatch/src/config.rs
Normal file
51
dispatch/src/config.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use common::util::load_or_create_config;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde_json::from_str;
|
||||||
|
|
||||||
|
const DEFAULT_CONFIG: &str = include_str!("../dispatch.json");
|
||||||
|
|
||||||
|
pub fn init_config() {
|
||||||
|
let _configuration = &*CONFIGURATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct DispatchServerConfiguration {
|
||||||
|
pub http_port: u16,
|
||||||
|
pub game_servers: HashMap<String, GameServerConfig>,
|
||||||
|
pub versions: HashMap<String, VersionConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct VersionConfig {
|
||||||
|
pub asset_bundle_url: String,
|
||||||
|
pub ex_resource_url: String,
|
||||||
|
pub lua_url: String,
|
||||||
|
pub lua_version: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct GameServerConfig {
|
||||||
|
pub name: String,
|
||||||
|
pub title: String,
|
||||||
|
pub dispatch_url: String,
|
||||||
|
pub env_type: String,
|
||||||
|
pub gateserver_ip: String,
|
||||||
|
pub gateserver_port: u16,
|
||||||
|
pub gateserver_protocol: GatewayProtocolType,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Eq, PartialEq)]
|
||||||
|
pub enum GatewayProtocolType {
|
||||||
|
Tcp,
|
||||||
|
Kcp,
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref CONFIGURATION: DispatchServerConfiguration = {
|
||||||
|
let data = load_or_create_config("dispatch.json", DEFAULT_CONFIG);
|
||||||
|
from_str(&data).unwrap()
|
||||||
|
};
|
||||||
|
}
|
85
dispatch/src/handlers.rs
Normal file
85
dispatch/src/handlers.rs
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
use crate::config::*;
|
||||||
|
use axum::extract::{Path, Query};
|
||||||
|
use prost::Message;
|
||||||
|
use proto::{Dispatch, Gateserver, RegionInfo};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
pub const QUERY_DISPATCH_PATH: &str = "/query_dispatch";
|
||||||
|
pub const QUERY_GATEWAY_PATH: &str = "/query_gateway/:region_name";
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn query_dispatch() -> String {
|
||||||
|
let rsp = Dispatch {
|
||||||
|
retcode: 0,
|
||||||
|
region_list: CONFIGURATION
|
||||||
|
.game_servers
|
||||||
|
.iter()
|
||||||
|
.map(|(_, c)| RegionInfo {
|
||||||
|
name: c.name.clone(),
|
||||||
|
title: c.title.clone(),
|
||||||
|
env_type: c.env_type.clone(),
|
||||||
|
dispatch_url: c.dispatch_url.clone(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
rsp.encode(&mut buff).unwrap();
|
||||||
|
|
||||||
|
rbase64::encode(&buff)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Debug)]
|
||||||
|
pub struct QueryGatewayParameters {
|
||||||
|
pub version: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn query_gateway(
|
||||||
|
Path(region_name): Path<String>,
|
||||||
|
parameters: Query<QueryGatewayParameters>,
|
||||||
|
) -> String {
|
||||||
|
let rsp = if let Some(server_config) = CONFIGURATION.game_servers.get(®ion_name) {
|
||||||
|
if let Some(version_config) = CONFIGURATION.versions.get(¶meters.version) {
|
||||||
|
Gateserver {
|
||||||
|
retcode: 0,
|
||||||
|
ip: server_config.gateserver_ip.clone(),
|
||||||
|
port: server_config.gateserver_port as u32,
|
||||||
|
asset_bundle_url: version_config.asset_bundle_url.clone(),
|
||||||
|
ex_resource_url: version_config.ex_resource_url.clone(),
|
||||||
|
lua_url: version_config.lua_url.clone(),
|
||||||
|
lua_version: version_config.lua_version.clone(),
|
||||||
|
ifix_version: String::from("0"),
|
||||||
|
jblkncaoiao: true,
|
||||||
|
hjdjakjkdbi: true,
|
||||||
|
ldknmcpffim: true,
|
||||||
|
feehapamfci: true,
|
||||||
|
eebfeohfpph: true,
|
||||||
|
dfmjjcfhfea: true,
|
||||||
|
najikcgjgan: true,
|
||||||
|
giddjofkndm: true,
|
||||||
|
use_tcp: server_config.gateserver_protocol == GatewayProtocolType::Tcp,
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Gateserver {
|
||||||
|
retcode: 9,
|
||||||
|
msg: format!("forbidden version: {} or invalid bind", parameters.version),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Gateserver {
|
||||||
|
retcode: 9,
|
||||||
|
msg: format!("server config for {region_name} not found"),
|
||||||
|
..Default::default()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
rsp.encode(&mut buff).unwrap();
|
||||||
|
|
||||||
|
rbase64::encode(&buff)
|
||||||
|
}
|
35
dispatch/src/main.rs
Normal file
35
dispatch/src/main.rs
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use axum::{extract::Request, routing::get, Router, ServiceExt};
|
||||||
|
use common::logging::init_tracing;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
use tower::Layer;
|
||||||
|
use tower_http::normalize_path::NormalizePathLayer;
|
||||||
|
use tracing::Level;
|
||||||
|
|
||||||
|
mod config;
|
||||||
|
mod handlers;
|
||||||
|
|
||||||
|
use config::{init_config, CONFIGURATION};
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
init_tracing();
|
||||||
|
init_config();
|
||||||
|
|
||||||
|
let span = tracing::span!(Level::DEBUG, "main");
|
||||||
|
let _ = span.enter();
|
||||||
|
|
||||||
|
let app = Router::new()
|
||||||
|
.route(handlers::QUERY_DISPATCH_PATH, get(handlers::query_dispatch))
|
||||||
|
.route(handlers::QUERY_GATEWAY_PATH, get(handlers::query_gateway));
|
||||||
|
|
||||||
|
let app = NormalizePathLayer::trim_trailing_slash().layer(app);
|
||||||
|
|
||||||
|
let addr = format!("0.0.0.0:{}", CONFIGURATION.http_port);
|
||||||
|
let server = TcpListener::bind(&addr).await?;
|
||||||
|
|
||||||
|
tracing::info!("dispatch is listening at {addr}");
|
||||||
|
axum::serve(server, ServiceExt::<Request>::into_make_service(app)).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -1,13 +1,12 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
mod game;
|
mod game;
|
||||||
mod logging;
|
|
||||||
mod net;
|
mod net;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
use common::data::init_assets;
|
use common::data::init_assets;
|
||||||
|
use common::logging::init_tracing;
|
||||||
use game::init_config;
|
use game::init_config;
|
||||||
use logging::init_tracing;
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use common::log_error;
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tracing::{info_span, Instrument};
|
use tracing::{info_span, Instrument};
|
||||||
|
|
||||||
use crate::{log_error, net::PlayerSession};
|
use crate::net::PlayerSession;
|
||||||
|
|
||||||
pub async fn listen(host: &str, port: u16) -> Result<()> {
|
pub async fn listen(host: &str, port: u16) -> Result<()> {
|
||||||
let listener = TcpListener::bind(format!("{host}:{port}")).await?;
|
let listener = TcpListener::bind(format!("{host}:{port}")).await?;
|
||||||
|
|
|
@ -11,6 +11,8 @@ env_logger.workspace = true
|
||||||
|
|
||||||
axum.workspace = true
|
axum.workspace = true
|
||||||
axum-server.workspace = true
|
axum-server.workspace = true
|
||||||
|
hyper.workspace = true
|
||||||
|
hyper-util.workspace = true
|
||||||
|
|
||||||
dirs.workspace = true
|
dirs.workspace = true
|
||||||
dotenv.workspace = true
|
dotenv.workspace = true
|
||||||
|
@ -30,8 +32,6 @@ tracing-subscriber.workspace = true
|
||||||
tracing-bunyan-formatter.workspace = true
|
tracing-bunyan-formatter.workspace = true
|
||||||
ansi_term.workspace = true
|
ansi_term.workspace = true
|
||||||
|
|
||||||
prost.workspace = true
|
|
||||||
rbase64.workspace = true
|
|
||||||
proto.workspace = true
|
|
||||||
tower.workspace = true
|
tower.workspace = true
|
||||||
tower-http.workspace = true
|
tower-http.workspace = true
|
||||||
|
|
||||||
|
|
4
sdkserver/sdkserver.json
Normal file
4
sdkserver/sdkserver.json
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
{
|
||||||
|
"http_port": 21000,
|
||||||
|
"dispatch_endpoint": "http://127.0.0.1:21041"
|
||||||
|
}
|
23
sdkserver/src/config.rs
Normal file
23
sdkserver/src/config.rs
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
use common::util::load_or_create_config;
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde_json::from_str;
|
||||||
|
|
||||||
|
const DEFAULT_CONFIG: &str = include_str!("../sdkserver.json");
|
||||||
|
|
||||||
|
pub fn init_config() {
|
||||||
|
let _configuration = &*CONFIGURATION;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct SDKServerConfiguration {
|
||||||
|
pub http_port: u16,
|
||||||
|
pub dispatch_endpoint: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref CONFIGURATION: SDKServerConfiguration = {
|
||||||
|
let data = load_or_create_config("sdkserver.json", DEFAULT_CONFIG);
|
||||||
|
from_str(&data).unwrap()
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,7 +0,0 @@
|
||||||
mod version_config;
|
|
||||||
|
|
||||||
pub use version_config::INSTANCE as versions;
|
|
||||||
|
|
||||||
pub fn init_config() {
|
|
||||||
tracing::info!("loaded {} version configs", versions.len());
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
use common::util::load_or_create_config;
|
|
||||||
use lazy_static::lazy_static;
|
|
||||||
use serde::Deserialize;
|
|
||||||
use serde_json::from_str;
|
|
||||||
|
|
||||||
const DEFAULT_VERSIONS: &str = include_str!("../../versions.json");
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
pub struct VersionConfig {
|
|
||||||
pub asset_bundle_url: String,
|
|
||||||
pub ex_resource_url: String,
|
|
||||||
pub lua_url: String,
|
|
||||||
pub lua_version: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref INSTANCE: HashMap<String, VersionConfig> = {
|
|
||||||
let data = load_or_create_config("versions.json", DEFAULT_VERSIONS);
|
|
||||||
from_str(&data).unwrap()
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,29 +0,0 @@
|
||||||
#[macro_export]
|
|
||||||
macro_rules! log_error {
|
|
||||||
($e:expr) => {
|
|
||||||
if let Err(e) = $e {
|
|
||||||
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
($context:expr, $e:expr $(,)?) => {
|
|
||||||
if let Err(e) = $e {
|
|
||||||
let e = format!("{:?}", ::anyhow::anyhow!(e).context($context));
|
|
||||||
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
($ok_context:expr, $err_context:expr, $e:expr $(,)?) => {
|
|
||||||
if let Err(e) = $e {
|
|
||||||
let e = format!("{:?}", ::anyhow::anyhow!(e).context($err_context));
|
|
||||||
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
|
||||||
} else {
|
|
||||||
tracing::info!($ok_context);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn init_tracing() {
|
|
||||||
#[cfg(target_os = "windows")]
|
|
||||||
ansi_term::enable_ansi_support().unwrap();
|
|
||||||
|
|
||||||
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
|
||||||
}
|
|
|
@ -1,21 +1,24 @@
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
use axum::body::Body;
|
||||||
use axum::extract::Request;
|
use axum::extract::Request;
|
||||||
use axum::routing::{get, post};
|
use axum::routing::{get, post};
|
||||||
use axum::{Router, ServiceExt};
|
use axum::{Router, ServiceExt};
|
||||||
use services::{auth, dispatch, errors};
|
use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor};
|
||||||
|
use services::{auth, errors};
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
use tower::Layer;
|
use tower::Layer;
|
||||||
use tower_http::normalize_path::NormalizePathLayer;
|
use tower_http::normalize_path::NormalizePathLayer;
|
||||||
use tracing::Level;
|
use tracing::Level;
|
||||||
|
|
||||||
|
type Client = hyper_util::client::legacy::Client<HttpConnector, Body>;
|
||||||
|
|
||||||
mod config;
|
mod config;
|
||||||
mod logging;
|
|
||||||
mod services;
|
mod services;
|
||||||
|
|
||||||
use config::init_config;
|
use common::logging::init_tracing;
|
||||||
use logging::init_tracing;
|
|
||||||
|
|
||||||
const PORT: u16 = 21000;
|
use config::{init_config, CONFIGURATION};
|
||||||
|
use services::reverse_proxy;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<()> {
|
async fn main() -> Result<()> {
|
||||||
|
@ -25,14 +28,16 @@ async fn main() -> Result<()> {
|
||||||
let span = tracing::span!(Level::DEBUG, "main");
|
let span = tracing::span!(Level::DEBUG, "main");
|
||||||
let _ = span.enter();
|
let _ = span.enter();
|
||||||
|
|
||||||
|
// For dispatch reverse proxy
|
||||||
|
let client: Client =
|
||||||
|
hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new())
|
||||||
|
.build(HttpConnector::new());
|
||||||
|
|
||||||
let app = Router::new()
|
let app = Router::new()
|
||||||
|
.route("/query_dispatch", get(reverse_proxy::forward_to_dispatch))
|
||||||
.route(
|
.route(
|
||||||
dispatch::QUERY_DISPATCH_ENDPOINT,
|
"/query_gateway/:region_name",
|
||||||
get(dispatch::query_dispatch),
|
get(reverse_proxy::forward_to_dispatch),
|
||||||
)
|
|
||||||
.route(
|
|
||||||
dispatch::QUERY_GATEWAY_ENDPOINT,
|
|
||||||
get(dispatch::query_gateway),
|
|
||||||
)
|
)
|
||||||
.route(auth::RISKY_API_CHECK_ENDPOINT, post(auth::risky_api_check))
|
.route(auth::RISKY_API_CHECK_ENDPOINT, post(auth::risky_api_check))
|
||||||
.route(
|
.route(
|
||||||
|
@ -47,11 +52,12 @@ async fn main() -> Result<()> {
|
||||||
auth::GRANTER_LOGIN_VERIFICATION_ENDPOINT,
|
auth::GRANTER_LOGIN_VERIFICATION_ENDPOINT,
|
||||||
post(auth::granter_login_verification),
|
post(auth::granter_login_verification),
|
||||||
)
|
)
|
||||||
.fallback(errors::not_found);
|
.fallback(errors::not_found)
|
||||||
|
.with_state(client);
|
||||||
|
|
||||||
let app = NormalizePathLayer::trim_trailing_slash().layer(app);
|
let app = NormalizePathLayer::trim_trailing_slash().layer(app);
|
||||||
|
|
||||||
let addr = format!("0.0.0.0:{PORT}");
|
let addr = format!("0.0.0.0:{}", CONFIGURATION.http_port);
|
||||||
let server = TcpListener::bind(&addr).await?;
|
let server = TcpListener::bind(&addr).await?;
|
||||||
|
|
||||||
tracing::info!("sdkserver is listening at {addr}");
|
tracing::info!("sdkserver is listening at {addr}");
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
use crate::config::versions;
|
|
||||||
use axum::extract::Query;
|
|
||||||
use prost::Message;
|
|
||||||
use proto::{Dispatch, Gateserver, RegionInfo};
|
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
pub const QUERY_DISPATCH_ENDPOINT: &str = "/query_dispatch";
|
|
||||||
pub const QUERY_GATEWAY_ENDPOINT: &str = "/query_gateway";
|
|
||||||
|
|
||||||
#[tracing::instrument]
|
|
||||||
pub async fn query_dispatch() -> String {
|
|
||||||
let rsp = Dispatch {
|
|
||||||
retcode: 0,
|
|
||||||
region_list: vec![RegionInfo {
|
|
||||||
name: String::from("AcheronSR"),
|
|
||||||
title: String::from("AcheronSR"),
|
|
||||||
env_type: String::from("2"),
|
|
||||||
dispatch_url: String::from("http://127.0.0.1:21000/query_gateway"),
|
|
||||||
..Default::default()
|
|
||||||
}],
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut buff = Vec::new();
|
|
||||||
rsp.encode(&mut buff).unwrap();
|
|
||||||
|
|
||||||
rbase64::encode(&buff)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
|
||||||
pub struct QueryGatewayParameters {
|
|
||||||
pub version: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tracing::instrument]
|
|
||||||
pub async fn query_gateway(parameters: Query<QueryGatewayParameters>) -> String {
|
|
||||||
let rsp = if let Some(config) = versions.get(¶meters.version) {
|
|
||||||
Gateserver {
|
|
||||||
retcode: 0,
|
|
||||||
ip: String::from("127.0.0.1"),
|
|
||||||
port: 23301,
|
|
||||||
asset_bundle_url: config.asset_bundle_url.clone(),
|
|
||||||
ex_resource_url: config.ex_resource_url.clone(),
|
|
||||||
lua_url: config.lua_url.clone(),
|
|
||||||
lua_version: config.lua_version.clone(),
|
|
||||||
ifix_version: String::from("0"),
|
|
||||||
jblkncaoiao: true,
|
|
||||||
hjdjakjkdbi: true,
|
|
||||||
ldknmcpffim: true,
|
|
||||||
feehapamfci: true,
|
|
||||||
eebfeohfpph: true,
|
|
||||||
dfmjjcfhfea: true,
|
|
||||||
najikcgjgan: true,
|
|
||||||
giddjofkndm: true,
|
|
||||||
fbnbbembcgn: false,
|
|
||||||
dedgfjhbnok: false,
|
|
||||||
use_tcp: true,
|
|
||||||
linlaijbboh: false,
|
|
||||||
ahmbfbkhmgh: false,
|
|
||||||
nmdccehcdcc: false,
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Gateserver {
|
|
||||||
retcode: 9,
|
|
||||||
msg: format!("forbidden version: {} or invalid bind", parameters.version),
|
|
||||||
..Default::default()
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut buff = Vec::new();
|
|
||||||
rsp.encode(&mut buff).unwrap();
|
|
||||||
|
|
||||||
rbase64::encode(&buff)
|
|
||||||
}
|
|
|
@ -1,3 +1,3 @@
|
||||||
pub mod auth;
|
pub mod auth;
|
||||||
pub mod dispatch;
|
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
|
pub mod reverse_proxy;
|
||||||
|
|
33
sdkserver/src/services/reverse_proxy.rs
Normal file
33
sdkserver/src/services/reverse_proxy.rs
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
use axum::{
|
||||||
|
body::Body,
|
||||||
|
extract::{Request, State},
|
||||||
|
http::uri::{PathAndQuery, Uri},
|
||||||
|
response::{IntoResponse, Response},
|
||||||
|
};
|
||||||
|
use hyper::StatusCode;
|
||||||
|
use hyper_util::client::legacy::connect::HttpConnector;
|
||||||
|
|
||||||
|
use crate::config::CONFIGURATION;
|
||||||
|
|
||||||
|
type Client = hyper_util::client::legacy::Client<HttpConnector, Body>;
|
||||||
|
|
||||||
|
pub async fn forward_to_dispatch(
|
||||||
|
State(client): State<Client>,
|
||||||
|
mut req: Request,
|
||||||
|
) -> Result<Response, StatusCode> {
|
||||||
|
let path = req.uri().path();
|
||||||
|
let path_query = req
|
||||||
|
.uri()
|
||||||
|
.path_and_query()
|
||||||
|
.map_or(path, PathAndQuery::as_str);
|
||||||
|
|
||||||
|
let uri = format!("{}{}", CONFIGURATION.dispatch_endpoint, path_query);
|
||||||
|
|
||||||
|
*req.uri_mut() = Uri::try_from(uri).unwrap();
|
||||||
|
|
||||||
|
Ok(client
|
||||||
|
.request(req)
|
||||||
|
.await
|
||||||
|
.map_err(|_| StatusCode::BAD_REQUEST)?
|
||||||
|
.into_response())
|
||||||
|
}
|
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"CNBETAWin2.1.51": {
|
|
||||||
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_6744505_89b2f5dc973e",
|
|
||||||
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_6759713_b4e0e740f0da",
|
|
||||||
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_6755976_3c46d7c46e2c",
|
|
||||||
"lua_version": "6755976"
|
|
||||||
},
|
|
||||||
"CNBETAWin2.1.52": {
|
|
||||||
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_6785106_15237df2ef89",
|
|
||||||
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_6787319_5f3f1dae4769",
|
|
||||||
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_6785460_26c4b6c61a8b",
|
|
||||||
"lua_version": "6785460"
|
|
||||||
},
|
|
||||||
"CNBETAWin2.1.53": {
|
|
||||||
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_6828321_72f2df86102b",
|
|
||||||
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_6834225_44836493b261",
|
|
||||||
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_6828764_f749b48347fd",
|
|
||||||
"lua_version": "6828764"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -36,6 +36,7 @@ fn spawn_servers(release: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
Ok::<(), io::Error>(())
|
Ok::<(), io::Error>(())
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let tx2 = tx.clone();
|
||||||
let handle2 = thread::spawn(move || {
|
let handle2 = thread::spawn(move || {
|
||||||
let mut sdkserver = Command::new("cargo")
|
let mut sdkserver = Command::new("cargo")
|
||||||
.arg("run")
|
.arg("run")
|
||||||
|
@ -46,6 +47,21 @@ fn spawn_servers(release: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
.expect("failed to start sdkserver");
|
.expect("failed to start sdkserver");
|
||||||
|
|
||||||
let _ = sdkserver.wait()?;
|
let _ = sdkserver.wait()?;
|
||||||
|
tx2.send(()).expect("failed to send completion signal");
|
||||||
|
|
||||||
|
Ok::<(), io::Error>(())
|
||||||
|
});
|
||||||
|
|
||||||
|
let handle3 = thread::spawn(move || {
|
||||||
|
let mut dispatch = Command::new("cargo")
|
||||||
|
.arg("run")
|
||||||
|
.arg("--bin")
|
||||||
|
.arg("dispatch")
|
||||||
|
.args(if release { vec!["--release"] } else { vec![] })
|
||||||
|
.spawn()
|
||||||
|
.expect("failed to start dispatch");
|
||||||
|
|
||||||
|
let _ = dispatch.wait()?;
|
||||||
tx.send(()).expect("failed to send completion signal");
|
tx.send(()).expect("failed to send completion signal");
|
||||||
|
|
||||||
Ok::<(), io::Error>(())
|
Ok::<(), io::Error>(())
|
||||||
|
@ -55,6 +71,7 @@ fn spawn_servers(release: bool) -> Result<(), Box<dyn std::error::Error>> {
|
||||||
|
|
||||||
handle1.join().expect("failed to join gameserver thread")?;
|
handle1.join().expect("failed to join gameserver thread")?;
|
||||||
handle2.join().expect("failed to join sdkserver thread")?;
|
handle2.join().expect("failed to join sdkserver thread")?;
|
||||||
|
handle3.join().expect("failed to join dispatch thread")?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue