mirror of
https://github.com/redstrate/Kawari.git
synced 2025-06-30 03:37:45 +00:00
Allow building for WebAssembly
This really only allows you to access the packet parsing bits, starting the servers isn't possible for a variety of reasons.
This commit is contained in:
parent
05f909497c
commit
7b8177b27b
5 changed files with 100 additions and 78 deletions
45
Cargo.toml
45
Cargo.toml
|
@ -51,27 +51,13 @@ serde = { version = "1.0", features = ["derive"], default-features = false }
|
|||
serde_json = { version = "1.0", features = ["std"], default-features = false }
|
||||
|
||||
[dependencies]
|
||||
# Used for the web servers
|
||||
axum = { version = "0.8", features = ["json", "tokio", "http1", "form", "query", "multipart"], default-features = false }
|
||||
axum-extra = { version = "0.10", features = ["cookie"], default-features = false }
|
||||
|
||||
# Serialization used in almost every server
|
||||
serde = { version = "1.0", features = ["derive"], default-features = false }
|
||||
serde_json = { version = "1.0", default-features = false }
|
||||
serde_json = { version = "1.0", features = ["std"], default-features = false }
|
||||
serde_yaml_ng = { version = "0.10", default-features = false }
|
||||
|
||||
# Async runtime
|
||||
tokio = { version = "1.45", features = ["macros", "rt", "rt-multi-thread", "io-util"], default-features = false }
|
||||
|
||||
# Logging
|
||||
tracing = { version = "0.1", default-features = false }
|
||||
tracing-subscriber = { version = "0.3", features = ["fmt"], default-features = false }
|
||||
|
||||
# Used currently for SID generation
|
||||
fastrand = { version = "2.3", features = ["std"], default-features = false }
|
||||
|
||||
# HTML templates used in the web servers
|
||||
minijinja = { version = "2.10", features = ["serde", "loader", "multi_template"], default-features = false }
|
||||
|
||||
# Serialization of packets
|
||||
binrw = { version = "0.15", features = ["std"], default-features = false }
|
||||
|
@ -82,12 +68,32 @@ md5 = { version = "0.7", default-features = false }
|
|||
# Used to access game data
|
||||
physis = { git = "https://github.com/redstrate/physis", default-features = false }
|
||||
|
||||
# Used for data persistence
|
||||
rusqlite = { version = "0.36", features = ["bundled"], default-features = false }
|
||||
|
||||
# needed for c-style bitflags
|
||||
bitflags = { version = "2.9", default-features = false }
|
||||
|
||||
# excel sheet data
|
||||
icarus = { git = "https://github.com/redstrate/Icarus", branch = "ver/2025.04.16.0000.0000", features = ["Warp", "Tribe", "ClassJob", "World", "TerritoryType", "Race", "Aetheryte", "EquipSlotCategory", "Action", "WeatherRate", "PlaceName"], default-features = false }
|
||||
|
||||
[target.'cfg(not(target_family = "wasm"))'.dependencies]
|
||||
# Used for the web servers
|
||||
axum = { version = "0.8", features = ["json", "tokio", "http1", "form", "query", "multipart"], default-features = false }
|
||||
axum-extra = { version = "0.10", features = ["cookie"], default-features = false }
|
||||
|
||||
# Async runtime
|
||||
tokio = { version = "1.45", features = ["macros", "rt", "rt-multi-thread", "io-util"], default-features = false }
|
||||
|
||||
# Logging
|
||||
tracing-subscriber = { version = "0.3", features = ["fmt"], default-features = false }
|
||||
|
||||
# Used currently for SID generation
|
||||
fastrand = { version = "2.3", features = ["std"], default-features = false }
|
||||
|
||||
# HTML templates used in the web servers
|
||||
minijinja = { version = "2.10", features = ["serde", "loader", "multi_template"], default-features = false }
|
||||
|
||||
# Used for data persistence
|
||||
rusqlite = { version = "0.36", features = ["bundled"], default-features = false }
|
||||
|
||||
# For server-side scripting
|
||||
mlua = { version = "0.10", features = ["lua54", "vendored", "send", "async", "serialize"], default-features = false }
|
||||
|
||||
|
@ -102,6 +108,3 @@ rkon = { version = "0.1" }
|
|||
|
||||
# For serving static files on the website
|
||||
tower-http = { version = "0.6", features = ["fs", "cors"] }
|
||||
|
||||
# excel sheet data
|
||||
icarus = { git = "https://github.com/redstrate/Icarus", branch = "ver/2025.04.16.0000.0000", features = ["Warp", "Tribe", "ClassJob", "World", "TerritoryType", "Race", "Aetheryte", "EquipSlotCategory", "Action", "WeatherRate", "PlaceName"], default-features = false }
|
||||
|
|
|
@ -16,15 +16,18 @@ pub mod common;
|
|||
pub mod config;
|
||||
|
||||
/// Lobby server-specific code.
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub mod lobby;
|
||||
|
||||
/// World server-specific code.
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub mod world;
|
||||
|
||||
/// Everything packet parsing related.
|
||||
pub mod packet;
|
||||
|
||||
/// Logic server-specific code.
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub mod login;
|
||||
|
||||
/// Patch server-specific code.
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod parsing;
|
||||
pub use parsing::{
|
||||
ConnectionType, PacketHeader, PacketSegment, PacketState, SegmentData, SegmentType,
|
||||
parse_packet, send_keep_alive, send_packet,
|
||||
parse_packet,
|
||||
};
|
||||
|
||||
mod compression;
|
||||
|
@ -15,3 +15,9 @@ pub use ipc::{IpcSegment, ReadWriteIpcSegment};
|
|||
|
||||
/// Bindings for Oodle network compression.
|
||||
pub mod oodle;
|
||||
|
||||
/// Send packet helpers.
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
mod send_helpers;
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub use send_helpers::{send_keep_alive, send_packet};
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
use std::{fs::write, io::Cursor};
|
||||
|
||||
use binrw::{BinRead, BinWrite, binrw};
|
||||
use tokio::{io::AsyncWriteExt, net::TcpStream};
|
||||
|
||||
use crate::{
|
||||
common::{read_string, timestamp_msecs, write_string},
|
||||
|
@ -181,39 +180,6 @@ fn dump(msg: &str, data: &[u8]) {
|
|||
tracing::warn!("{msg} Dumped to packet.bin.");
|
||||
}
|
||||
|
||||
pub async fn send_packet<T: ReadWriteIpcSegment>(
|
||||
socket: &mut TcpStream,
|
||||
state: &mut PacketState,
|
||||
connection_type: ConnectionType,
|
||||
compression_type: CompressionType,
|
||||
segments: &[PacketSegment<T>],
|
||||
) {
|
||||
let (data, uncompressed_size) = compress(state, &compression_type, segments);
|
||||
let size = std::mem::size_of::<PacketHeader>() + data.len();
|
||||
|
||||
let header = PacketHeader {
|
||||
prefix: [0; 16],
|
||||
timestamp: timestamp_msecs(),
|
||||
size: size as u32,
|
||||
connection_type,
|
||||
segment_count: segments.len() as u16,
|
||||
version: 0,
|
||||
compression_type,
|
||||
unk4: 0,
|
||||
uncompressed_size: uncompressed_size as u32,
|
||||
};
|
||||
|
||||
let mut cursor = Cursor::new(Vec::new());
|
||||
header.write_le(&mut cursor).unwrap();
|
||||
std::io::Write::write_all(&mut cursor, &data).unwrap();
|
||||
|
||||
let buffer = cursor.into_inner();
|
||||
|
||||
if let Err(e) = socket.write_all(&buffer).await {
|
||||
tracing::warn!("Failed to send packet: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
// temporary
|
||||
/// State needed for each connection between the client & server, containing various things like the compressor and encryption keys.
|
||||
pub struct PacketState {
|
||||
|
@ -249,28 +215,6 @@ pub fn parse_packet<T: ReadWriteIpcSegment>(
|
|||
}
|
||||
}
|
||||
|
||||
pub async fn send_keep_alive<T: ReadWriteIpcSegment>(
|
||||
socket: &mut TcpStream,
|
||||
state: &mut PacketState,
|
||||
connection_type: ConnectionType,
|
||||
id: u32,
|
||||
timestamp: u32,
|
||||
) {
|
||||
let response_packet: PacketSegment<T> = PacketSegment {
|
||||
segment_type: SegmentType::KeepAliveResponse,
|
||||
data: SegmentData::KeepAliveResponse { id, timestamp },
|
||||
..Default::default()
|
||||
};
|
||||
send_packet(
|
||||
socket,
|
||||
state,
|
||||
connection_type,
|
||||
CompressionType::Uncompressed,
|
||||
&[response_packet],
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::packet::IpcSegment;
|
||||
|
|
66
src/packet/send_helpers.rs
Normal file
66
src/packet/send_helpers.rs
Normal file
|
@ -0,0 +1,66 @@
|
|||
use std::io::Cursor;
|
||||
|
||||
use binrw::BinWrite;
|
||||
use tokio::{io::AsyncWriteExt, net::TcpStream};
|
||||
|
||||
use crate::common::timestamp_msecs;
|
||||
|
||||
use super::{
|
||||
CompressionType, ConnectionType, PacketHeader, PacketSegment, PacketState, ReadWriteIpcSegment,
|
||||
SegmentData, SegmentType, compression::compress,
|
||||
};
|
||||
|
||||
pub async fn send_packet<T: ReadWriteIpcSegment>(
|
||||
socket: &mut TcpStream,
|
||||
state: &mut PacketState,
|
||||
connection_type: ConnectionType,
|
||||
compression_type: CompressionType,
|
||||
segments: &[PacketSegment<T>],
|
||||
) {
|
||||
let (data, uncompressed_size) = compress(state, &compression_type, segments);
|
||||
let size = std::mem::size_of::<PacketHeader>() + data.len();
|
||||
|
||||
let header = PacketHeader {
|
||||
prefix: [0; 16],
|
||||
timestamp: timestamp_msecs(),
|
||||
size: size as u32,
|
||||
connection_type,
|
||||
segment_count: segments.len() as u16,
|
||||
version: 0,
|
||||
compression_type,
|
||||
unk4: 0,
|
||||
uncompressed_size: uncompressed_size as u32,
|
||||
};
|
||||
|
||||
let mut cursor = Cursor::new(Vec::new());
|
||||
header.write_le(&mut cursor).unwrap();
|
||||
std::io::Write::write_all(&mut cursor, &data).unwrap();
|
||||
|
||||
let buffer = cursor.into_inner();
|
||||
|
||||
if let Err(e) = socket.write_all(&buffer).await {
|
||||
tracing::warn!("Failed to send packet: {e}");
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn send_keep_alive<T: ReadWriteIpcSegment>(
|
||||
socket: &mut TcpStream,
|
||||
state: &mut PacketState,
|
||||
connection_type: ConnectionType,
|
||||
id: u32,
|
||||
timestamp: u32,
|
||||
) {
|
||||
let response_packet: PacketSegment<T> = PacketSegment {
|
||||
segment_type: SegmentType::KeepAliveResponse,
|
||||
data: SegmentData::KeepAliveResponse { id, timestamp },
|
||||
..Default::default()
|
||||
};
|
||||
send_packet(
|
||||
socket,
|
||||
state,
|
||||
connection_type,
|
||||
CompressionType::Uncompressed,
|
||||
&[response_packet],
|
||||
)
|
||||
.await;
|
||||
}
|
Loading…
Add table
Reference in a new issue